summaryrefslogtreecommitdiff
path: root/redfish-core/lib
diff options
context:
space:
mode:
Diffstat (limited to 'redfish-core/lib')
-rw-r--r--redfish-core/lib/account_service.hpp1130
-rw-r--r--redfish-core/lib/bios.hpp14
-rw-r--r--redfish-core/lib/cable.hpp165
-rw-r--r--redfish-core/lib/certificate_service.hpp493
-rw-r--r--redfish-core/lib/chassis.hpp483
-rw-r--r--redfish-core/lib/ethernet.hpp1027
-rw-r--r--redfish-core/lib/event_service.hpp1160
-rw-r--r--redfish-core/lib/eventservice_sse.hpp26
-rw-r--r--redfish-core/lib/fabric_adapters.hpp198
-rw-r--r--redfish-core/lib/fan.hpp258
-rw-r--r--redfish-core/lib/hypervisor_system.hpp605
-rw-r--r--redfish-core/lib/led.hpp215
-rw-r--r--redfish-core/lib/log_services.hpp4178
-rw-r--r--redfish-core/lib/manager_diagnostic_data.hpp4
-rw-r--r--redfish-core/lib/manager_logservices_journal.hpp655
-rw-r--r--redfish-core/lib/managers.hpp2198
-rw-r--r--redfish-core/lib/memory.hpp310
-rw-r--r--redfish-core/lib/message_registries.hpp34
-rw-r--r--redfish-core/lib/metric_report.hpp111
-rw-r--r--redfish-core/lib/metric_report_definition.hpp809
-rw-r--r--redfish-core/lib/network_protocol.hpp199
-rw-r--r--redfish-core/lib/odata.hpp56
-rw-r--r--redfish-core/lib/pcie.hpp409
-rw-r--r--redfish-core/lib/pcie_slots.hpp23
-rw-r--r--redfish-core/lib/power.hpp58
-rw-r--r--redfish-core/lib/power_subsystem.hpp5
-rw-r--r--redfish-core/lib/power_supply.hpp472
-rw-r--r--redfish-core/lib/processor.hpp1230
-rw-r--r--redfish-core/lib/redfish_sessions.hpp67
-rw-r--r--redfish-core/lib/redfish_util.hpp298
-rw-r--r--redfish-core/lib/redfish_v1.hpp148
-rw-r--r--redfish-core/lib/roles.hpp157
-rw-r--r--redfish-core/lib/sensors.hpp2299
-rw-r--r--redfish-core/lib/service_root.hpp26
-rw-r--r--redfish-core/lib/storage.hpp642
-rw-r--r--redfish-core/lib/systems.hpp1689
-rw-r--r--redfish-core/lib/systems_logservices_hostlogger.hpp241
-rw-r--r--redfish-core/lib/systems_logservices_postcodes.hpp615
-rw-r--r--redfish-core/lib/task.hpp454
-rw-r--r--redfish-core/lib/telemetry_service.hpp83
-rw-r--r--redfish-core/lib/thermal.hpp122
-rw-r--r--redfish-core/lib/thermal_metrics.hpp19
-rw-r--r--redfish-core/lib/thermal_subsystem.hpp5
-rw-r--r--redfish-core/lib/trigger.hpp175
-rw-r--r--redfish-core/lib/update_service.hpp527
-rw-r--r--redfish-core/lib/virtual_media.hpp364
46 files changed, 12434 insertions, 12022 deletions
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 05cfbe762d..8bb746eda8 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -1,21 +1,22 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
+#include "boost_formatters.hpp"
#include "certificate_service.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
@@ -23,6 +24,7 @@
#include "persistent_data.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
+#include "sessions.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
@@ -175,10 +177,9 @@ inline bool translateUserGroup(const std::vector<std::string>& userGroups,
*
* @return true if Account Types mapped to User Groups, false otherwise.
*/
-inline bool
- getUserGroupFromAccountType(crow::Response& res,
- const std::vector<std::string>& accountTypes,
- std::vector<std::string>& userGroups)
+inline bool getUserGroupFromAccountType(
+ crow::Response& res, const std::vector<std::string>& accountTypes,
+ std::vector<std::string>& userGroups)
{
// Need both Redfish and WebUI Account Types to map to 'redfish' User Group
bool redfishType = false;
@@ -383,24 +384,25 @@ inline void handleRoleMapPatch(
crow::connections::systemBus->async_method_call(
[asyncResp, roleMapObjData, serverType,
index](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue[serverType]["RemoteRoleMapping"]
- [index] = nullptr;
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res
+ .jsonValue[serverType]["RemoteRoleMapping"][index] =
+ nullptr;
+ },
ldapDbusService, roleMapObjData[index].first,
"xyz.openbmc_project.Object.Delete", "Delete");
}
else
{
BMCWEB_LOG_ERROR("Can't delete the object");
- messages::propertyValueTypeError(asyncResp->res, "null",
- "RemoteRoleMapping/" +
- std::to_string(index));
+ messages::propertyValueTypeError(
+ asyncResp->res, "null",
+ "RemoteRoleMapping/" + std::to_string(index));
return;
}
}
@@ -439,12 +441,21 @@ inline void handleRoleMapPatch(
// If "LocalRole" info is provided
if (localRole)
{
+ std::string priv = getPrivilegeFromRoleId(*localRole);
+ if (priv.empty())
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, *localRole,
+ std::format("RemoteRoleMapping/{}/LocalRole",
+ index));
+ return;
+ }
setDbusProperty(
asyncResp,
std::format("RemoteRoleMapping/{}/LocalRole", index),
ldapDbusService, roleMapObjData[index].first,
"xyz.openbmc_project.User.PrivilegeMapperEntry",
- "Privilege", *localRole);
+ "Privilege", priv);
}
}
// Create a new RoleMapping Object.
@@ -452,8 +463,8 @@ inline void handleRoleMapPatch(
{
BMCWEB_LOG_DEBUG(
"setRoleMappingProperties: Creating new Object");
- std::string pathString = "RemoteRoleMapping/" +
- std::to_string(index);
+ std::string pathString =
+ "RemoteRoleMapping/" + std::to_string(index);
if (!localRole)
{
@@ -484,20 +495,20 @@ inline void handleRoleMapPatch(
crow::connections::systemBus->async_method_call(
[asyncResp, serverType, localRole,
remoteGroup](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json& remoteRoleJson =
- asyncResp->res
- .jsonValue[serverType]["RemoteRoleMapping"];
- nlohmann::json::object_t roleMapEntry;
- roleMapEntry["LocalRole"] = *localRole;
- roleMapEntry["RemoteGroup"] = *remoteGroup;
- remoteRoleJson.emplace_back(std::move(roleMapEntry));
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& remoteRoleJson =
+ asyncResp->res
+ .jsonValue[serverType]["RemoteRoleMapping"];
+ nlohmann::json::object_t roleMapEntry;
+ roleMapEntry["LocalRole"] = *localRole;
+ roleMapEntry["RemoteGroup"] = *remoteGroup;
+ remoteRoleJson.emplace_back(std::move(roleMapEntry));
+ },
ldapDbusService, dbusObjectPath, ldapPrivMapperInterface,
"Create", *remoteGroup,
getPrivilegeFromRoleId(std::move(*localRole)));
@@ -511,8 +522,8 @@ inline void handleRoleMapPatch(
* into JSON
*/
template <typename CallbackFunc>
-inline void getLDAPConfigData(const std::string& ldapType,
- CallbackFunc&& callback)
+inline void
+ getLDAPConfigData(const std::string& ldapType, CallbackFunc&& callback)
{
constexpr std::array<std::string_view, 2> interfaces = {
ldapEnableInterface, ldapConfigInterface};
@@ -522,156 +533,165 @@ inline void getLDAPConfigData(const std::string& ldapType,
[callback = std::forward<CallbackFunc>(callback),
ldapType](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& resp) mutable {
- if (ec || resp.empty())
- {
- BMCWEB_LOG_WARNING(
- "DBUS response error during getting of service name: {}", ec);
- LDAPConfigData empty{};
- callback(false, empty, ldapType);
- return;
- }
- std::string service = resp.begin()->first;
- sdbusplus::message::object_path path(ldapRootObject);
- dbus::utility::getManagedObjects(
- service, path,
- [callback, ldapType](
- const boost::system::error_code& ec2,
- const dbus::utility::ManagedObjectType& ldapObjects) mutable {
- LDAPConfigData confData{};
- if (ec2)
+ if (ec || resp.empty())
{
- callback(false, confData, ldapType);
- BMCWEB_LOG_WARNING("D-Bus responses error: {}", ec2);
+ BMCWEB_LOG_WARNING(
+ "DBUS response error during getting of service name: {}",
+ ec);
+ LDAPConfigData empty{};
+ callback(false, empty, ldapType);
return;
}
+ std::string service = resp.begin()->first;
+ sdbusplus::message::object_path path(ldapRootObject);
+ dbus::utility::getManagedObjects(
+ service, path,
+ [callback, ldapType](const boost::system::error_code& ec2,
+ const dbus::utility::ManagedObjectType&
+ ldapObjects) mutable {
+ LDAPConfigData confData{};
+ if (ec2)
+ {
+ callback(false, confData, ldapType);
+ BMCWEB_LOG_WARNING("D-Bus responses error: {}", ec2);
+ return;
+ }
- std::string ldapDbusType;
- std::string searchString;
-
- if (ldapType == "LDAP")
- {
- ldapDbusType =
- "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap";
- searchString = "openldap";
- }
- else if (ldapType == "ActiveDirectory")
- {
- ldapDbusType =
- "xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory";
- searchString = "active_directory";
- }
- else
- {
- BMCWEB_LOG_ERROR("Can't get the DbusType for the given type={}",
- ldapType);
- callback(false, confData, ldapType);
- return;
- }
-
- std::string ldapEnableInterfaceStr = ldapEnableInterface;
- std::string ldapConfigInterfaceStr = ldapConfigInterface;
+ std::string ldapDbusType;
+ std::string searchString;
- for (const auto& object : ldapObjects)
- {
- // let's find the object whose ldap type is equal to the
- // given type
- if (object.first.str.find(searchString) == std::string::npos)
- {
- continue;
- }
-
- for (const auto& interface : object.second)
- {
- if (interface.first == ldapEnableInterfaceStr)
+ if (ldapType == "LDAP")
{
- // rest of the properties are string.
- for (const auto& property : interface.second)
- {
- if (property.first == "Enabled")
- {
- const bool* value =
- std::get_if<bool>(&property.second);
- if (value == nullptr)
- {
- continue;
- }
- confData.serviceEnabled = *value;
- break;
- }
- }
+ ldapDbusType =
+ "xyz.openbmc_project.User.Ldap.Config.Type.OpenLdap";
+ searchString = "openldap";
}
- else if (interface.first == ldapConfigInterfaceStr)
+ else if (ldapType == "ActiveDirectory")
{
- for (const auto& property : interface.second)
- {
- const std::string* strValue =
- std::get_if<std::string>(&property.second);
- if (strValue == nullptr)
- {
- continue;
- }
- if (property.first == "LDAPServerURI")
- {
- confData.uri = *strValue;
- }
- else if (property.first == "LDAPBindDN")
- {
- confData.bindDN = *strValue;
- }
- else if (property.first == "LDAPBaseDN")
- {
- confData.baseDN = *strValue;
- }
- else if (property.first == "LDAPSearchScope")
- {
- confData.searchScope = *strValue;
- }
- else if (property.first == "GroupNameAttribute")
- {
- confData.groupAttribute = *strValue;
- }
- else if (property.first == "UserNameAttribute")
- {
- confData.userNameAttribute = *strValue;
- }
- else if (property.first == "LDAPType")
- {
- confData.serverType = *strValue;
- }
- }
+ ldapDbusType =
+ "xyz.openbmc_project.User.Ldap.Config.Type.ActiveDirectory";
+ searchString = "active_directory";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR(
+ "Can't get the DbusType for the given type={}",
+ ldapType);
+ callback(false, confData, ldapType);
+ return;
}
- else if (interface.first ==
- "xyz.openbmc_project.User.PrivilegeMapperEntry")
+
+ std::string ldapEnableInterfaceStr = ldapEnableInterface;
+ std::string ldapConfigInterfaceStr = ldapConfigInterface;
+
+ for (const auto& object : ldapObjects)
{
- LDAPRoleMapData roleMapData{};
- for (const auto& property : interface.second)
+ // let's find the object whose ldap type is equal to the
+ // given type
+ if (object.first.str.find(searchString) ==
+ std::string::npos)
{
- const std::string* strValue =
- std::get_if<std::string>(&property.second);
+ continue;
+ }
- if (strValue == nullptr)
+ for (const auto& interface : object.second)
+ {
+ if (interface.first == ldapEnableInterfaceStr)
{
- continue;
+ // rest of the properties are string.
+ for (const auto& property : interface.second)
+ {
+ if (property.first == "Enabled")
+ {
+ const bool* value =
+ std::get_if<bool>(&property.second);
+ if (value == nullptr)
+ {
+ continue;
+ }
+ confData.serviceEnabled = *value;
+ break;
+ }
+ }
}
-
- if (property.first == "GroupName")
+ else if (interface.first == ldapConfigInterfaceStr)
{
- roleMapData.groupName = *strValue;
+ for (const auto& property : interface.second)
+ {
+ const std::string* strValue =
+ std::get_if<std::string>(
+ &property.second);
+ if (strValue == nullptr)
+ {
+ continue;
+ }
+ if (property.first == "LDAPServerURI")
+ {
+ confData.uri = *strValue;
+ }
+ else if (property.first == "LDAPBindDN")
+ {
+ confData.bindDN = *strValue;
+ }
+ else if (property.first == "LDAPBaseDN")
+ {
+ confData.baseDN = *strValue;
+ }
+ else if (property.first ==
+ "LDAPSearchScope")
+ {
+ confData.searchScope = *strValue;
+ }
+ else if (property.first ==
+ "GroupNameAttribute")
+ {
+ confData.groupAttribute = *strValue;
+ }
+ else if (property.first ==
+ "UserNameAttribute")
+ {
+ confData.userNameAttribute = *strValue;
+ }
+ else if (property.first == "LDAPType")
+ {
+ confData.serverType = *strValue;
+ }
+ }
}
- else if (property.first == "Privilege")
+ else if (
+ interface.first ==
+ "xyz.openbmc_project.User.PrivilegeMapperEntry")
{
- roleMapData.privilege = *strValue;
+ LDAPRoleMapData roleMapData{};
+ for (const auto& property : interface.second)
+ {
+ const std::string* strValue =
+ std::get_if<std::string>(
+ &property.second);
+
+ if (strValue == nullptr)
+ {
+ continue;
+ }
+
+ if (property.first == "GroupName")
+ {
+ roleMapData.groupName = *strValue;
+ }
+ else if (property.first == "Privilege")
+ {
+ roleMapData.privilege = *strValue;
+ }
+ }
+
+ confData.groupRoleList.emplace_back(
+ object.first.str, roleMapData);
}
}
-
- confData.groupRoleList.emplace_back(object.first.str,
- roleMapData);
}
- }
- }
- callback(true, confData, ldapType);
+ callback(true, confData, ldapType);
+ });
});
- });
}
/**
@@ -764,17 +784,17 @@ inline void
server(openLDAP/ActiveDirectory)
*/
-inline void
- handleUserNameAttrPatch(const std::string& userNameAttribute,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& ldapServerElementName,
- const std::string& ldapConfigObject)
+inline void handleUserNameAttrPatch(
+ const std::string& userNameAttribute,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& ldapServerElementName,
+ const std::string& ldapConfigObject)
{
- setDbusProperty(asyncResp,
- ldapServerElementName +
- "LDAPService/SearchSettings/UsernameAttribute",
- ldapDbusService, ldapConfigObject, ldapConfigInterface,
- "UserNameAttribute", userNameAttribute);
+ setDbusProperty(
+ asyncResp,
+ ldapServerElementName + "LDAPService/SearchSettings/UsernameAttribute",
+ ldapDbusService, ldapConfigObject, ldapConfigInterface,
+ "UserNameAttribute", userNameAttribute);
}
/**
* @brief updates the LDAP group attribute and updates the
@@ -791,11 +811,11 @@ inline void handleGroupNameAttrPatch(
const std::string& ldapServerElementName,
const std::string& ldapConfigObject)
{
- setDbusProperty(asyncResp,
- ldapServerElementName +
- "/LDAPService/SearchSettings/GroupsAttribute",
- ldapDbusService, ldapConfigObject, ldapConfigInterface,
- "GroupNameAttribute", groupsAttribute);
+ setDbusProperty(
+ asyncResp,
+ ldapServerElementName + "/LDAPService/SearchSettings/GroupsAttribute",
+ ldapDbusService, ldapConfigObject, ldapConfigInterface,
+ "GroupNameAttribute", groupsAttribute);
}
/**
* @brief updates the LDAP service enable and updates the
@@ -991,11 +1011,11 @@ inline void handleLDAPPatch(LdapPatchParams&& input,
// Get the existing resource first then keep modifying
// whenever any property gets updated.
- getLDAPConfigData(serverType,
- [asyncResp, input = std::move(input),
- dbusObjectPath = std::move(dbusObjectPath)](
- bool success, const LDAPConfigData& confData,
- const std::string& serverT) mutable {
+ getLDAPConfigData(serverType, [asyncResp, input = std::move(input),
+ dbusObjectPath = std::move(dbusObjectPath)](
+ bool success,
+ const LDAPConfigData& confData,
+ const std::string& serverT) mutable {
if (!success)
{
messages::internalError(asyncResp->res);
@@ -1085,89 +1105,91 @@ inline void updateUserProperties(
[dbusObjectPath, username, password, roleId, enabled, locked,
accountTypes(std::move(accountTypes)), userSelf, session,
asyncResp{std::move(asyncResp)}](int rc) {
- if (rc <= 0)
- {
- messages::resourceNotFound(asyncResp->res, "ManagerAccount",
- username);
- return;
- }
-
- if (password)
- {
- int retval = pamUpdatePassword(username, *password);
-
- if (retval == PAM_USER_UNKNOWN)
+ if (rc <= 0)
{
messages::resourceNotFound(asyncResp->res, "ManagerAccount",
username);
+ return;
}
- else if (retval == PAM_AUTHTOK_ERR)
+
+ if (password)
{
- // If password is invalid
- messages::propertyValueFormatError(asyncResp->res, nullptr,
- "Password");
- BMCWEB_LOG_ERROR("pamUpdatePassword Failed");
+ int retval = pamUpdatePassword(username, *password);
+
+ if (retval == PAM_USER_UNKNOWN)
+ {
+ messages::resourceNotFound(asyncResp->res, "ManagerAccount",
+ username);
+ }
+ else if (retval == PAM_AUTHTOK_ERR)
+ {
+ // If password is invalid
+ messages::propertyValueFormatError(asyncResp->res, nullptr,
+ "Password");
+ BMCWEB_LOG_ERROR("pamUpdatePassword Failed");
+ }
+ else if (retval != PAM_SUCCESS)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ else
+ {
+ // Remove existing sessions of the user when password
+ // changed
+ persistent_data::SessionStore::getInstance()
+ .removeSessionsByUsernameExceptSession(username,
+ session);
+ messages::success(asyncResp->res);
+ }
}
- else if (retval != PAM_SUCCESS)
+
+ if (enabled)
{
- messages::internalError(asyncResp->res);
- return;
+ setDbusProperty(
+ asyncResp, "Enabled", "xyz.openbmc_project.User.Manager",
+ dbusObjectPath, "xyz.openbmc_project.User.Attributes",
+ "UserEnabled", *enabled);
}
- else
+
+ if (roleId)
{
- // Remove existing sessions of the user when password changed
- persistent_data::SessionStore::getInstance()
- .removeSessionsByUsernameExceptSession(username, session);
- messages::success(asyncResp->res);
+ std::string priv = getPrivilegeFromRoleId(*roleId);
+ if (priv.empty())
+ {
+ messages::propertyValueNotInList(asyncResp->res, true,
+ "Locked");
+ return;
+ }
+ setDbusProperty(
+ asyncResp, "RoleId", "xyz.openbmc_project.User.Manager",
+ dbusObjectPath, "xyz.openbmc_project.User.Attributes",
+ "UserPrivilege", priv);
}
- }
- if (enabled)
- {
- setDbusProperty(asyncResp, "Enabled",
- "xyz.openbmc_project.User.Manager", dbusObjectPath,
- "xyz.openbmc_project.User.Attributes",
- "UserEnabled", *enabled);
- }
-
- if (roleId)
- {
- std::string priv = getPrivilegeFromRoleId(*roleId);
- if (priv.empty())
+ if (locked)
{
- messages::propertyValueNotInList(asyncResp->res, true,
- "Locked");
- return;
+ // admin can unlock the account which is locked by
+ // successive authentication failures but admin should
+ // not be allowed to lock an account.
+ if (*locked)
+ {
+ messages::propertyValueNotInList(asyncResp->res, "true",
+ "Locked");
+ return;
+ }
+ setDbusProperty(
+ asyncResp, "Locked", "xyz.openbmc_project.User.Manager",
+ dbusObjectPath, "xyz.openbmc_project.User.Attributes",
+ "UserLockedForFailedAttempt", *locked);
}
- setDbusProperty(asyncResp, "RoleId",
- "xyz.openbmc_project.User.Manager", dbusObjectPath,
- "xyz.openbmc_project.User.Attributes",
- "UserPrivilege", priv);
- }
- if (locked)
- {
- // admin can unlock the account which is locked by
- // successive authentication failures but admin should
- // not be allowed to lock an account.
- if (*locked)
+ if (accountTypes)
{
- messages::propertyValueNotInList(asyncResp->res, "true",
- "Locked");
- return;
+ patchAccountTypes(*accountTypes, asyncResp, dbusObjectPath,
+ userSelf);
}
- setDbusProperty(asyncResp, "Locked",
- "xyz.openbmc_project.User.Manager", dbusObjectPath,
- "xyz.openbmc_project.User.Attributes",
- "UserLockedForFailedAttempt", *locked);
- }
-
- if (accountTypes)
- {
- patchAccountTypes(*accountTypes, asyncResp, dbusObjectPath,
- userSelf);
- }
- });
+ });
}
inline void handleAccountServiceHead(
@@ -1257,6 +1279,45 @@ inline void handleAccountServiceClientCertificatesGet(
getClientCertificates(asyncResp, "/Members"_json_pointer);
}
+using account_service::CertificateMappingAttribute;
+using persistent_data::MTLSCommonNameParseMode;
+inline CertificateMappingAttribute
+ getCertificateMapping(MTLSCommonNameParseMode parse)
+{
+ switch (parse)
+ {
+ case MTLSCommonNameParseMode::CommonName:
+ {
+ return CertificateMappingAttribute::CommonName;
+ }
+ break;
+ case MTLSCommonNameParseMode::Whole:
+ {
+ return CertificateMappingAttribute::Whole;
+ }
+ break;
+ case MTLSCommonNameParseMode::UserPrincipalName:
+ {
+ return CertificateMappingAttribute::UserPrincipalName;
+ }
+ break;
+
+ case MTLSCommonNameParseMode::Meta:
+ {
+ if constexpr (BMCWEB_META_TLS_COMMON_NAME_PARSING)
+ {
+ return CertificateMappingAttribute::CommonName;
+ }
+ }
+ break;
+ default:
+ {
+ return CertificateMappingAttribute::Invalid;
+ }
+ break;
+ }
+}
+
inline void
handleAccountServiceGet(App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
@@ -1300,9 +1361,21 @@ inline void
nlohmann::json::object_t clientCertificate;
clientCertificate["Enabled"] = authMethodsConfig.tls;
- clientCertificate["RespondToUnauthenticatedClients"] = true;
- clientCertificate["CertificateMappingAttribute"] =
- account_service::CertificateMappingAttribute::CommonName;
+ clientCertificate["RespondToUnauthenticatedClients"] =
+ !authMethodsConfig.tlsStrict;
+
+ using account_service::CertificateMappingAttribute;
+
+ CertificateMappingAttribute mapping =
+ getCertificateMapping(authMethodsConfig.mTLSCommonNameParsingMode);
+ if (mapping == CertificateMappingAttribute::Invalid)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ else
+ {
+ clientCertificate["CertificateMappingAttribute"] = mapping;
+ }
nlohmann::json::object_t certificates;
certificates["@odata.id"] =
"/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates";
@@ -1344,48 +1417,49 @@ inline void
"/xyz/openbmc_project/user", "xyz.openbmc_project.User.AccountPolicy",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- BMCWEB_LOG_DEBUG("Got {} properties for AccountService",
- propertiesList.size());
+ BMCWEB_LOG_DEBUG("Got {} properties for AccountService",
+ propertiesList.size());
- const uint8_t* minPasswordLength = nullptr;
- const uint32_t* accountUnlockTimeout = nullptr;
- const uint16_t* maxLoginAttemptBeforeLockout = nullptr;
+ const uint8_t* minPasswordLength = nullptr;
+ const uint32_t* accountUnlockTimeout = nullptr;
+ const uint16_t* maxLoginAttemptBeforeLockout = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList,
- "MinPasswordLength", minPasswordLength, "AccountUnlockTimeout",
- accountUnlockTimeout, "MaxLoginAttemptBeforeLockout",
- maxLoginAttemptBeforeLockout);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList,
+ "MinPasswordLength", minPasswordLength, "AccountUnlockTimeout",
+ accountUnlockTimeout, "MaxLoginAttemptBeforeLockout",
+ maxLoginAttemptBeforeLockout);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (minPasswordLength != nullptr)
- {
- asyncResp->res.jsonValue["MinPasswordLength"] = *minPasswordLength;
- }
+ if (minPasswordLength != nullptr)
+ {
+ asyncResp->res.jsonValue["MinPasswordLength"] =
+ *minPasswordLength;
+ }
- if (accountUnlockTimeout != nullptr)
- {
- asyncResp->res.jsonValue["AccountLockoutDuration"] =
- *accountUnlockTimeout;
- }
+ if (accountUnlockTimeout != nullptr)
+ {
+ asyncResp->res.jsonValue["AccountLockoutDuration"] =
+ *accountUnlockTimeout;
+ }
- if (maxLoginAttemptBeforeLockout != nullptr)
- {
- asyncResp->res.jsonValue["AccountLockoutThreshold"] =
- *maxLoginAttemptBeforeLockout;
- }
- });
+ if (maxLoginAttemptBeforeLockout != nullptr)
+ {
+ asyncResp->res.jsonValue["AccountLockoutThreshold"] =
+ *maxLoginAttemptBeforeLockout;
+ }
+ });
auto callback = [asyncResp](bool success, const LDAPConfigData& confData,
const std::string& ldapType) {
@@ -1400,6 +1474,55 @@ inline void
getLDAPConfigData("ActiveDirectory", callback);
}
+inline void handleCertificateMappingAttributePatch(
+ crow::Response& res, const std::string& certMapAttribute)
+{
+ MTLSCommonNameParseMode parseMode =
+ persistent_data::getMTLSCommonNameParseMode(certMapAttribute);
+ if (parseMode == MTLSCommonNameParseMode::Invalid)
+ {
+ messages::propertyValueNotInList(res, "CertificateMappingAttribute",
+ certMapAttribute);
+ return;
+ }
+
+ persistent_data::AuthConfigMethods& authMethodsConfig =
+ persistent_data::SessionStore::getInstance().getAuthMethodsConfig();
+ authMethodsConfig.mTLSCommonNameParsingMode = parseMode;
+}
+
+inline void handleRespondToUnauthenticatedClientsPatch(
+ App& app, const crow::Request& req, crow::Response& res,
+ bool respondToUnauthenticatedClients)
+{
+ if (req.session != nullptr)
+ {
+ // Sanity check. If the user isn't currently authenticated with mutual
+ // TLS, they very likely are about to permanently lock themselves out.
+ // Make sure they're using mutual TLS before allowing locking.
+ if (req.session->sessionType != persistent_data::SessionType::MutualTLS)
+ {
+ messages::propertyValueExternalConflict(
+ res,
+ "MultiFactorAuth/ClientCertificate/RespondToUnauthenticatedClients",
+ respondToUnauthenticatedClients);
+ return;
+ }
+ }
+
+ persistent_data::AuthConfigMethods& authMethodsConfig =
+ persistent_data::SessionStore::getInstance().getAuthMethodsConfig();
+
+ // Change the settings
+ authMethodsConfig.tlsStrict = !respondToUnauthenticatedClients;
+
+ // Write settings to disk
+ persistent_data::getConfig().writeData();
+
+ // Trigger a reload, to apply the new settings to new connections
+ app.loadCertificate();
+}
+
inline void handleAccountServicePatch(
App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
@@ -1413,9 +1536,12 @@ inline void handleAccountServicePatch(
std::optional<uint8_t> minPasswordLength;
std::optional<uint16_t> maxPasswordLength;
LdapPatchParams ldapObject;
+ std::optional<std::string> certificateMappingAttribute;
+ std::optional<bool> respondToUnauthenticatedClients;
LdapPatchParams activeDirectoryObject;
AuthMethods auth;
std::optional<std::string> httpBasicAuth;
+
// clang-format off
if (!json_util::readJsonPatch(
req, asyncResp->res,
@@ -1430,6 +1556,8 @@ inline void handleAccountServicePatch(
"ActiveDirectory/RemoteRoleMapping", activeDirectoryObject.remoteRoleMapData,
"ActiveDirectory/ServiceAddresses", activeDirectoryObject.serviceAddressList,
"ActiveDirectory/ServiceEnabled", activeDirectoryObject.serviceEnabled,
+ "MultiFactorAuth/ClientCertificate/CertificateMappingAttribute", certificateMappingAttribute,
+ "MultiFactorAuth/ClientCertificate/RespondToUnauthenticatedClients", respondToUnauthenticatedClients,
"LDAP/Authentication/AuthenticationType", ldapObject.authType,
"LDAP/Authentication/Password", ldapObject.password,
"LDAP/Authentication/Username", ldapObject.userName,
@@ -1469,6 +1597,18 @@ inline void handleAccountServicePatch(
}
}
+ if (respondToUnauthenticatedClients)
+ {
+ handleRespondToUnauthenticatedClientsPatch(
+ app, req, asyncResp->res, *respondToUnauthenticatedClients);
+ }
+
+ if (certificateMappingAttribute)
+ {
+ handleCertificateMappingAttributePatch(asyncResp->res,
+ *certificateMappingAttribute);
+ }
+
if (minPasswordLength)
{
setDbusProperty(
@@ -1562,47 +1702,49 @@ inline void handleAccountCollectionGet(
[asyncResp, thisUser, effectiveUserPrivileges](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& users) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- bool userCanSeeAllAccounts =
- effectiveUserPrivileges.isSupersetOf({"ConfigureUsers"});
+ bool userCanSeeAllAccounts =
+ effectiveUserPrivileges.isSupersetOf({"ConfigureUsers"});
- bool userCanSeeSelf =
- effectiveUserPrivileges.isSupersetOf({"ConfigureSelf"});
+ bool userCanSeeSelf =
+ effectiveUserPrivileges.isSupersetOf({"ConfigureSelf"});
- nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
- memberArray = nlohmann::json::array();
+ nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
+ memberArray = nlohmann::json::array();
- for (const auto& userpath : users)
- {
- std::string user = userpath.first.filename();
- if (user.empty())
+ for (const auto& userpath : users)
{
- messages::internalError(asyncResp->res);
- BMCWEB_LOG_ERROR("Invalid firmware ID");
+ std::string user = userpath.first.filename();
+ if (user.empty())
+ {
+ messages::internalError(asyncResp->res);
+ BMCWEB_LOG_ERROR("Invalid firmware ID");
- return;
- }
+ return;
+ }
- // As clarified by Redfish here:
- // https://redfishforum.com/thread/281/manageraccountcollection-change-allows-account-enumeration
- // Users without ConfigureUsers, only see their own
- // account. Users with ConfigureUsers, see all
- // accounts.
- if (userCanSeeAllAccounts || (thisUser == user && userCanSeeSelf))
- {
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/AccountService/Accounts/{}", user);
- memberArray.emplace_back(std::move(member));
+ // As clarified by Redfish here:
+ // https://redfishforum.com/thread/281/manageraccountcollection-change-allows-account-enumeration
+ // Users without ConfigureUsers, only see their own
+ // account. Users with ConfigureUsers, see all
+ // accounts.
+ if (userCanSeeAllAccounts ||
+ (thisUser == user && userCanSeeSelf))
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/AccountService/Accounts/{}", user);
+ memberArray.emplace_back(std::move(member));
+ }
}
- }
- asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size();
- });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ memberArray.size();
+ });
}
inline void processAfterCreateUser(
@@ -1628,16 +1770,16 @@ inline void processAfterCreateUser(
crow::connections::systemBus->async_method_call(
[asyncResp, password](const boost::system::error_code& ec3) {
- if (ec3)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec3)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // If password is invalid
- messages::propertyValueFormatError(asyncResp->res, nullptr,
- "Password");
- },
+ // If password is invalid
+ messages::propertyValueFormatError(asyncResp->res, nullptr,
+ "Password");
+ },
"xyz.openbmc_project.User.Manager", userPath,
"xyz.openbmc_project.Object.Delete", "Delete");
@@ -1721,8 +1863,8 @@ inline void processAfterGetAllGroups(
crow::connections::systemBus->async_method_call(
[asyncResp, username, password](const boost::system::error_code& ec2,
sdbusplus::message_t& m) {
- processAfterCreateUser(asyncResp, username, password, ec2, m);
- },
+ processAfterCreateUser(asyncResp, username, password, ec2, m);
+ },
"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
"xyz.openbmc_project.User.Manager", "CreateUser", username, userGroups,
roleId, enabled);
@@ -1741,10 +1883,10 @@ inline void handleAccountCollectionPost(
std::optional<std::string> roleIdJson;
std::optional<bool> enabledJson;
std::optional<std::vector<std::string>> accountTypes;
- if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", username,
- "Password", password, "RoleId", roleIdJson,
- "Enabled", enabledJson, "AccountTypes",
- accountTypes))
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "UserName", username, "Password", password,
+ "RoleId", roleIdJson, "Enabled", enabledJson, "AccountTypes",
+ accountTypes))
{
return;
}
@@ -1768,22 +1910,22 @@ inline void handleAccountCollectionPost(
[asyncResp, username, password{std::move(password)}, roleId, enabled,
accountTypes](const boost::system::error_code& ec,
const std::vector<std::string>& allGroupsList) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("ERROR with async_method_call");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("D-Bus response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (allGroupsList.empty())
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (allGroupsList.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- processAfterGetAllGroups(asyncResp, username, password, roleId, enabled,
- accountTypes, allGroupsList);
- });
+ processAfterGetAllGroups(asyncResp, username, password, roleId,
+ enabled, accountTypes, allGroupsList);
+ });
}
inline void
@@ -1851,138 +1993,140 @@ inline void
[asyncResp,
accountName](const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& users) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- const auto userIt = std::ranges::find_if(
- users,
- [accountName](
- const std::pair<sdbusplus::message::object_path,
- dbus::utility::DBusInterfacesMap>& user) {
- return accountName == user.first.filename();
- });
-
- if (userIt == users.end())
- {
- messages::resourceNotFound(asyncResp->res, "ManagerAccount",
- accountName);
- return;
- }
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const auto userIt = std::ranges::find_if(
+ users,
+ [accountName](
+ const std::pair<sdbusplus::message::object_path,
+ dbus::utility::DBusInterfacesMap>& user) {
+ return accountName == user.first.filename();
+ });
+
+ if (userIt == users.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "ManagerAccount",
+ accountName);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#ManagerAccount.v1_7_0.ManagerAccount";
- asyncResp->res.jsonValue["Name"] = "User Account";
- asyncResp->res.jsonValue["Description"] = "User Account";
- asyncResp->res.jsonValue["Password"] = nullptr;
- asyncResp->res.jsonValue["StrictAccountTypes"] = true;
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ManagerAccount.v1_7_0.ManagerAccount";
+ asyncResp->res.jsonValue["Name"] = "User Account";
+ asyncResp->res.jsonValue["Description"] = "User Account";
+ asyncResp->res.jsonValue["Password"] = nullptr;
+ asyncResp->res.jsonValue["StrictAccountTypes"] = true;
- for (const auto& interface : userIt->second)
- {
- if (interface.first == "xyz.openbmc_project.User.Attributes")
+ for (const auto& interface : userIt->second)
{
- for (const auto& property : interface.second)
+ if (interface.first == "xyz.openbmc_project.User.Attributes")
{
- if (property.first == "UserEnabled")
- {
- const bool* userEnabled =
- std::get_if<bool>(&property.second);
- if (userEnabled == nullptr)
- {
- BMCWEB_LOG_ERROR("UserEnabled wasn't a bool");
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["Enabled"] = *userEnabled;
- }
- else if (property.first == "UserLockedForFailedAttempt")
+ for (const auto& property : interface.second)
{
- const bool* userLocked =
- std::get_if<bool>(&property.second);
- if (userLocked == nullptr)
+ if (property.first == "UserEnabled")
{
- BMCWEB_LOG_ERROR("UserLockedForF"
- "ailedAttempt "
- "wasn't a bool");
- messages::internalError(asyncResp->res);
- return;
+ const bool* userEnabled =
+ std::get_if<bool>(&property.second);
+ if (userEnabled == nullptr)
+ {
+ BMCWEB_LOG_ERROR("UserEnabled wasn't a bool");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["Enabled"] = *userEnabled;
}
- asyncResp->res.jsonValue["Locked"] = *userLocked;
- nlohmann::json::array_t allowed;
- // can only unlock accounts
- allowed.emplace_back("false");
- asyncResp->res
- .jsonValue["Locked@Redfish.AllowableValues"] =
- std::move(allowed);
- }
- else if (property.first == "UserPrivilege")
- {
- const std::string* userPrivPtr =
- std::get_if<std::string>(&property.second);
- if (userPrivPtr == nullptr)
+ else if (property.first == "UserLockedForFailedAttempt")
{
- BMCWEB_LOG_ERROR("UserPrivilege wasn't a "
- "string");
- messages::internalError(asyncResp->res);
- return;
+ const bool* userLocked =
+ std::get_if<bool>(&property.second);
+ if (userLocked == nullptr)
+ {
+ BMCWEB_LOG_ERROR("UserLockedForF"
+ "ailedAttempt "
+ "wasn't a bool");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["Locked"] = *userLocked;
+ nlohmann::json::array_t allowed;
+ // can only unlock accounts
+ allowed.emplace_back("false");
+ asyncResp->res
+ .jsonValue["Locked@Redfish.AllowableValues"] =
+ std::move(allowed);
}
- std::string role = getRoleIdFromPrivilege(*userPrivPtr);
- if (role.empty())
+ else if (property.first == "UserPrivilege")
{
- BMCWEB_LOG_ERROR("Invalid user role");
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["RoleId"] = role;
+ const std::string* userPrivPtr =
+ std::get_if<std::string>(&property.second);
+ if (userPrivPtr == nullptr)
+ {
+ BMCWEB_LOG_ERROR("UserPrivilege wasn't a "
+ "string");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::string role =
+ getRoleIdFromPrivilege(*userPrivPtr);
+ if (role.empty())
+ {
+ BMCWEB_LOG_ERROR("Invalid user role");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["RoleId"] = role;
- nlohmann::json& roleEntry =
- asyncResp->res.jsonValue["Links"]["Role"];
- roleEntry["@odata.id"] = boost::urls::format(
- "/redfish/v1/AccountService/Roles/{}", role);
- }
- else if (property.first == "UserPasswordExpired")
- {
- const bool* userPasswordExpired =
- std::get_if<bool>(&property.second);
- if (userPasswordExpired == nullptr)
- {
- BMCWEB_LOG_ERROR(
- "UserPasswordExpired wasn't a bool");
- messages::internalError(asyncResp->res);
- return;
+ nlohmann::json& roleEntry =
+ asyncResp->res.jsonValue["Links"]["Role"];
+ roleEntry["@odata.id"] = boost::urls::format(
+ "/redfish/v1/AccountService/Roles/{}", role);
}
- asyncResp->res.jsonValue["PasswordChangeRequired"] =
- *userPasswordExpired;
- }
- else if (property.first == "UserGroups")
- {
- const std::vector<std::string>* userGroups =
- std::get_if<std::vector<std::string>>(
- &property.second);
- if (userGroups == nullptr)
+ else if (property.first == "UserPasswordExpired")
{
- BMCWEB_LOG_ERROR(
- "userGroups wasn't a string vector");
- messages::internalError(asyncResp->res);
- return;
+ const bool* userPasswordExpired =
+ std::get_if<bool>(&property.second);
+ if (userPasswordExpired == nullptr)
+ {
+ BMCWEB_LOG_ERROR(
+ "UserPasswordExpired wasn't a bool");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["PasswordChangeRequired"] =
+ *userPasswordExpired;
}
- if (!translateUserGroup(*userGroups, asyncResp->res))
+ else if (property.first == "UserGroups")
{
- BMCWEB_LOG_ERROR("userGroups mapping failed");
- messages::internalError(asyncResp->res);
- return;
+ const std::vector<std::string>* userGroups =
+ std::get_if<std::vector<std::string>>(
+ &property.second);
+ if (userGroups == nullptr)
+ {
+ BMCWEB_LOG_ERROR(
+ "userGroups wasn't a string vector");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (!translateUserGroup(*userGroups,
+ asyncResp->res))
+ {
+ BMCWEB_LOG_ERROR("userGroups mapping failed");
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
}
}
}
- }
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/AccountService/Accounts/{}", accountName);
- asyncResp->res.jsonValue["Id"] = accountName;
- asyncResp->res.jsonValue["UserName"] = accountName;
- });
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/AccountService/Accounts/{}", accountName);
+ asyncResp->res.jsonValue["Id"] = accountName;
+ asyncResp->res.jsonValue["UserName"] = accountName;
+ });
}
inline void
@@ -2007,15 +2151,15 @@ inline void
crow::connections::systemBus->async_method_call(
[asyncResp, username](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::resourceNotFound(asyncResp->res, "ManagerAccount",
- username);
- return;
- }
+ if (ec)
+ {
+ messages::resourceNotFound(asyncResp->res, "ManagerAccount",
+ username);
+ return;
+ }
- messages::accountRemoved(asyncResp->res);
- },
+ messages::accountRemoved(asyncResp->res);
+ },
"xyz.openbmc_project.User.Manager", userPath,
"xyz.openbmc_project.Object.Delete", "Delete");
}
@@ -2099,16 +2243,16 @@ inline void
roleId(std::move(roleId)), enabled, newUser{std::string(*newUserName)},
locked, userSelf, req, accountTypes(std::move(accountTypes))](
const boost::system::error_code& ec, sdbusplus::message_t& m) {
- if (ec)
- {
- userErrorMessageHandler(m.get_error(), asyncResp, newUser,
- username);
- return;
- }
+ if (ec)
+ {
+ userErrorMessageHandler(m.get_error(), asyncResp, newUser,
+ username);
+ return;
+ }
- updateUserProperties(asyncResp, newUser, password, enabled, roleId,
- locked, accountTypes, userSelf, req.session);
- },
+ updateUserProperties(asyncResp, newUser, password, enabled, roleId,
+ locked, accountTypes, userSelf, req.session);
+ },
"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
"xyz.openbmc_project.User.Manager", "RenameUser", username,
*newUserName);
diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp
index 1ec967b6eb..ee922af854 100644
--- a/redfish-core/lib/bios.hpp
+++ b/redfish-core/lib/bios.hpp
@@ -91,13 +91,13 @@ inline void
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Failed to reset bios: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Failed to reset bios: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
"org.open_power.Software.Host.Updater", "/xyz/openbmc_project/software",
"xyz.openbmc_project.Common.FactoryReset", "Reset");
}
diff --git a/redfish-core/lib/cable.hpp b/redfish-core/lib/cable.hpp
index bc73267101..27ee276a55 100644
--- a/redfish-core/lib/cable.hpp
+++ b/redfish-core/lib/cable.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "dbus_utility.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
@@ -23,10 +24,9 @@ namespace redfish
* @param[in] ec Error code corresponding to Async method call.
* @param[in] properties List of Cable Properties key/value pairs.
*/
-inline void
- fillCableProperties(crow::Response& resp,
- const boost::system::error_code& ec,
- const dbus::utility::DBusPropertiesMap& properties)
+inline void fillCableProperties(
+ crow::Response& resp, const boost::system::error_code& ec,
+ const dbus::utility::DBusPropertiesMap& properties)
{
if (ec)
{
@@ -97,8 +97,8 @@ inline void
[asyncResp](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- fillCableProperties(asyncResp->res, ec, properties);
- });
+ fillCableProperties(asyncResp->res, ec, properties);
+ });
}
else if (interface == "xyz.openbmc_project.Inventory.Item")
{
@@ -107,23 +107,24 @@ inline void
interface, "Present",
[asyncResp, cableObjectPath](
const boost::system::error_code& ec, bool present) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG(
- "get presence failed for Cable {} with error {}",
- cableObjectPath, ec);
- if (ec.value() != EBADR)
+ if (ec)
{
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG(
+ "get presence failed for Cable {} with error {}",
+ cableObjectPath, ec);
+ if (ec.value() != EBADR)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+
+ if (!present)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
}
- return;
- }
-
- if (!present)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ });
}
}
}
@@ -140,52 +141,59 @@ inline void requestRoutesCable(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& cableId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
- constexpr std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Cable"};
- dbus::utility::getSubTree(
- "/xyz/openbmc_project/inventory", 0, interfaces,
- [asyncResp,
- cableId](const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "Cable", cableId);
- return;
- }
-
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- for (const auto& [objectPath, serviceMap] : subtree)
- {
- sdbusplus::message::object_path path(objectPath);
- if (path.filename() != cableId)
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- continue;
+ return;
}
+ BMCWEB_LOG_DEBUG("Cable Id: {}", cableId);
+ constexpr std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Cable"};
+ dbus::utility::getSubTree(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ [asyncResp,
+ cableId](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse&
+ subtree) {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res, "Cable",
+ cableId);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable";
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Cables/{}", cableId);
- asyncResp->res.jsonValue["Id"] = cableId;
- asyncResp->res.jsonValue["Name"] = "Cable";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- getCableProperties(asyncResp, objectPath, serviceMap);
- return;
- }
- messages::resourceNotFound(asyncResp->res, "Cable", cableId);
- });
- });
+ for (const auto& [objectPath, serviceMap] : subtree)
+ {
+ sdbusplus::message::object_path path(objectPath);
+ if (path.filename() != cableId)
+ {
+ continue;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Cable.v1_0_0.Cable";
+ asyncResp->res.jsonValue["@odata.id"] =
+ boost::urls::format("/redfish/v1/Cables/{}",
+ cableId);
+ asyncResp->res.jsonValue["Id"] = cableId;
+ asyncResp->res.jsonValue["Name"] = "Cable";
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+
+ getCableProperties(asyncResp, objectPath,
+ serviceMap);
+ return;
+ }
+ messages::resourceNotFound(asyncResp->res, "Cable",
+ cableId);
+ });
+ });
}
/**
@@ -198,21 +206,22 @@ inline void requestRoutesCableCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#CableCollection.CableCollection";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
- asyncResp->res.jsonValue["Name"] = "Cable Collection";
- asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries";
- constexpr std::array<std::string_view, 1> interfaces{
- "xyz.openbmc_project.Inventory.Item.Cable"};
- collection_util::getCollectionMembers(
- asyncResp, boost::urls::url("/redfish/v1/Cables"), interfaces,
- "/xyz/openbmc_project/inventory");
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#CableCollection.CableCollection";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables";
+ asyncResp->res.jsonValue["Name"] = "Cable Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Cable Entries";
+ constexpr std::array<std::string_view, 1> interfaces{
+ "xyz.openbmc_project.Inventory.Item.Cable"};
+ collection_util::getCollectionMembers(
+ asyncResp, boost::urls::url("/redfish/v1/Cables"),
+ interfaces, "/xyz/openbmc_project/inventory");
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index af35450ab7..7ae194cdf2 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -106,9 +106,9 @@ class CertificateFile
{
certDirectory = tempDirectory;
certificateFile = certDirectory / "cert.pem";
- std::ofstream out(certificateFile, std::ofstream::out |
- std::ofstream::binary |
- std::ofstream::trunc);
+ std::ofstream out(certificateFile,
+ std::ofstream::out | std::ofstream::binary |
+ std::ofstream::trunc);
out << certString;
out.close();
BMCWEB_LOG_DEBUG("Creating certificate file{}",
@@ -148,7 +148,7 @@ class CertificateFile
* @param[in] type Issuer/Subject
* @return None
*/
-static void updateCertIssuerOrSubject(nlohmann::json& out,
+inline void updateCertIssuerOrSubject(nlohmann::json& out,
std::string_view value)
{
// example: O=openbmc-project.xyz,CN=localhost
@@ -213,11 +213,10 @@ static void updateCertIssuerOrSubject(nlohmann::json& out,
* @param[in] countPtr Json pointer to the count in asyncResp
* @return None
*/
-static void
- getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& basePath,
- const nlohmann::json::json_pointer& listPtr,
- const nlohmann::json::json_pointer& countPtr)
+inline void getCertificateList(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& basePath, const nlohmann::json::json_pointer& listPtr,
+ const nlohmann::json::json_pointer& countPtr)
{
constexpr std::array<std::string_view, 1> interfaces = {
certs::certPropIntf};
@@ -226,55 +225,57 @@ static void
[asyncResp, listPtr, countPtr](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Certificate collection query failed: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
- links = nlohmann::json::array();
- for (const auto& certPath : certPaths)
- {
- sdbusplus::message::object_path objPath(certPath);
- std::string certId = objPath.filename();
- if (certId.empty())
+ if (ec)
{
- BMCWEB_LOG_ERROR("Invalid certificate objPath {}", certPath);
- continue;
+ BMCWEB_LOG_ERROR("Certificate collection query failed: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
}
- boost::urls::url certURL;
- if (objPath.parent_path() == certs::httpsObjectPath)
+ nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
+ links = nlohmann::json::array();
+ for (const auto& certPath : certPaths)
{
- certURL = boost::urls::format(
- "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
+ sdbusplus::message::object_path objPath(certPath);
+ std::string certId = objPath.filename();
+ if (certId.empty())
+ {
+ BMCWEB_LOG_ERROR("Invalid certificate objPath {}",
+ certPath);
+ continue;
+ }
+
+ boost::urls::url certURL;
+ if (objPath.parent_path() == certs::httpsObjectPath)
+ {
+ certURL = boost::urls::format(
+ "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
+ }
+ else if (objPath.parent_path() == certs::ldapObjectPath)
+ {
+ certURL = boost::urls::format(
+ "/redfish/v1/AccountService/LDAP/Certificates/{}",
+ certId);
+ }
+ else if (objPath.parent_path() == certs::authorityObjectPath)
+ {
+ certURL = boost::urls::format(
+ "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
+ }
+ else
+ {
+ continue;
+ }
+
+ nlohmann::json::object_t link;
+ link["@odata.id"] = certURL;
+ links.emplace_back(std::move(link));
}
- else if (objPath.parent_path() == certs::ldapObjectPath)
- {
- certURL = boost::urls::format(
- "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
- }
- else if (objPath.parent_path() == certs::authorityObjectPath)
- {
- certURL = boost::urls::format(
- "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
- }
- else
- {
- continue;
- }
-
- nlohmann::json::object_t link;
- link["@odata.id"] = certURL;
- links.emplace_back(std::move(link));
- }
- asyncResp->res.jsonValue[countPtr] = links.size();
- });
+ asyncResp->res.jsonValue[countPtr] = links.size();
+ });
}
/**
@@ -288,7 +289,7 @@ static void
* @param[in] name name of the certificate
* @return None
*/
-static void getCertificateProperties(
+inline void getCertificateProperties(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& objectPath, const std::string& service,
const std::string& certId, const boost::urls::url& certURL,
@@ -301,82 +302,84 @@ static void getCertificateProperties(
[asyncResp, certURL, certId,
name](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::resourceNotFound(asyncResp->res, "Certificate", certId);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::resourceNotFound(asyncResp->res, "Certificate",
+ certId);
+ return;
+ }
- const std::string* certificateString = nullptr;
- const std::vector<std::string>* keyUsage = nullptr;
- const std::string* issuer = nullptr;
- const std::string* subject = nullptr;
- const uint64_t* validNotAfter = nullptr;
- const uint64_t* validNotBefore = nullptr;
+ const std::string* certificateString = nullptr;
+ const std::vector<std::string>* keyUsage = nullptr;
+ const std::string* issuer = nullptr;
+ const std::string* subject = nullptr;
+ const uint64_t* validNotAfter = nullptr;
+ const uint64_t* validNotBefore = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "CertificateString",
- certificateString, "KeyUsage", keyUsage, "Issuer", issuer,
- "Subject", subject, "ValidNotAfter", validNotAfter,
- "ValidNotBefore", validNotBefore);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties,
+ "CertificateString", certificateString, "KeyUsage", keyUsage,
+ "Issuer", issuer, "Subject", subject, "ValidNotAfter",
+ validNotAfter, "ValidNotBefore", validNotBefore);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.id"] = certURL;
- asyncResp->res.jsonValue["@odata.type"] =
- "#Certificate.v1_0_0.Certificate";
- asyncResp->res.jsonValue["Id"] = certId;
- asyncResp->res.jsonValue["Name"] = name;
- asyncResp->res.jsonValue["Description"] = name;
- asyncResp->res.jsonValue["CertificateString"] = "";
- asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["@odata.id"] = certURL;
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Certificate.v1_0_0.Certificate";
+ asyncResp->res.jsonValue["Id"] = certId;
+ asyncResp->res.jsonValue["Name"] = name;
+ asyncResp->res.jsonValue["Description"] = name;
+ asyncResp->res.jsonValue["CertificateString"] = "";
+ asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();
- if (certificateString != nullptr)
- {
- asyncResp->res.jsonValue["CertificateString"] = *certificateString;
- }
+ if (certificateString != nullptr)
+ {
+ asyncResp->res.jsonValue["CertificateString"] =
+ *certificateString;
+ }
- if (keyUsage != nullptr)
- {
- asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
- }
+ if (keyUsage != nullptr)
+ {
+ asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
+ }
- if (issuer != nullptr)
- {
- updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
- *issuer);
- }
+ if (issuer != nullptr)
+ {
+ updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
+ *issuer);
+ }
- if (subject != nullptr)
- {
- updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
- *subject);
- }
+ if (subject != nullptr)
+ {
+ updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
+ *subject);
+ }
- if (validNotAfter != nullptr)
- {
- asyncResp->res.jsonValue["ValidNotAfter"] =
- redfish::time_utils::getDateTimeUint(*validNotAfter);
- }
+ if (validNotAfter != nullptr)
+ {
+ asyncResp->res.jsonValue["ValidNotAfter"] =
+ redfish::time_utils::getDateTimeUint(*validNotAfter);
+ }
- if (validNotBefore != nullptr)
- {
- asyncResp->res.jsonValue["ValidNotBefore"] =
- redfish::time_utils::getDateTimeUint(*validNotBefore);
- }
+ if (validNotBefore != nullptr)
+ {
+ asyncResp->res.jsonValue["ValidNotBefore"] =
+ redfish::time_utils::getDateTimeUint(*validNotBefore);
+ }
- asyncResp->res.addHeader(
- boost::beast::http::field::location,
- std::string_view(certURL.data(), certURL.size()));
- });
+ asyncResp->res.addHeader(
+ boost::beast::http::field::location,
+ std::string_view(certURL.data(), certURL.size()));
+ });
}
-static void
+inline void
deleteCertificate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& service,
const sdbusplus::message::object_path& objectPath)
@@ -384,14 +387,14 @@ static void
crow::connections::systemBus->async_method_call(
[asyncResp,
id{objectPath.filename()}](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::resourceNotFound(asyncResp->res, "Certificate", id);
- return;
- }
- BMCWEB_LOG_INFO("Certificate deleted");
- asyncResp->res.result(boost::beast::http::status::no_content);
- },
+ if (ec)
+ {
+ messages::resourceNotFound(asyncResp->res, "Certificate", id);
+ return;
+ }
+ BMCWEB_LOG_INFO("Certificate deleted");
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ },
service, objectPath, certs::objDeleteIntf, "Delete");
}
@@ -462,6 +465,26 @@ inline void handleCertificateLocationsGet(
"/Links/Certificates@odata.count"_json_pointer);
}
+inline void handleError(const std::string_view dbusErrorName,
+ const std::string& id, const std::string& certificate,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ if (dbusErrorName == "org.freedesktop.DBus.Error.UnknownObject")
+ {
+ messages::resourceNotFound(asyncResp->res, "Certificate", id);
+ }
+ else if (dbusErrorName ==
+ "xyz.openbmc_project.Certs.Error.InvalidCertificate")
+ {
+ messages::propertyValueIncorrect(asyncResp->res, "Certificate",
+ certificate);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+}
+
inline void handleReplaceCertificateAction(
App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
@@ -546,24 +569,28 @@ inline void handleReplaceCertificateAction(
std::shared_ptr<CertificateFile> certFile =
std::make_shared<CertificateFile>(certificate);
crow::connections::systemBus->async_method_call(
- [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
- name](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- if (ec.value() ==
- boost::system::linux_error::bad_request_descriptor)
+ [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id, name,
+ certificate](const boost::system::error_code& ec,
+ sdbusplus::message_t& m) {
+ if (ec)
{
- messages::resourceNotFound(asyncResp->res, "Certificate", id);
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ const sd_bus_error* dbusError = m.get_error();
+ if ((dbusError != nullptr) && (dbusError->name != nullptr))
+ {
+ handleError(dbusError->name, id, certificate, asyncResp);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
return;
}
- messages::internalError(asyncResp->res);
- return;
- }
- getCertificateProperties(asyncResp, objectPath, service, id, url, name);
- BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
- certFile->getCertFilePath());
- },
+ getCertificateProperties(asyncResp, objectPath, service, id, url,
+ name);
+ BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
+ certFile->getCertFilePath());
+ },
service, objectPath, certs::certReplaceIntf, "Replace",
certFile->getCertFilePath());
}
@@ -580,7 +607,7 @@ static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
* @param[in] csrObjPath CSR D-Bus object path
* @return None
*/
-static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+inline void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& certURI, const std::string& service,
const std::string& certObjPath,
const std::string& csrObjPath)
@@ -588,24 +615,24 @@ static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
BMCWEB_LOG_DEBUG("getCSR CertObjectPath{} CSRObjectPath={} service={}",
certObjPath, csrObjPath, service);
crow::connections::systemBus->async_method_call(
- [asyncResp, certURI](const boost::system::error_code& ec,
- const std::string& csr) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- if (csr.empty())
- {
- BMCWEB_LOG_ERROR("CSR read is empty");
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["CSRString"] = csr;
- asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
- certURI;
- },
+ [asyncResp,
+ certURI](const boost::system::error_code& ec, const std::string& csr) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (csr.empty())
+ {
+ BMCWEB_LOG_ERROR("CSR read is empty");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["CSRString"] = csr;
+ asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
+ certURI;
+ },
service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
}
@@ -804,38 +831,38 @@ inline void
csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
*crow::connections::systemBus, match,
[asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
- timeout.cancel();
- if (m.is_method_error())
- {
- BMCWEB_LOG_ERROR("Dbus method error!!!");
- messages::internalError(asyncResp->res);
- return;
- }
+ timeout.cancel();
+ if (m.is_method_error())
+ {
+ BMCWEB_LOG_ERROR("Dbus method error!!!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- dbus::utility::DBusInterfacesMap interfacesProperties;
+ dbus::utility::DBusInterfacesMap interfacesProperties;
- sdbusplus::message::object_path csrObjectPath;
- m.read(csrObjectPath, interfacesProperties);
- BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str);
- for (const auto& interface : interfacesProperties)
- {
- if (interface.first == "xyz.openbmc_project.Certs.CSR")
+ sdbusplus::message::object_path csrObjectPath;
+ m.read(csrObjectPath, interfacesProperties);
+ BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str);
+ for (const auto& interface : interfacesProperties)
{
- getCSR(asyncResp, certURI, service, objectPath,
- csrObjectPath.str);
- break;
+ if (interface.first == "xyz.openbmc_project.Certs.CSR")
+ {
+ getCSR(asyncResp, certURI, service, objectPath,
+ csrObjectPath.str);
+ break;
+ }
}
- }
- });
+ });
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec, const std::string&) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
"GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
commonName, *optContactPerson, country, *optEmail, *optGivenName,
@@ -937,23 +964,24 @@ inline void handleHTTPSCertificateCollectionPost(
crow::connections::systemBus->async_method_call(
[asyncResp, certFile](const boost::system::error_code& ec,
const std::string& objectPath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- sdbusplus::message::object_path path(objectPath);
- std::string certId = path.filename();
- const boost::urls::url certURL = boost::urls::format(
- "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
- getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
- certId, certURL, "HTTPS Certificate");
- BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
- certFile->getCertFilePath());
- },
+ sdbusplus::message::object_path path(objectPath);
+ std::string certId = path.filename();
+ const boost::urls::url certURL = boost::urls::format(
+ "/redfish/v1/Managers/{}/NetworkProtocol/HTTPS/Certificates/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::httpsServiceName, certId, certURL,
+ "HTTPS Certificate");
+ BMCWEB_LOG_DEBUG("HTTPS certificate install file={}",
+ certFile->getCertFilePath());
+ },
certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
"Install", certFile->getCertFilePath());
}
@@ -1051,22 +1079,23 @@ inline void handleLDAPCertificateCollectionPost(
crow::connections::systemBus->async_method_call(
[asyncResp, certFile](const boost::system::error_code& ec,
const std::string& objectPath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- sdbusplus::message::object_path path(objectPath);
- std::string certId = path.filename();
- const boost::urls::url certURL = boost::urls::format(
- "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
- getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
- certId, certURL, "LDAP Certificate");
- BMCWEB_LOG_DEBUG("LDAP certificate install file={}",
- certFile->getCertFilePath());
- },
+ sdbusplus::message::object_path path(objectPath);
+ std::string certId = path.filename();
+ const boost::urls::url certURL = boost::urls::format(
+ "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::ldapServiceName, certId, certURL,
+ "LDAP Certificate");
+ BMCWEB_LOG_DEBUG("LDAP certificate install file={}",
+ certFile->getCertFilePath());
+ },
certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
"Install", certFile->getCertFilePath());
}
@@ -1188,24 +1217,24 @@ inline void handleTrustStoreCertificateCollectionPost(
crow::connections::systemBus->async_method_call(
[asyncResp, certFile](const boost::system::error_code& ec,
const std::string& objectPath) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- sdbusplus::message::object_path path(objectPath);
- std::string certId = path.filename();
- const boost::urls::url certURL = boost::urls::format(
- "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
- getCertificateProperties(asyncResp, objectPath,
- certs::authorityServiceName, certId, certURL,
- "TrustStore Certificate");
- BMCWEB_LOG_DEBUG("TrustStore certificate install file={}",
- certFile->getCertFilePath());
- },
+ sdbusplus::message::object_path path(objectPath);
+ std::string certId = path.filename();
+ const boost::urls::url certURL = boost::urls::format(
+ "/redfish/v1/Managers/{}/Truststore/Certificates/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, certId);
+ getCertificateProperties(asyncResp, objectPath,
+ certs::authorityServiceName, certId,
+ certURL, "TrustStore Certificate");
+ BMCWEB_LOG_DEBUG("TrustStore certificate install file={}",
+ certFile->getCertFilePath());
+ },
certs::authorityServiceName, certs::authorityObjectPath,
certs::certInstallIntf, "Install", certFile->getCertFilePath());
}
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index 723cc1e411..a993b016bc 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -1,22 +1,25 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/action_info.hpp"
+#include "generated/enums/chassis.hpp"
+#include "generated/enums/resource.hpp"
#include "led.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
@@ -59,32 +62,32 @@ inline void getStorageLink(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
(path / "storage").str, "xyz.openbmc_project.Association", "endpoints",
[asyncResp](const boost::system::error_code& ec,
const std::vector<std::string>& storageList) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error");
- return;
- }
-
- nlohmann::json::array_t storages;
- for (const std::string& storagePath : storageList)
- {
- std::string id =
- sdbusplus::message::object_path(storagePath).filename();
- if (id.empty())
+ if (ec)
{
- continue;
+ BMCWEB_LOG_DEBUG("getStorageLink got DBUS response error");
+ return;
}
- nlohmann::json::object_t storage;
- storage["@odata.id"] =
- boost::urls::format("/redfish/v1/Systems/{}/Storage/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, id);
- storages.emplace_back(std::move(storage));
- }
- asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
- storages.size();
- asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages);
- });
+ nlohmann::json::array_t storages;
+ for (const std::string& storagePath : storageList)
+ {
+ std::string id =
+ sdbusplus::message::object_path(storagePath).filename();
+ if (id.empty())
+ {
+ continue;
+ }
+
+ nlohmann::json::object_t storage;
+ storage["@odata.id"] =
+ boost::urls::format("/redfish/v1/Systems/{}/Storage/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, id);
+ storages.emplace_back(std::move(storage));
+ }
+ asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
+ storages.size();
+ asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages);
+ });
}
/**
@@ -103,34 +106,39 @@ inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> asyncResp)
"xyz.openbmc_project.State.Chassis", "CurrentPowerState",
[asyncResp{std::move(asyncResp)}](const boost::system::error_code& ec,
const std::string& chassisState) {
- if (ec)
- {
- if (ec == boost::system::errc::host_unreachable)
+ if (ec)
{
- // Service not available, no error, just don't return
- // chassis state info
- BMCWEB_LOG_DEBUG("Service not available {}", ec);
+ if (ec == boost::system::errc::host_unreachable)
+ {
+ // Service not available, no error, just don't return
+ // chassis state info
+ BMCWEB_LOG_DEBUG("Service not available {}", ec);
+ return;
+ }
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState);
- // Verify Chassis State
- if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- }
- else if (chassisState ==
- "xyz.openbmc_project.State.Chassis.PowerState.Off")
- {
- asyncResp->res.jsonValue["PowerState"] = "Off";
- asyncResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
- }
- });
+ BMCWEB_LOG_DEBUG("Chassis state: {}", chassisState);
+ // Verify Chassis State
+ if (chassisState ==
+ "xyz.openbmc_project.State.Chassis.PowerState.On")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+ }
+ else if (chassisState ==
+ "xyz.openbmc_project.State.Chassis.PowerState.Off")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::Off;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::StandbyOffline;
+ }
+ });
}
/**
@@ -162,19 +170,20 @@ inline void handlePhysicalSecurityGetSubTree(
"xyz.openbmc_project.Chassis.Intrusion", "Status",
[asyncResp](const boost::system::error_code& ec1,
const std::string& value) {
- if (ec1)
- {
- // do not add err msg in redfish response, because this is
- // not
- // mandatory property
- BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
- return;
- }
- asyncResp->res
- .jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1;
- asyncResp->res
- .jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value;
- });
+ if (ec1)
+ {
+ // do not add err msg in redfish response, because this
+ // is not
+ // mandatory property
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec1);
+ return;
+ }
+ asyncResp->res.jsonValue["PhysicalSecurity"]
+ ["IntrusionSensorNumber"] = 1;
+ asyncResp->res
+ .jsonValue["PhysicalSecurity"]["IntrusionSensor"] =
+ value;
+ });
return;
}
@@ -205,7 +214,7 @@ inline void handleChassisCollectionGet(
inline void getChassisContainedBy(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& chassisId, const boost::system::error_code& ec,
- const dbus::utility::MapperEndPoints& upstreamChassisPaths)
+ const dbus::utility::MapperGetSubTreePathsResponse& upstreamChassisPaths)
{
if (ec)
{
@@ -244,7 +253,7 @@ inline void getChassisContainedBy(
inline void getChassisContains(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& chassisId, const boost::system::error_code& ec,
- const dbus::utility::MapperEndPoints& downstreamChassisPaths)
+ const dbus::utility::MapperGetSubTreePathsResponse& downstreamChassisPaths)
{
if (ec)
{
@@ -276,27 +285,33 @@ inline void getChassisContains(
continue;
}
nlohmann::json link;
- link["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
- downstreamChassis);
+ link["@odata.id"] =
+ boost::urls::format("/redfish/v1/Chassis/{}", downstreamChassis);
jValue.push_back(std::move(link));
}
asyncResp->res.jsonValue["Links"]["Contains@odata.count"] = jValue.size();
}
-inline void
- getChassisConnectivity(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::string& chassisPath)
+inline void getChassisConnectivity(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const std::string& chassisPath)
{
BMCWEB_LOG_DEBUG("Get chassis connectivity");
- dbus::utility::getAssociationEndPoints(
+ constexpr std::array<std::string_view, 2> interfaces{
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+
+ dbus::utility::getAssociatedSubTreePaths(
chassisPath + "/contained_by",
+ sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
+ interfaces,
std::bind_front(getChassisContainedBy, asyncResp, chassisId));
- dbus::utility::getAssociationEndPoints(
+ dbus::utility::getAssociatedSubTreePaths(
chassisPath + "/containing",
- std::bind_front(getChassisContains, asyncResp, chassisId));
+ sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
+ interfaces, std::bind_front(getChassisContains, asyncResp, chassisId));
}
/**
@@ -311,26 +326,26 @@ inline void requestRoutesChassisCollection(App& app)
std::bind_front(handleChassisCollectionGet, std::ref(app)));
}
-inline void
- getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& connectionName,
- const std::string& path)
+inline void getChassisLocationCode(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& connectionName, const std::string& path)
{
sdbusplus::asio::getProperty<std::string>(
*crow::connections::systemBus, connectionName, path,
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
[asyncResp](const boost::system::error_code& ec,
const std::string& property) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error for Location");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Location");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- property;
- });
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+ property;
+ });
}
inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -342,14 +357,14 @@ inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"xyz.openbmc_project.Common.UUID", "UUID",
[asyncResp](const boost::system::error_code& ec,
const std::string& chassisUUID) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error for UUID");
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["UUID"] = chassisUUID;
- });
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for UUID");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["UUID"] = chassisUUID;
+ });
}
inline void handleDecoratorAssetProperties(
@@ -428,12 +443,12 @@ inline void handleDecoratorAssetProperties(
// SensorCollection
asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
boost::urls::format("/redfish/v1/Chassis/{}/Sensors", chassisId);
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
nlohmann::json::array_t computerSystems;
nlohmann::json::object_t system;
- system["@odata.id"] = std::format("/redfish/v1/Systems/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ system["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
computerSystems.emplace_back(std::move(system));
asyncResp->res.jsonValue["Links"]["ComputerSystems"] =
std::move(computerSystems);
@@ -487,7 +502,8 @@ inline void handleChassisGetSubTree(
asyncResp->res.jsonValue["@odata.id"] =
boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
asyncResp->res.jsonValue["Name"] = "Chassis Collection";
- asyncResp->res.jsonValue["ChassisType"] = "RackMount";
+ asyncResp->res.jsonValue["ChassisType"] =
+ chassis::ChassisType::RackMount;
asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
boost::urls::format("/redfish/v1/Chassis/{}/Actions/Chassis.Reset",
chassisId);
@@ -499,16 +515,16 @@ inline void handleChassisGetSubTree(
path + "/drive",
[asyncResp, chassisId](const boost::system::error_code& ec3,
const dbus::utility::MapperEndPoints& resp) {
- if (ec3 || resp.empty())
- {
- return; // no drives = no failures
- }
+ if (ec3 || resp.empty())
+ {
+ return; // no drives = no failures
+ }
- nlohmann::json reference;
- reference["@odata.id"] =
- boost::urls::format("/redfish/v1/Chassis/{}/Drives", chassisId);
- asyncResp->res.jsonValue["Drives"] = std::move(reference);
- });
+ nlohmann::json reference;
+ reference["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/Drives", chassisId);
+ asyncResp->res.jsonValue["Drives"] = std::move(reference);
+ });
const std::string& connectionName = connectionNames[0].first;
@@ -533,15 +549,15 @@ inline void handleChassisGetSubTree(
assetTagInterface, "AssetTag",
[asyncResp, chassisId](const boost::system::error_code& ec2,
const std::string& property) {
- if (ec2)
- {
- BMCWEB_LOG_ERROR("DBus response error for AssetTag: {}",
- ec2);
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["AssetTag"] = property;
- });
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBus response error for AssetTag: {}", ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["AssetTag"] = property;
+ });
}
else if (interface == replaceableInterface)
{
@@ -550,15 +566,16 @@ inline void handleChassisGetSubTree(
replaceableInterface, "HotPluggable",
[asyncResp, chassisId](const boost::system::error_code& ec2,
const bool property) {
- if (ec2)
- {
- BMCWEB_LOG_ERROR(
- "DBus response error for HotPluggable: {}", ec2);
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["HotPluggable"] = property;
- });
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBus response error for HotPluggable: {}",
+ ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["HotPluggable"] = property;
+ });
}
else if (interface == revisionInterface)
{
@@ -567,15 +584,15 @@ inline void handleChassisGetSubTree(
revisionInterface, "Version",
[asyncResp, chassisId](const boost::system::error_code& ec2,
const std::string& property) {
- if (ec2)
- {
- BMCWEB_LOG_ERROR("DBus response error for Version: {}",
- ec2);
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["Version"] = property;
- });
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBus response error for Version: {}", ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["Version"] = property;
+ });
}
}
@@ -595,9 +612,9 @@ inline void handleChassisGetSubTree(
[asyncResp, chassisId,
path](const boost::system::error_code&,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- handleDecoratorAssetProperties(asyncResp, chassisId, path,
- propertiesList);
- });
+ handleDecoratorAssetProperties(asyncResp, chassisId, path,
+ propertiesList);
+ });
for (const auto& interface : interfaces2)
{
@@ -691,81 +708,83 @@ inline void
[asyncResp, chassisId, locationIndicatorActive,
indicatorLed](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Iterate over all retrieved ObjectPaths.
- for (const std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- const std::string& path = object.first;
- const std::vector<std::pair<std::string, std::vector<std::string>>>&
- connectionNames = object.second;
-
- sdbusplus::message::object_path objPath(path);
- if (objPath.filename() != chassisId)
+ if (ec)
{
- continue;
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
}
- if (connectionNames.empty())
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>&
+ object : subtree)
{
- BMCWEB_LOG_ERROR("Got 0 Connection names");
- continue;
- }
-
- const std::vector<std::string>& interfaces3 =
- connectionNames[0].second;
+ const std::string& path = object.first;
+ const std::vector<
+ std::pair<std::string, std::vector<std::string>>>&
+ connectionNames = object.second;
- const std::array<const char*, 3> hasIndicatorLed = {
- "xyz.openbmc_project.Inventory.Item.Chassis",
- "xyz.openbmc_project.Inventory.Item.Panel",
- "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
- bool indicatorChassis = false;
- for (const char* interface : hasIndicatorLed)
- {
- if (std::ranges::find(interfaces3, interface) !=
- interfaces3.end())
+ sdbusplus::message::object_path objPath(path);
+ if (objPath.filename() != chassisId)
{
- indicatorChassis = true;
- break;
+ continue;
}
- }
- if (locationIndicatorActive)
- {
- if (indicatorChassis)
+
+ if (connectionNames.empty())
{
- setSystemLocationIndicatorActive(asyncResp,
- *locationIndicatorActive);
+ BMCWEB_LOG_ERROR("Got 0 Connection names");
+ continue;
}
- else
+
+ const std::vector<std::string>& interfaces3 =
+ connectionNames[0].second;
+
+ const std::array<const char*, 3> hasIndicatorLed = {
+ "xyz.openbmc_project.Inventory.Item.Chassis",
+ "xyz.openbmc_project.Inventory.Item.Panel",
+ "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
+ bool indicatorChassis = false;
+ for (const char* interface : hasIndicatorLed)
{
- messages::propertyUnknown(asyncResp->res,
- "LocationIndicatorActive");
+ if (std::ranges::find(interfaces3, interface) !=
+ interfaces3.end())
+ {
+ indicatorChassis = true;
+ break;
+ }
}
- }
- if (indicatorLed)
- {
- if (indicatorChassis)
+ if (locationIndicatorActive)
{
- setIndicatorLedState(asyncResp, *indicatorLed);
+ if (indicatorChassis)
+ {
+ setSystemLocationIndicatorActive(
+ asyncResp, *locationIndicatorActive);
+ }
+ else
+ {
+ messages::propertyUnknown(asyncResp->res,
+ "LocationIndicatorActive");
+ }
}
- else
+ if (indicatorLed)
{
- messages::propertyUnknown(asyncResp->res, "IndicatorLED");
+ if (indicatorChassis)
+ {
+ setIndicatorLedState(asyncResp, *indicatorLed);
+ }
+ else
+ {
+ messages::propertyUnknown(asyncResp->res,
+ "IndicatorLED");
+ }
}
+ return;
}
- return;
- }
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- });
+ messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+ });
}
/**
@@ -797,32 +816,34 @@ inline void
[asyncResp](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- const char* processName = "xyz.openbmc_project.State.Chassis";
- const char* interfaceName = "xyz.openbmc_project.State.Chassis";
- const char* destProperty = "RequestedPowerTransition";
- const std::string propertyValue =
- "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
- std::string objectPath = "/xyz/openbmc_project/state/chassis_system0";
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("[mapper] Bad D-Bus request error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- /* Look for system reset chassis path */
- if ((std::ranges::find(chassisList, objectPath)) == chassisList.end())
- {
- /* We prefer to reset the full chassis_system, but if it doesn't
- * exist on some platforms, fall back to a host-only power reset
- */
- objectPath = "/xyz/openbmc_project/state/chassis0";
- }
+ const char* processName = "xyz.openbmc_project.State.Chassis";
+ const char* interfaceName = "xyz.openbmc_project.State.Chassis";
+ const char* destProperty = "RequestedPowerTransition";
+ const std::string propertyValue =
+ "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
+ std::string objectPath =
+ "/xyz/openbmc_project/state/chassis_system0";
+
+ /* Look for system reset chassis path */
+ if ((std::ranges::find(chassisList, objectPath)) ==
+ chassisList.end())
+ {
+ /* We prefer to reset the full chassis_system, but if it doesn't
+ * exist on some platforms, fall back to a host-only power reset
+ */
+ objectPath = "/xyz/openbmc_project/state/chassis0";
+ }
- setDbusProperty(asyncResp, "ResetType", processName, objectPath,
- interfaceName, destProperty, propertyValue);
- });
+ setDbusProperty(asyncResp, "ResetType", processName, objectPath,
+ interfaceName, destProperty, propertyValue);
+ });
}
inline void handleChassisResetActionInfoPost(
@@ -888,7 +909,7 @@ inline void handleChassisResetActionInfoGet(
nlohmann::json::object_t parameter;
parameter["Name"] = "ResetType";
parameter["Required"] = true;
- parameter["DataType"] = "String";
+ parameter["DataType"] = action_info::ParameterTypes::String;
nlohmann::json::array_t allowed;
allowed.emplace_back("PowerCycle");
parameter["AllowableValues"] = std::move(allowed);
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index a3cda9ca38..d8c5ae358e 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -19,6 +19,8 @@
#include "dbus_singleton.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
+#include "generated/enums/ethernet_interface.hpp"
+#include "generated/enums/resource.hpp"
#include "human_sort.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
@@ -116,7 +118,7 @@ struct EthernetInterfaceData
std::string defaultGateway;
std::string ipv6DefaultGateway;
std::string ipv6StaticDefaultGateway;
- std::string macAddress;
+ std::optional<std::string> macAddress;
std::optional<uint32_t> vlanId;
std::vector<std::string> nameServers;
std::vector<std::string> staticNameServers;
@@ -178,9 +180,8 @@ inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
}
-inline std::string
- translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
- bool isIPv4)
+inline std::string translateAddressOriginDbusToRedfish(
+ const std::string& inputOrigin, bool isIPv4)
{
if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
{
@@ -393,8 +394,8 @@ inline bool extractEthernetInterfaceData(
sdbusplus::message::object_path path(
"/xyz/openbmc_project/network");
- sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
- "dhcp4";
+ sdbusplus::message::object_path dhcp4Path =
+ path / ethifaceId / "dhcp4";
if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
{
@@ -443,8 +444,8 @@ inline bool extractEthernetInterfaceData(
}
}
- sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
- "dhcp6";
+ sdbusplus::message::object_path dhcp6Path =
+ path / ethifaceId / "dhcp6";
if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
{
@@ -520,8 +521,8 @@ inline void extractIPV6Data(const std::string& ethifaceId,
const dbus::utility::ManagedObjectType& dbusData,
std::vector<IPv6AddressData>& ipv6Config)
{
- const std::string ipPathStart = "/xyz/openbmc_project/network/" +
- ethifaceId;
+ const std::string ipPathStart =
+ "/xyz/openbmc_project/network/" + ethifaceId;
// Since there might be several IPv6 configurations aligned with
// single ethernet interface, loop over all of them
@@ -534,10 +535,10 @@ inline void extractIPV6Data(const std::string& ethifaceId,
{
if (interface.first == "xyz.openbmc_project.Network.IP")
{
- auto type = std::ranges::find_if(interface.second,
- [](const auto& property) {
- return property.first == "Type";
- });
+ auto type = std::ranges::find_if(
+ interface.second, [](const auto& property) {
+ return property.first == "Type";
+ });
if (type == interface.second.end())
{
continue;
@@ -612,8 +613,8 @@ inline void extractIPData(const std::string& ethifaceId,
const dbus::utility::ManagedObjectType& dbusData,
std::vector<IPv4AddressData>& ipv4Config)
{
- const std::string ipPathStart = "/xyz/openbmc_project/network/" +
- ethifaceId;
+ const std::string ipPathStart =
+ "/xyz/openbmc_project/network/" + ethifaceId;
// Since there might be several IPv4 configurations aligned with
// single ethernet interface, loop over all of them
@@ -626,10 +627,10 @@ inline void extractIPData(const std::string& ethifaceId,
{
if (interface.first == "xyz.openbmc_project.Network.IP")
{
- auto type = std::ranges::find_if(interface.second,
- [](const auto& property) {
- return property.first == "Type";
- });
+ auto type = std::ranges::find_if(
+ interface.second, [](const auto& property) {
+ return property.first == "Type";
+ });
if (type == interface.second.end())
{
continue;
@@ -743,11 +744,11 @@ inline void deleteIPAddress(const std::string& ifaceId,
{
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- }
- },
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ },
"xyz.openbmc_project.Network",
"/xyz/openbmc_project/network/" + ifaceId + ipHash,
"xyz.openbmc_project.Object.Delete", "Delete");
@@ -768,14 +769,14 @@ inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
const std::string& gateway, const std::string& address,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
- auto createIpHandler = [asyncResp, ifaceId,
- gateway](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- };
+ auto createIpHandler =
+ [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ };
crow::connections::systemBus->async_method_call(
std::move(createIpHandler), "xyz.openbmc_project.Network",
@@ -808,24 +809,24 @@ inline void deleteAndCreateIPAddress(
crow::connections::systemBus->async_method_call(
[asyncResp, version, ifaceId, address, prefixLength,
gateway](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- }
- std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
- protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec2) {
- if (ec2)
+ if (ec)
{
messages::internalError(asyncResp->res);
}
+ std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
+ protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec2) {
+ if (ec2)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ },
+ "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId,
+ "xyz.openbmc_project.Network.IP.Create", "IP", protocol,
+ address, prefixLength, gateway);
},
- "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/" + ifaceId,
- "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
- prefixLength, gateway);
- },
"xyz.openbmc_project.Network",
"/xyz/openbmc_project/network/" + ifaceId + id,
"xyz.openbmc_project.Object.Delete", "Delete");
@@ -858,8 +859,7 @@ inline bool extractIPv6DefaultGatewayData(
bool success = sdbusplus::unpackPropertiesNoThrow(
redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
- "Gateway", staticGateway.gateway, "PrefixLength",
- staticGateway.prefixLength, "ProtocolType",
+ "Gateway", staticGateway.gateway, "ProtocolType",
staticGateway.protocol);
if (!success)
{
@@ -887,21 +887,21 @@ inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
sdbusplus::message::object_path path("/xyz/openbmc_project/network");
path /= ifaceId;
- auto createIpHandler = [asyncResp,
- address](const boost::system::error_code& ec) {
- if (ec)
- {
- if (ec == boost::system::errc::io_error)
+ auto createIpHandler =
+ [asyncResp, address](const boost::system::error_code& ec) {
+ if (ec)
{
- messages::propertyValueFormatError(asyncResp->res, address,
- "Address");
- }
- else
- {
- messages::internalError(asyncResp->res);
+ if (ec == boost::system::errc::io_error)
+ {
+ messages::propertyValueFormatError(asyncResp->res, address,
+ "Address");
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
}
- }
- };
+ };
// Passing null for gateway, as per redfish spec IPv6StaticAddresses
// object does not have associated gateway property
crow::connections::systemBus->async_method_call(
@@ -921,18 +921,19 @@ inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
* @return None
*/
inline void
- deleteIPv6Gateway(std::string_view gatewayId,
+ deleteIPv6Gateway(std::string_view ifaceId, std::string_view gatewayId,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
sdbusplus::message::object_path path("/xyz/openbmc_project/network");
+ path /= ifaceId;
path /= gatewayId;
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- }
- },
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ },
"xyz.openbmc_project.Network", path,
"xyz.openbmc_project.Object.Delete", "Delete");
}
@@ -941,14 +942,13 @@ inline void
* @brief Creates IPv6 static default gateway with given data
*
* @param[in] ifaceId Id of interface whose IP should be added
- * @param[in] prefixLength Prefix length that needs to be added
* @param[in] gateway Gateway address that needs to be added
* @param[io] asyncResp Response object that will be returned to client
*
* @return None
*/
inline void createIPv6DefaultGateway(
- std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
+ std::string_view ifaceId, std::string_view gateway,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
sdbusplus::message::object_path path("/xyz/openbmc_project/network");
@@ -962,7 +962,7 @@ inline void createIPv6DefaultGateway(
crow::connections::systemBus->async_method_call(
std::move(createIpHandler), "xyz.openbmc_project.Network", path,
"xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
- gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
+ gateway, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
}
/**
@@ -972,28 +972,27 @@ inline void createIPv6DefaultGateway(
* @param[in] ifaceId Id of interface upon which to create the IPv6
* entry
* @param[in] gateway IPv6 gateway to assign to this interface
- * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
* @param[io] asyncResp Response object that will be returned to client
*
* @return None
*/
inline void deleteAndCreateIPv6DefaultGateway(
std::string_view ifaceId, std::string_view gatewayId,
- std::string_view gateway, size_t prefixLength,
+ std::string_view gateway,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
sdbusplus::message::object_path path("/xyz/openbmc_project/network");
+ path /= ifaceId;
path /= gatewayId;
crow::connections::systemBus->async_method_call(
- [asyncResp, ifaceId, gateway,
- prefixLength](const boost::system::error_code& ec) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
- },
+ [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ createIPv6DefaultGateway(ifaceId, gateway, asyncResp);
+ },
"xyz.openbmc_project.Network", path,
"xyz.openbmc_project.Object.Delete", "Delete");
}
@@ -1032,8 +1031,8 @@ inline void handleIPv6DefaultGateway(
}
staticGatewayEntry++;
}
- std::string pathString = "IPv6StaticDefaultGateways/" +
- std::to_string(entryIdx);
+ std::string pathString =
+ "IPv6StaticDefaultGateways/" + std::to_string(entryIdx);
nlohmann::json::object_t* obj =
std::get_if<nlohmann::json::object_t>(&thisJson);
if (obj == nullptr)
@@ -1043,7 +1042,7 @@ inline void handleIPv6DefaultGateway(
messages::resourceCannotBeDeleted(asyncResp->res);
return;
}
- deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
+ deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp);
return;
}
if (obj->empty())
@@ -1057,15 +1056,13 @@ inline void handleIPv6DefaultGateway(
}
}
std::optional<std::string> address;
- std::optional<size_t> prefixLength;
- if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address,
- "PrefixLength", prefixLength))
+ if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
+ address))
{
return;
}
const std::string* addr = nullptr;
- size_t prefix = 0;
if (address)
{
addr = &(*address);
@@ -1079,29 +1076,15 @@ inline void handleIPv6DefaultGateway(
messages::propertyMissing(asyncResp->res, pathString + "/Address");
return;
}
- if (prefixLength)
- {
- prefix = *prefixLength;
- }
- else if (staticGatewayEntry != staticGatewayData.end())
- {
- prefix = staticGatewayEntry->prefixLength;
- }
- else
- {
- messages::propertyMissing(asyncResp->res,
- pathString + "/PrefixLength");
- return;
- }
if (staticGatewayEntry != staticGatewayData.end())
{
deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
- *addr, prefix, asyncResp);
+ *addr, asyncResp);
staticGatewayEntry++;
}
else
{
- createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
+ createIPv6DefaultGateway(ifaceId, *addr, asyncResp);
}
entryIdx++;
}
@@ -1126,44 +1109,46 @@ void getEthernetIfaceData(const std::string& ethifaceId,
callback = std::forward<CallbackFunc>(callback)](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& resp) mutable {
- EthernetInterfaceData ethData{};
- std::vector<IPv4AddressData> ipv4Data;
- std::vector<IPv6AddressData> ipv6Data;
- std::vector<StaticGatewayData> ipv6GatewayData;
+ EthernetInterfaceData ethData{};
+ std::vector<IPv4AddressData> ipv4Data;
+ std::vector<IPv6AddressData> ipv6Data;
+ std::vector<StaticGatewayData> ipv6GatewayData;
- if (ec)
- {
- callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
- return;
- }
+ if (ec)
+ {
+ callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
+ return;
+ }
- bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
- if (!found)
- {
- callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
- return;
- }
+ bool found =
+ extractEthernetInterfaceData(ethifaceId, resp, ethData);
+ if (!found)
+ {
+ callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
+ return;
+ }
- extractIPData(ethifaceId, resp, ipv4Data);
- // Fix global GW
- for (IPv4AddressData& ipv4 : ipv4Data)
- {
- if (((ipv4.linktype == LinkType::Global) &&
- (ipv4.gateway == "0.0.0.0")) ||
- (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
+ extractIPData(ethifaceId, resp, ipv4Data);
+ // Fix global GW
+ for (IPv4AddressData& ipv4 : ipv4Data)
{
- ipv4.gateway = ethData.defaultGateway;
+ if (((ipv4.linktype == LinkType::Global) &&
+ (ipv4.gateway == "0.0.0.0")) ||
+ (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
+ {
+ ipv4.gateway = ethData.defaultGateway;
+ }
}
- }
- extractIPV6Data(ethifaceId, resp, ipv6Data);
- if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
- {
- callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
- }
- // Finally make a callback with useful data
- callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
- });
+ extractIPV6Data(ethifaceId, resp, ipv6Data);
+ if (!extractIPv6DefaultGatewayData(ethifaceId, resp,
+ ipv6GatewayData))
+ {
+ callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
+ }
+ // Finally make a callback with useful data
+ callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
+ });
}
/**
@@ -1181,44 +1166,44 @@ void getEthernetIfaceList(CallbackFunc&& callback)
[callback = std::forward<CallbackFunc>(callback)](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& resp) {
- // Callback requires vector<string> to retrieve all available
- // ethernet interfaces
- std::vector<std::string> ifaceList;
- ifaceList.reserve(resp.size());
- if (ec)
- {
- callback(false, ifaceList);
- return;
- }
+ // Callback requires vector<string> to retrieve all available
+ // ethernet interfaces
+ std::vector<std::string> ifaceList;
+ ifaceList.reserve(resp.size());
+ if (ec)
+ {
+ callback(false, ifaceList);
+ return;
+ }
- // Iterate over all retrieved ObjectPaths.
- for (const auto& objpath : resp)
- {
- // And all interfaces available for certain ObjectPath.
- for (const auto& interface : objpath.second)
+ // Iterate over all retrieved ObjectPaths.
+ for (const auto& objpath : resp)
{
- // If interface is
- // xyz.openbmc_project.Network.EthernetInterface, this is
- // what we're looking for.
- if (interface.first ==
- "xyz.openbmc_project.Network.EthernetInterface")
+ // And all interfaces available for certain ObjectPath.
+ for (const auto& interface : objpath.second)
{
- std::string ifaceId = objpath.first.filename();
- if (ifaceId.empty())
+ // If interface is
+ // xyz.openbmc_project.Network.EthernetInterface, this is
+ // what we're looking for.
+ if (interface.first ==
+ "xyz.openbmc_project.Network.EthernetInterface")
{
- continue;
+ std::string ifaceId = objpath.first.filename();
+ if (ifaceId.empty())
+ {
+ continue;
+ }
+ // and put it into output vector.
+ ifaceList.emplace_back(ifaceId);
}
- // and put it into output vector.
- ifaceList.emplace_back(ifaceId);
}
}
- }
- std::ranges::sort(ifaceList, AlphanumLess<std::string>());
+ std::ranges::sort(ifaceList, AlphanumLess<std::string>());
- // Finally make a callback with useful data
- callback(true, ifaceList);
- });
+ // Finally make a callback with useful data
+ callback(true, ifaceList);
+ });
}
inline void
@@ -1250,10 +1235,9 @@ inline void
"MTU", mtuSize);
}
-inline void
- handleDomainnamePatch(const std::string& ifaceId,
- const std::string& domainname,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+inline void handleDomainnamePatch(
+ const std::string& ifaceId, const std::string& domainname,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
std::vector<std::string> vectorDomainname = {domainname};
setDbusProperty(
@@ -1323,10 +1307,9 @@ inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
handleDomainnamePatch(ifaceId, domainname, asyncResp);
}
-inline void
- handleMACAddressPatch(const std::string& ifaceId,
- const std::string& macAddress,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+inline void handleMACAddressPatch(
+ const std::string& ifaceId, const std::string& macAddress,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
setDbusProperty(
asyncResp, "MACAddress", "xyz.openbmc_project.Network",
@@ -1392,11 +1375,10 @@ inline void handleSLAACAutoConfigPatch(
"IPv6AcceptRA", ipv6AutoConfigEnabled);
}
-inline void handleDHCPPatch(const std::string& ifaceId,
- const EthernetInterfaceData& ethData,
- const DHCPParameters& v4dhcpParms,
- const DHCPParameters& v6dhcpParms,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+inline void handleDHCPPatch(
+ const std::string& ifaceId, const EthernetInterfaceData& ethData,
+ const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
@@ -1532,8 +1514,8 @@ inline void handleIPv4StaticPatch(
for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
input)
{
- std::string pathString = "IPv4StaticAddresses/" +
- std::to_string(entryIdx);
+ std::string pathString =
+ "IPv4StaticAddresses/" + std::to_string(entryIdx);
nlohmann::json::object_t* obj =
std::get_if<nlohmann::json::object_t>(&thisJson);
if (obj == nullptr)
@@ -1541,8 +1523,8 @@ inline void handleIPv4StaticPatch(
if (nicIpEntry != ipv4Data.cend())
{
deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
- nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
- ipv4Data.cend());
+ nicIpEntry =
+ getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend());
if (!preserveGateway && (nicIpEntry == ipv4Data.cend()))
{
// All entries have been processed, and this last has
@@ -1678,8 +1660,8 @@ inline void handleIPv4StaticPatch(
deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
nicIpEntry->id, prefixLength, *address,
*gateway, asyncResp);
- nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
- ipv4Data.cend());
+ nicIpEntry =
+ getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend());
preserveGateway = true;
}
else
@@ -1695,8 +1677,8 @@ inline void handleIPv4StaticPatch(
// Received {}, do not modify this address
if (nicIpEntry != ipv4Data.cend())
{
- nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
- ipv4Data.cend());
+ nicIpEntry =
+ getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend());
preserveGateway = true;
entryIdx++;
}
@@ -1737,8 +1719,8 @@ inline void handleIPv6StaticAddressesPatch(
for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
input)
{
- std::string pathString = "IPv6StaticAddresses/" +
- std::to_string(entryIdx);
+ std::string pathString =
+ "IPv6StaticAddresses/" + std::to_string(entryIdx);
nlohmann::json::object_t* obj =
std::get_if<nlohmann::json::object_t>(&thisJson);
if (obj != nullptr && !obj->empty())
@@ -1786,8 +1768,8 @@ inline void handleIPv6StaticAddressesPatch(
deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
nicIpEntry->id, *prefixLength,
*address, "", asyncResp);
- nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
- ipv6Data.cend());
+ nicIpEntry =
+ getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend());
}
else
{
@@ -1818,8 +1800,8 @@ inline void handleIPv6StaticAddressesPatch(
}
if (nicIpEntry != ipv6Data.cend())
{
- nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
- ipv6Data.cend());
+ nicIpEntry =
+ getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend());
}
entryIdx++;
}
@@ -1832,13 +1814,12 @@ inline std::string extractParentInterfaceName(const std::string& ifaceId)
return ifaceId.substr(0, pos);
}
-inline void
- parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& ifaceId,
- const EthernetInterfaceData& ethData,
- const std::vector<IPv4AddressData>& ipv4Data,
- const std::vector<IPv6AddressData>& ipv6Data,
- const std::vector<StaticGatewayData>& ipv6GatewayData)
+inline void parseInterfaceData(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& ifaceId, const EthernetInterfaceData& ethData,
+ const std::vector<IPv4AddressData>& ipv4Data,
+ const std::vector<IPv6AddressData>& ipv6Data,
+ const std::vector<StaticGatewayData>& ipv6GatewayData)
{
nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
jsonResponse["Id"] = ifaceId;
@@ -1849,26 +1830,32 @@ inline void
if (ethData.nicEnabled)
{
- jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
- jsonResponse["Status"]["State"] = "Enabled";
+ jsonResponse["LinkStatus"] =
+ ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp
+ : ethernet_interface::LinkStatus::LinkDown;
+ jsonResponse["Status"]["State"] = resource::State::Enabled;
}
else
{
- jsonResponse["LinkStatus"] = "NoLink";
- jsonResponse["Status"]["State"] = "Disabled";
+ jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink;
+ jsonResponse["Status"]["State"] = resource::State::Disabled;
}
jsonResponse["SpeedMbps"] = ethData.speed;
jsonResponse["MTUSize"] = ethData.mtuSize;
- jsonResponse["MACAddress"] = ethData.macAddress;
+ if (ethData.macAddress)
+ {
+ jsonResponse["MACAddress"] = *ethData.macAddress;
+ }
jsonResponse["DHCPv4"]["DHCPEnabled"] =
translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled;
jsonResponse["DHCPv6"]["OperatingMode"] =
- translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
- : "Disabled";
+ translateDhcpEnabledToBool(ethData.dhcpEnabled, false)
+ ? "Enabled"
+ : "Disabled";
jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled;
@@ -1892,7 +1879,8 @@ inline void
if (ethData.vlanId)
{
- jsonResponse["EthernetInterfaceType"] = "Virtual";
+ jsonResponse["EthernetInterfaceType"] =
+ ethernet_interface::EthernetDeviceType::Virtual;
jsonResponse["VLAN"]["VLANEnable"] = true;
jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
jsonResponse["VLAN"]["Tagged"] = true;
@@ -1908,7 +1896,8 @@ inline void
}
else
{
- jsonResponse["EthernetInterfaceType"] = "Physical";
+ jsonResponse["EthernetInterfaceType"] =
+ ethernet_interface::EthernetDeviceType::Physical;
}
jsonResponse["NameServers"] = ethData.nameServers;
@@ -1952,7 +1941,6 @@ inline void
{
nlohmann::json::object_t ipv6Gateway;
ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
- ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
}
jsonResponse["IPv6StaticDefaultGateways"] =
@@ -2016,11 +2004,10 @@ inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
messages::internalError(asyncResp->res);
}
-inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& parentInterfaceUri,
- const std::string& vlanInterface,
- const boost::system::error_code& ec,
- const sdbusplus::message_t& m
+inline void afterVlanCreate(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& parentInterfaceUri, const std::string& vlanInterface,
+ const boost::system::error_code& ec, const sdbusplus::message_t& m
)
{
@@ -2069,55 +2056,59 @@ inline void requestEthernetInterfacesRoutes(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EthernetInterfaceCollection.EthernetInterfaceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["Name"] =
- "Ethernet Network Interface Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of EthernetInterfaces for this Manager";
-
- // Get eth interface list, and call the below callback for JSON
- // preparation
- getEthernetIfaceList(
- [asyncResp](const bool& success,
- const std::vector<std::string>& ifaceList) {
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EthernetInterfaceCollection.EthernetInterfaceCollection";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/EthernetInterfaces",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["Name"] =
+ "Ethernet Network Interface Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of EthernetInterfaces for this Manager";
+
+ // Get eth interface list, and call the below callback for JSON
+ // preparation
+ getEthernetIfaceList(
+ [asyncResp](const bool& success,
+ const std::vector<std::string>& ifaceList) {
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
- ifaceArray = nlohmann::json::array();
- for (const std::string& ifaceItem : ifaceList)
- {
- nlohmann::json::object_t iface;
- iface["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/EthernetInterfaces/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem);
- ifaceArray.push_back(std::move(iface));
- }
+ nlohmann::json& ifaceArray =
+ asyncResp->res.jsonValue["Members"];
+ ifaceArray = nlohmann::json::array();
+ for (const std::string& ifaceItem : ifaceList)
+ {
+ nlohmann::json::object_t iface;
+ iface["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/EthernetInterfaces/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem);
+ ifaceArray.push_back(std::move(iface));
+ }
- asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/EthernetInterfaces",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- });
- });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ ifaceArray.size();
+ asyncResp->res.jsonValue["@odata.id"] =
+ boost::urls::format(
+ "/redfish/v1/Managers/{}/EthernetInterfaces",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ });
+ });
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
.privileges(redfish::privileges::postEthernetInterfaceCollection)
@@ -2125,90 +2116,93 @@ inline void requestEthernetInterfacesRoutes(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- bool vlanEnable = false;
- uint32_t vlanId = 0;
- std::vector<nlohmann::json::object_t> relatedInterfaces;
+ bool vlanEnable = false;
+ uint32_t vlanId = 0;
+ std::vector<nlohmann::json::object_t> relatedInterfaces;
- if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
- vlanEnable, "VLAN/VLANId", vlanId,
- "Links/RelatedInterfaces",
- relatedInterfaces))
- {
- return;
- }
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "VLAN/VLANEnable", vlanEnable,
+ "VLAN/VLANId", vlanId, "Links/RelatedInterfaces",
+ relatedInterfaces))
+ {
+ return;
+ }
- if (relatedInterfaces.size() != 1)
- {
- messages::arraySizeTooLong(asyncResp->res,
- "Links/RelatedInterfaces",
- relatedInterfaces.size());
- return;
- }
+ if (relatedInterfaces.size() != 1)
+ {
+ messages::arraySizeTooLong(asyncResp->res,
+ "Links/RelatedInterfaces",
+ relatedInterfaces.size());
+ return;
+ }
- std::string parentInterfaceUri;
- if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res,
- "@odata.id", parentInterfaceUri))
- {
- messages::propertyMissing(asyncResp->res,
- "Links/RelatedInterfaces/0/@odata.id");
- return;
- }
- BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
+ std::string parentInterfaceUri;
+ if (!json_util::readJsonObject(relatedInterfaces[0],
+ asyncResp->res, "@odata.id",
+ parentInterfaceUri))
+ {
+ messages::propertyMissing(
+ asyncResp->res, "Links/RelatedInterfaces/0/@odata.id");
+ return;
+ }
+ BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
- boost::system::result<boost::urls::url_view> parsedUri =
- boost::urls::parse_relative_ref(parentInterfaceUri);
- if (!parsedUri)
- {
- messages::propertyValueFormatError(
- asyncResp->res, parentInterfaceUri,
- "Links/RelatedInterfaces/0/@odata.id");
- return;
- }
+ boost::system::result<boost::urls::url_view> parsedUri =
+ boost::urls::parse_relative_ref(parentInterfaceUri);
+ if (!parsedUri)
+ {
+ messages::propertyValueFormatError(
+ asyncResp->res, parentInterfaceUri,
+ "Links/RelatedInterfaces/0/@odata.id");
+ return;
+ }
- std::string parentInterface;
- if (!crow::utility::readUrlSegments(
- *parsedUri, "redfish", "v1", "Managers", "bmc",
- "EthernetInterfaces", std::ref(parentInterface)))
- {
- messages::propertyValueNotInList(
- asyncResp->res, parentInterfaceUri,
- "Links/RelatedInterfaces/0/@odata.id");
- return;
- }
+ std::string parentInterface;
+ if (!crow::utility::readUrlSegments(
+ *parsedUri, "redfish", "v1", "Managers", "bmc",
+ "EthernetInterfaces", std::ref(parentInterface)))
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, parentInterfaceUri,
+ "Links/RelatedInterfaces/0/@odata.id");
+ return;
+ }
- if (!vlanEnable)
- {
- // In OpenBMC implementation, VLANEnable cannot be false on
- // create
- messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
- "false");
- return;
- }
+ if (!vlanEnable)
+ {
+ // In OpenBMC implementation, VLANEnable cannot be false on
+ // create
+ messages::propertyValueIncorrect(
+ asyncResp->res, "VLAN/VLANEnable", "false");
+ return;
+ }
- std::string vlanInterface = parentInterface + "_" +
- std::to_string(vlanId);
- crow::connections::systemBus->async_method_call(
- [asyncResp, parentInterfaceUri,
- vlanInterface](const boost::system::error_code& ec,
- const sdbusplus::message_t& m) {
- afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
- m);
- },
- "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
- "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
- vlanId);
- });
+ std::string vlanInterface =
+ parentInterface + "_" + std::to_string(vlanId);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, parentInterfaceUri,
+ vlanInterface](const boost::system::error_code& ec,
+ const sdbusplus::message_t& m) {
+ afterVlanCreate(asyncResp, parentInterfaceUri,
+ vlanInterface, ec, m);
+ },
+ "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network",
+ "xyz.openbmc_project.Network.VLAN.Create", "VLAN",
+ parentInterface, vlanId);
+ });
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
.privileges(redfish::privileges::getEthernetInterface)
@@ -2216,43 +2210,46 @@ inline void requestEthernetInterfacesRoutes(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId, const std::string& ifaceId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- getEthernetIfaceData(
- ifaceId,
- [asyncResp,
- ifaceId](const bool& success, const EthernetInterfaceData& ethData,
- const std::vector<IPv4AddressData>& ipv4Data,
- const std::vector<IPv6AddressData>& ipv6Data,
- const std::vector<StaticGatewayData>& ipv6GatewayData) {
- if (!success)
- {
- // TODO(Pawel)consider distinguish between non
- // existing object, and other errors
- messages::resourceNotFound(asyncResp->res, "EthernetInterface",
- ifaceId);
- return;
- }
+ getEthernetIfaceData(
+ ifaceId,
+ [asyncResp, ifaceId](
+ const bool& success,
+ const EthernetInterfaceData& ethData,
+ const std::vector<IPv4AddressData>& ipv4Data,
+ const std::vector<IPv6AddressData>& ipv6Data,
+ const std::vector<StaticGatewayData>& ipv6GatewayData) {
+ if (!success)
+ {
+ // TODO(Pawel)consider distinguish between non
+ // existing object, and other errors
+ messages::resourceNotFound(
+ asyncResp->res, "EthernetInterface", ifaceId);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EthernetInterface.v1_9_0.EthernetInterface";
- asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
- asyncResp->res.jsonValue["Description"] =
- "Management Network Interface";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EthernetInterface.v1_9_0.EthernetInterface";
+ asyncResp->res.jsonValue["Name"] =
+ "Manager Ethernet Interface";
+ asyncResp->res.jsonValue["Description"] =
+ "Management Network Interface";
- parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
- ipv6GatewayData);
- });
- });
+ parseInterfaceData(asyncResp, ifaceId, ethData,
+ ipv4Data, ipv6Data, ipv6GatewayData);
+ });
+ });
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
.privileges(redfish::privileges::patchEthernetInterface)
@@ -2260,37 +2257,38 @@ inline void requestEthernetInterfacesRoutes(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId, const std::string& ifaceId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- std::optional<std::string> hostname;
- std::optional<std::string> fqdn;
- std::optional<std::string> macAddress;
- std::optional<std::string> ipv6DefaultGateway;
- std::optional<
- std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
- ipv4StaticAddresses;
- std::optional<
- std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
- ipv6StaticAddresses;
- std::optional<
- std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
- ipv6StaticDefaultGateways;
- std::optional<std::vector<std::string>> staticNameServers;
- std::optional<bool> ipv6AutoConfigEnabled;
- std::optional<bool> interfaceEnabled;
- std::optional<size_t> mtuSize;
- DHCPParameters v4dhcpParms;
- DHCPParameters v6dhcpParms;
- // clang-format off
+ std::optional<std::string> hostname;
+ std::optional<std::string> fqdn;
+ std::optional<std::string> macAddress;
+ std::optional<std::string> ipv6DefaultGateway;
+ std::optional<std::vector<
+ std::variant<nlohmann::json::object_t, std::nullptr_t>>>
+ ipv4StaticAddresses;
+ std::optional<std::vector<
+ std::variant<nlohmann::json::object_t, std::nullptr_t>>>
+ ipv6StaticAddresses;
+ std::optional<std::vector<
+ std::variant<nlohmann::json::object_t, std::nullptr_t>>>
+ ipv6StaticDefaultGateways;
+ std::optional<std::vector<std::string>> staticNameServers;
+ std::optional<bool> ipv6AutoConfigEnabled;
+ std::optional<bool> interfaceEnabled;
+ std::optional<size_t> mtuSize;
+ DHCPParameters v4dhcpParms;
+ DHCPParameters v6dhcpParms;
+ // clang-format off
if (!json_util::readJsonPatch(req, asyncResp->res,
"DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled,
"DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers,
@@ -2316,106 +2314,114 @@ inline void requestEthernetInterfacesRoutes(App& app)
{
return;
}
- // clang-format on
-
- // Get single eth interface data, and call the below callback
- // for JSON preparation
- getEthernetIfaceData(
- ifaceId,
- [asyncResp, ifaceId, hostname = std::move(hostname),
- fqdn = std::move(fqdn), macAddress = std::move(macAddress),
- ipv4StaticAddresses = std::move(ipv4StaticAddresses),
- ipv6DefaultGateway = std::move(ipv6DefaultGateway),
- ipv6StaticAddresses = std::move(ipv6StaticAddresses),
- ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
- staticNameServers = std::move(staticNameServers), mtuSize,
- ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
- v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
- const bool success, const EthernetInterfaceData& ethData,
- const std::vector<IPv4AddressData>& ipv4Data,
- const std::vector<IPv6AddressData>& ipv6Data,
- const std::vector<StaticGatewayData>& ipv6GatewayData) mutable {
- if (!success)
- {
- // ... otherwise return error
- // TODO(Pawel)consider distinguish between non
- // existing object, and other errors
- messages::resourceNotFound(asyncResp->res, "EthernetInterface",
- ifaceId);
- return;
- }
+ // clang-format on
+
+ // Get single eth interface data, and call the below callback
+ // for JSON preparation
+ getEthernetIfaceData(
+ ifaceId,
+ [asyncResp, ifaceId, hostname = std::move(hostname),
+ fqdn = std::move(fqdn), macAddress = std::move(macAddress),
+ ipv4StaticAddresses = std::move(ipv4StaticAddresses),
+ ipv6DefaultGateway = std::move(ipv6DefaultGateway),
+ ipv6StaticAddresses = std::move(ipv6StaticAddresses),
+ ipv6StaticDefaultGateway =
+ std::move(ipv6StaticDefaultGateways),
+ staticNameServers = std::move(staticNameServers), mtuSize,
+ ipv6AutoConfigEnabled,
+ v4dhcpParms = std::move(v4dhcpParms),
+ v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
+ const bool success,
+ const EthernetInterfaceData& ethData,
+ const std::vector<IPv4AddressData>& ipv4Data,
+ const std::vector<IPv6AddressData>& ipv6Data,
+ const std::vector<StaticGatewayData>&
+ ipv6GatewayData) mutable {
+ if (!success)
+ {
+ // ... otherwise return error
+ // TODO(Pawel)consider distinguish between non
+ // existing object, and other errors
+ messages::resourceNotFound(
+ asyncResp->res, "EthernetInterface", ifaceId);
+ return;
+ }
- handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
- asyncResp);
+ handleDHCPPatch(ifaceId, ethData, v4dhcpParms,
+ v6dhcpParms, asyncResp);
- if (hostname)
- {
- handleHostnamePatch(*hostname, asyncResp);
- }
+ if (hostname)
+ {
+ handleHostnamePatch(*hostname, asyncResp);
+ }
- if (ipv6AutoConfigEnabled)
- {
- handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
- asyncResp);
- }
+ if (ipv6AutoConfigEnabled)
+ {
+ handleSLAACAutoConfigPatch(
+ ifaceId, *ipv6AutoConfigEnabled, asyncResp);
+ }
- if (fqdn)
- {
- handleFqdnPatch(ifaceId, *fqdn, asyncResp);
- }
+ if (fqdn)
+ {
+ handleFqdnPatch(ifaceId, *fqdn, asyncResp);
+ }
- if (macAddress)
- {
- handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
- }
+ if (macAddress)
+ {
+ handleMACAddressPatch(ifaceId, *macAddress,
+ asyncResp);
+ }
- if (ipv4StaticAddresses)
- {
- handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ethData,
- ipv4Data, asyncResp);
- }
+ if (ipv4StaticAddresses)
+ {
+ handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses,
+ ethData, ipv4Data, asyncResp);
+ }
- if (staticNameServers)
- {
- handleStaticNameServersPatch(ifaceId, *staticNameServers,
- asyncResp);
- }
+ if (staticNameServers)
+ {
+ handleStaticNameServersPatch(
+ ifaceId, *staticNameServers, asyncResp);
+ }
- if (ipv6DefaultGateway)
- {
- messages::propertyNotWritable(asyncResp->res,
- "IPv6DefaultGateway");
- }
+ if (ipv6DefaultGateway)
+ {
+ messages::propertyNotWritable(asyncResp->res,
+ "IPv6DefaultGateway");
+ }
- if (ipv6StaticAddresses)
- {
- handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
- ipv6Data, asyncResp);
- }
+ if (ipv6StaticAddresses)
+ {
+ handleIPv6StaticAddressesPatch(ifaceId,
+ *ipv6StaticAddresses,
+ ipv6Data, asyncResp);
+ }
- if (ipv6StaticDefaultGateway)
- {
- handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
- ipv6GatewayData, asyncResp);
- }
+ if (ipv6StaticDefaultGateway)
+ {
+ handleIPv6DefaultGateway(
+ ifaceId, *ipv6StaticDefaultGateway,
+ ipv6GatewayData, asyncResp);
+ }
- if (interfaceEnabled)
- {
- setDbusProperty(asyncResp, "InterfaceEnabled",
+ if (interfaceEnabled)
+ {
+ setDbusProperty(
+ asyncResp, "InterfaceEnabled",
"xyz.openbmc_project.Network",
sdbusplus::message::object_path(
"/xyz/openbmc_project/network") /
ifaceId,
"xyz.openbmc_project.Network.EthernetInterface",
"NICEnabled", *interfaceEnabled);
- }
+ }
- if (mtuSize)
- {
- handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
- }
- });
- });
+ if (mtuSize)
+ {
+ handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
+ }
+ });
+ });
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
.privileges(redfish::privileges::deleteEthernetInterface)
@@ -2423,26 +2429,27 @@ inline void requestEthernetInterfacesRoutes(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId, const std::string& ifaceId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- crow::connections::systemBus->async_method_call(
- [asyncResp, ifaceId](const boost::system::error_code& ec,
- const sdbusplus::message_t& m) {
- afterDelete(asyncResp, ifaceId, ec, m);
- },
- "xyz.openbmc_project.Network",
- std::string("/xyz/openbmc_project/network/") + ifaceId,
- "xyz.openbmc_project.Object.Delete", "Delete");
- });
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, ifaceId](const boost::system::error_code& ec,
+ const sdbusplus::message_t& m) {
+ afterDelete(asyncResp, ifaceId, ec, m);
+ },
+ "xyz.openbmc_project.Network",
+ std::string("/xyz/openbmc_project/network/") + ifaceId,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index aebc2824b0..76f3c5a9ed 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -1,21 +1,22 @@
/*
-// Copyright (c) 2020 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2020 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "event_service_manager.hpp"
+#include "generated/enums/event_service.hpp"
#include "http/utility.hpp"
#include "logging.hpp"
#include "query.hpp"
@@ -33,6 +34,7 @@
#include <ranges>
#include <span>
#include <string>
+#include <vector>
namespace redfish
{
@@ -51,118 +53,123 @@ inline void requestRoutesEventService(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
.privileges(redfish::privileges::getEventService)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](
+ const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
- asyncResp->res.jsonValue["@odata.type"] =
- "#EventService.v1_5_0.EventService";
- asyncResp->res.jsonValue["Id"] = "EventService";
- asyncResp->res.jsonValue["Name"] = "Event Service";
- asyncResp->res.jsonValue["ServerSentEventUri"] =
- "/redfish/v1/EventService/SSE";
-
- asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
- "/redfish/v1/EventService/Subscriptions";
- asyncResp->res
- .jsonValue["Actions"]["#EventService.SubmitTestEvent"]["target"] =
- "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
-
- const persistent_data::EventServiceConfig eventServiceConfig =
- persistent_data::EventServiceStore::getInstance()
- .getEventServiceConfig();
-
- asyncResp->res.jsonValue["Status"]["State"] =
- (eventServiceConfig.enabled ? "Enabled" : "Disabled");
- asyncResp->res.jsonValue["ServiceEnabled"] = eventServiceConfig.enabled;
- asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
- eventServiceConfig.retryAttempts;
- asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
- eventServiceConfig.retryTimeoutInterval;
- asyncResp->res.jsonValue["EventFormatTypes"] = supportedEvtFormatTypes;
- asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
- asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
-
- nlohmann::json::object_t supportedSSEFilters;
- supportedSSEFilters["EventFormatType"] = true;
- supportedSSEFilters["MessageId"] = true;
- supportedSSEFilters["MetricReportDefinition"] = true;
- supportedSSEFilters["RegistryPrefix"] = true;
- supportedSSEFilters["OriginResource"] = false;
- supportedSSEFilters["ResourceType"] = false;
-
- asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
- std::move(supportedSSEFilters);
- });
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/EventService";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EventService.v1_5_0.EventService";
+ asyncResp->res.jsonValue["Id"] = "EventService";
+ asyncResp->res.jsonValue["Name"] = "Event Service";
+ asyncResp->res.jsonValue["ServerSentEventUri"] =
+ "/redfish/v1/EventService/SSE";
+
+ asyncResp->res.jsonValue["Subscriptions"]["@odata.id"] =
+ "/redfish/v1/EventService/Subscriptions";
+ asyncResp->res.jsonValue["Actions"]["#EventService.SubmitTestEvent"]
+ ["target"] =
+ "/redfish/v1/EventService/Actions/EventService.SubmitTestEvent";
+
+ const persistent_data::EventServiceConfig eventServiceConfig =
+ persistent_data::EventServiceStore::getInstance()
+ .getEventServiceConfig();
+
+ asyncResp->res.jsonValue["Status"]["State"] =
+ (eventServiceConfig.enabled ? "Enabled" : "Disabled");
+ asyncResp->res.jsonValue["ServiceEnabled"] =
+ eventServiceConfig.enabled;
+ asyncResp->res.jsonValue["DeliveryRetryAttempts"] =
+ eventServiceConfig.retryAttempts;
+ asyncResp->res.jsonValue["DeliveryRetryIntervalSeconds"] =
+ eventServiceConfig.retryTimeoutInterval;
+ asyncResp->res.jsonValue["EventFormatTypes"] =
+ supportedEvtFormatTypes;
+ asyncResp->res.jsonValue["RegistryPrefixes"] = supportedRegPrefixes;
+ asyncResp->res.jsonValue["ResourceTypes"] = supportedResourceTypes;
+
+ nlohmann::json::object_t supportedSSEFilters;
+ supportedSSEFilters["EventFormatType"] = true;
+ supportedSSEFilters["MessageId"] = true;
+ supportedSSEFilters["MetricReportDefinition"] = true;
+ supportedSSEFilters["RegistryPrefix"] = true;
+ supportedSSEFilters["OriginResource"] = false;
+ supportedSSEFilters["ResourceType"] = false;
+
+ asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] =
+ std::move(supportedSSEFilters);
+ });
BMCWEB_ROUTE(app, "/redfish/v1/EventService/")
.privileges(redfish::privileges::patchEventService)
.methods(boost::beast::http::verb::patch)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- std::optional<bool> serviceEnabled;
- std::optional<uint32_t> retryAttemps;
- std::optional<uint32_t> retryInterval;
-
- if (!json_util::readJsonPatch(
- req, asyncResp->res, "ServiceEnabled", serviceEnabled,
- "DeliveryRetryAttempts", retryAttemps,
- "DeliveryRetryIntervalSeconds", retryInterval))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ std::optional<bool> serviceEnabled;
+ std::optional<uint32_t> retryAttemps;
+ std::optional<uint32_t> retryInterval;
+
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "ServiceEnabled", serviceEnabled,
+ "DeliveryRetryAttempts", retryAttemps,
+ "DeliveryRetryIntervalSeconds", retryInterval))
+ {
+ return;
+ }
- persistent_data::EventServiceConfig eventServiceConfig =
- persistent_data::EventServiceStore::getInstance()
- .getEventServiceConfig();
+ persistent_data::EventServiceConfig eventServiceConfig =
+ persistent_data::EventServiceStore::getInstance()
+ .getEventServiceConfig();
- if (serviceEnabled)
- {
- eventServiceConfig.enabled = *serviceEnabled;
- }
+ if (serviceEnabled)
+ {
+ eventServiceConfig.enabled = *serviceEnabled;
+ }
- if (retryAttemps)
- {
- // Supported range [1-3]
- if ((*retryAttemps < 1) || (*retryAttemps > 3))
- {
- messages::queryParameterOutOfRange(
- asyncResp->res, std::to_string(*retryAttemps),
- "DeliveryRetryAttempts", "[1-3]");
- }
- else
- {
- eventServiceConfig.retryAttempts = *retryAttemps;
- }
- }
+ if (retryAttemps)
+ {
+ // Supported range [1-3]
+ if ((*retryAttemps < 1) || (*retryAttemps > 3))
+ {
+ messages::queryParameterOutOfRange(
+ asyncResp->res, std::to_string(*retryAttemps),
+ "DeliveryRetryAttempts", "[1-3]");
+ }
+ else
+ {
+ eventServiceConfig.retryAttempts = *retryAttemps;
+ }
+ }
- if (retryInterval)
- {
- // Supported range [5 - 180]
- if ((*retryInterval < 5) || (*retryInterval > 180))
- {
- messages::queryParameterOutOfRange(
- asyncResp->res, std::to_string(*retryInterval),
- "DeliveryRetryIntervalSeconds", "[5-180]");
- }
- else
- {
- eventServiceConfig.retryTimeoutInterval = *retryInterval;
- }
- }
+ if (retryInterval)
+ {
+ // Supported range [5 - 180]
+ if ((*retryInterval < 5) || (*retryInterval > 180))
+ {
+ messages::queryParameterOutOfRange(
+ asyncResp->res, std::to_string(*retryInterval),
+ "DeliveryRetryIntervalSeconds", "[5-180]");
+ }
+ else
+ {
+ eventServiceConfig.retryTimeoutInterval =
+ *retryInterval;
+ }
+ }
- EventServiceManager::getInstance().setEventServiceConfig(
- eventServiceConfig);
- });
+ EventServiceManager::getInstance().setEventServiceConfig(
+ eventServiceConfig);
+ });
}
inline void requestRoutesSubmitTestEvent(App& app)
@@ -173,18 +180,18 @@ inline void requestRoutesSubmitTestEvent(App& app)
.methods(boost::beast::http::verb::post)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (!EventServiceManager::getInstance().sendTestEventLog())
- {
- messages::serviceDisabled(asyncResp->res,
- "/redfish/v1/EventService/");
- return;
- }
- asyncResp->res.result(boost::beast::http::status::no_content);
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if (!EventServiceManager::getInstance().sendTestEventLog())
+ {
+ messages::serviceDisabled(asyncResp->res,
+ "/redfish/v1/EventService/");
+ return;
+ }
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ });
}
inline void doSubscriptionCollection(
@@ -227,402 +234,424 @@ inline void requestRoutesEventDestinationCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EventDestinationCollection.EventDestinationCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/EventService/Subscriptions";
- asyncResp->res.jsonValue["Name"] = "Event Destination Collections";
-
- nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
-
- std::vector<std::string> subscripIds =
- EventServiceManager::getInstance().getAllIDs();
- memberArray = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size();
-
- for (const std::string& id : subscripIds)
- {
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/EventService/Subscriptions/{}" + id);
- memberArray.emplace_back(std::move(member));
- }
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& resp) {
- doSubscriptionCollection(ec, asyncResp, resp);
- },
- "xyz.openbmc_project.Network.SNMP",
- "/xyz/openbmc_project/network/snmp/manager",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EventDestinationCollection.EventDestinationCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/EventService/Subscriptions";
+ asyncResp->res.jsonValue["Name"] =
+ "Event Destination Collections";
+
+ nlohmann::json& memberArray =
+ asyncResp->res.jsonValue["Members"];
+
+ std::vector<std::string> subscripIds =
+ EventServiceManager::getInstance().getAllIDs();
+ memberArray = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ subscripIds.size();
+
+ for (const std::string& id : subscripIds)
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/EventService/Subscriptions/{}" + id);
+ memberArray.emplace_back(std::move(member));
+ }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec,
+ const dbus::utility::ManagedObjectType& resp) {
+ doSubscriptionCollection(ec, asyncResp, resp);
+ },
+ "xyz.openbmc_project.Network.SNMP",
+ "/xyz/openbmc_project/network/snmp/manager",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ });
BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/")
.privileges(redfish::privileges::postEventDestinationCollection)
- .methods(boost::beast::http::verb::post)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
- maxNoOfSubscriptions)
- {
- messages::eventSubscriptionLimitExceeded(asyncResp->res);
- return;
- }
- std::string destUrl;
- std::string protocol;
- std::optional<std::string> context;
- std::optional<std::string> subscriptionType;
- std::optional<std::string> eventFormatType2;
- std::optional<std::string> retryPolicy;
- std::optional<std::vector<std::string>> msgIds;
- std::optional<std::vector<std::string>> regPrefixes;
- std::optional<std::vector<std::string>> resTypes;
- std::optional<std::vector<nlohmann::json::object_t>> headers;
- std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
-
- if (!json_util::readJsonPatch(
- req, asyncResp->res, "Destination", destUrl, "Context", context,
- "Protocol", protocol, "SubscriptionType", subscriptionType,
- "EventFormatType", eventFormatType2, "HttpHeaders", headers,
- "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
- "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
- mrdJsonArray, "ResourceTypes", resTypes))
- {
- return;
- }
-
- // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
- static constexpr const uint16_t maxDestinationSize = 2000;
- if (destUrl.size() > maxDestinationSize)
- {
- messages::stringValueTooLong(asyncResp->res, "Destination",
- maxDestinationSize);
- return;
- }
-
- if (regPrefixes && msgIds)
- {
- if (!regPrefixes->empty() && !msgIds->empty())
+ .methods(
+ boost::beast::http::verb::
+ post)([&app](
+ const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- messages::propertyValueConflict(asyncResp->res, "MessageIds",
- "RegistryPrefixes");
return;
}
- }
-
- boost::system::result<boost::urls::url> url =
- boost::urls::parse_absolute_uri(destUrl);
- if (!url)
- {
- BMCWEB_LOG_WARNING("Failed to validate and split destination url");
- messages::propertyValueFormatError(asyncResp->res, destUrl,
- "Destination");
- return;
- }
- url->normalize();
- crow::utility::setProtocolDefaults(*url, protocol);
- crow::utility::setPortDefaults(*url);
-
- if (url->path().empty())
- {
- url->set_path("/");
- }
-
- if (url->has_userinfo())
- {
- messages::propertyValueFormatError(asyncResp->res, destUrl,
- "Destination");
- return;
- }
-
- if (protocol == "SNMPv2c")
- {
- if (context)
+ if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
+ maxNoOfSubscriptions)
{
- messages::propertyValueConflict(asyncResp->res, "Context",
- "Protocol");
+ messages::eventSubscriptionLimitExceeded(asyncResp->res);
return;
}
- if (eventFormatType2)
+ std::string destUrl;
+ std::string protocol;
+ std::optional<bool> verifyCertificate;
+ std::optional<std::string> context;
+ std::optional<std::string> subscriptionType;
+ std::optional<std::string> eventFormatType2;
+ std::optional<std::string> retryPolicy;
+ std::optional<std::vector<std::string>> msgIds;
+ std::optional<std::vector<std::string>> regPrefixes;
+ std::optional<std::vector<std::string>> originResources;
+ std::optional<std::vector<std::string>> resTypes;
+ std::optional<std::vector<nlohmann::json::object_t>> headers;
+ std::optional<std::vector<nlohmann::json::object_t>> mrdJsonArray;
+
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "Destination", destUrl, "Context",
+ context, "Protocol", protocol, "SubscriptionType",
+ subscriptionType, "EventFormatType", eventFormatType2,
+ "HttpHeaders", headers, "RegistryPrefixes", regPrefixes,
+ "OriginResources", originResources, "MessageIds", msgIds,
+ "DeliveryRetryPolicy", retryPolicy,
+ "MetricReportDefinitions", mrdJsonArray, "ResourceTypes",
+ resTypes, "VerifyCertificate", verifyCertificate))
{
- messages::propertyValueConflict(asyncResp->res,
- "EventFormatType", "Protocol");
return;
}
- if (retryPolicy)
- {
- messages::propertyValueConflict(asyncResp->res, "RetryPolicy",
- "Protocol");
- return;
- }
- if (msgIds)
+
+ // https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
+ static constexpr const uint16_t maxDestinationSize = 2000;
+ if (destUrl.size() > maxDestinationSize)
{
- messages::propertyValueConflict(asyncResp->res, "MessageIds",
- "Protocol");
+ messages::stringValueTooLong(asyncResp->res, "Destination",
+ maxDestinationSize);
return;
}
- if (regPrefixes)
+
+ if (regPrefixes && msgIds)
{
- messages::propertyValueConflict(asyncResp->res,
- "RegistryPrefixes", "Protocol");
- return;
+ if (!regPrefixes->empty() && !msgIds->empty())
+ {
+ messages::propertyValueConflict(
+ asyncResp->res, "MessageIds", "RegistryPrefixes");
+ return;
+ }
}
- if (resTypes)
+
+ boost::system::result<boost::urls::url> url =
+ boost::urls::parse_absolute_uri(destUrl);
+ if (!url)
{
- messages::propertyValueConflict(asyncResp->res, "ResourceTypes",
- "Protocol");
+ BMCWEB_LOG_WARNING(
+ "Failed to validate and split destination url");
+ messages::propertyValueFormatError(asyncResp->res, destUrl,
+ "Destination");
return;
}
- if (headers)
+ url->normalize();
+ crow::utility::setProtocolDefaults(*url, protocol);
+ crow::utility::setPortDefaults(*url);
+
+ if (url->path().empty())
{
- messages::propertyValueConflict(asyncResp->res, "HttpHeaders",
- "Protocol");
- return;
+ url->set_path("/");
}
- if (mrdJsonArray)
+
+ if (url->has_userinfo())
{
- messages::propertyValueConflict(
- asyncResp->res, "MetricReportDefinitions", "Protocol");
+ messages::propertyValueFormatError(asyncResp->res, destUrl,
+ "Destination");
return;
}
- if (url->scheme() != "snmp")
+
+ if (protocol == "SNMPv2c")
{
- messages::propertyValueConflict(asyncResp->res, "Destination",
- "Protocol");
+ if (context)
+ {
+ messages::propertyValueConflict(asyncResp->res, "Context",
+ "Protocol");
+ return;
+ }
+ if (eventFormatType2)
+ {
+ messages::propertyValueConflict(
+ asyncResp->res, "EventFormatType", "Protocol");
+ return;
+ }
+ if (retryPolicy)
+ {
+ messages::propertyValueConflict(asyncResp->res,
+ "RetryPolicy", "Protocol");
+ return;
+ }
+ if (msgIds)
+ {
+ messages::propertyValueConflict(asyncResp->res,
+ "MessageIds", "Protocol");
+ return;
+ }
+ if (regPrefixes)
+ {
+ messages::propertyValueConflict(
+ asyncResp->res, "RegistryPrefixes", "Protocol");
+ return;
+ }
+ if (resTypes)
+ {
+ messages::propertyValueConflict(
+ asyncResp->res, "ResourceTypes", "Protocol");
+ return;
+ }
+ if (headers)
+ {
+ messages::propertyValueConflict(asyncResp->res,
+ "HttpHeaders", "Protocol");
+ return;
+ }
+ if (mrdJsonArray)
+ {
+ messages::propertyValueConflict(
+ asyncResp->res, "MetricReportDefinitions", "Protocol");
+ return;
+ }
+ if (url->scheme() != "snmp")
+ {
+ messages::propertyValueConflict(asyncResp->res,
+ "Destination", "Protocol");
+ return;
+ }
+
+ addSnmpTrapClient(asyncResp, url->host_address(),
+ url->port_number());
return;
}
- addSnmpTrapClient(asyncResp, url->host_address(),
- url->port_number());
- return;
- }
-
- std::shared_ptr<Subscription> subValue =
- std::make_shared<Subscription>(*url, app.ioContext());
+ std::shared_ptr<Subscription> subValue =
+ std::make_shared<Subscription>(*url, app.ioContext());
- subValue->destinationUrl = std::move(*url);
+ subValue->destinationUrl = std::move(*url);
- if (subscriptionType)
- {
- if (*subscriptionType != "RedfishEvent")
+ if (subscriptionType)
{
- messages::propertyValueNotInList(
- asyncResp->res, *subscriptionType, "SubscriptionType");
- return;
+ if (*subscriptionType != "RedfishEvent")
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, *subscriptionType, "SubscriptionType");
+ return;
+ }
+ subValue->subscriptionType = *subscriptionType;
}
- subValue->subscriptionType = *subscriptionType;
- }
- else
- {
- subValue->subscriptionType = "RedfishEvent"; // Default
- }
-
- if (protocol != "Redfish")
- {
- messages::propertyValueNotInList(asyncResp->res, protocol,
- "Protocol");
- return;
- }
- subValue->protocol = protocol;
-
- if (eventFormatType2)
- {
- if (std::ranges::find(supportedEvtFormatTypes, *eventFormatType2) ==
- supportedEvtFormatTypes.end())
+ else
{
- messages::propertyValueNotInList(
- asyncResp->res, *eventFormatType2, "EventFormatType");
- return;
+ subValue->subscriptionType = "RedfishEvent"; // Default
}
- subValue->eventFormatType = *eventFormatType2;
- }
- else
- {
- // If not specified, use default "Event"
- subValue->eventFormatType = "Event";
- }
- if (context)
- {
- // This value is selected arbitrarily.
- constexpr const size_t maxContextSize = 256;
- if (context->size() > maxContextSize)
+ if (protocol != "Redfish")
{
- messages::stringValueTooLong(asyncResp->res, "Context",
- maxContextSize);
+ messages::propertyValueNotInList(asyncResp->res, protocol,
+ "Protocol");
return;
}
- subValue->customText = *context;
- }
+ subValue->protocol = protocol;
- if (headers)
- {
- size_t cumulativeLen = 0;
+ if (verifyCertificate)
+ {
+ subValue->verifyCertificate = *verifyCertificate;
+ }
- for (const nlohmann::json::object_t& headerChunk : *headers)
+ if (eventFormatType2)
{
- for (const auto& item : headerChunk)
+ if (std::ranges::find(supportedEvtFormatTypes,
+ *eventFormatType2) ==
+ supportedEvtFormatTypes.end())
{
- const std::string* value =
- item.second.get_ptr<const std::string*>();
- if (value == nullptr)
- {
- messages::propertyValueFormatError(
- asyncResp->res, item.second,
- "HttpHeaders/" + item.first);
- return;
- }
- // Adding a new json value is the size of the key, +
- // the size of the value + 2 * 2 quotes for each, +
- // the colon and space between. example:
- // "key": "value"
- cumulativeLen += item.first.size() + value->size() + 6;
- // This value is selected to mirror http_connection.hpp
- constexpr const uint16_t maxHeaderSizeED = 8096;
- if (cumulativeLen > maxHeaderSizeED)
- {
- messages::arraySizeTooLong(
- asyncResp->res, "HttpHeaders", maxHeaderSizeED);
- return;
- }
- subValue->httpHeaders.set(item.first, *value);
+ messages::propertyValueNotInList(
+ asyncResp->res, *eventFormatType2, "EventFormatType");
+ return;
}
+ subValue->eventFormatType = *eventFormatType2;
+ }
+ else
+ {
+ // If not specified, use default "Event"
+ subValue->eventFormatType = "Event";
}
- }
- if (regPrefixes)
- {
- for (const std::string& it : *regPrefixes)
+ if (context)
{
- if (std::ranges::find(supportedRegPrefixes, it) ==
- supportedRegPrefixes.end())
+ // This value is selected arbitrarily.
+ constexpr const size_t maxContextSize = 256;
+ if (context->size() > maxContextSize)
{
- messages::propertyValueNotInList(asyncResp->res, it,
- "RegistryPrefixes");
+ messages::stringValueTooLong(asyncResp->res, "Context",
+ maxContextSize);
return;
}
+ subValue->customText = *context;
}
- subValue->registryPrefixes = *regPrefixes;
- }
- if (resTypes)
- {
- for (const std::string& it : *resTypes)
+ if (headers)
{
- if (std::ranges::find(supportedResourceTypes, it) ==
- supportedResourceTypes.end())
+ size_t cumulativeLen = 0;
+
+ for (const nlohmann::json::object_t& headerChunk : *headers)
{
- messages::propertyValueNotInList(asyncResp->res, it,
- "ResourceTypes");
- return;
+ for (const auto& item : headerChunk)
+ {
+ const std::string* value =
+ item.second.get_ptr<const std::string*>();
+ if (value == nullptr)
+ {
+ messages::propertyValueFormatError(
+ asyncResp->res, item.second,
+ "HttpHeaders/" + item.first);
+ return;
+ }
+ // Adding a new json value is the size of the key, +
+ // the size of the value + 2 * 2 quotes for each, +
+ // the colon and space between. example:
+ // "key": "value"
+ cumulativeLen += item.first.size() + value->size() + 6;
+ // This value is selected to mirror http_connection.hpp
+ constexpr const uint16_t maxHeaderSizeED = 8096;
+ if (cumulativeLen > maxHeaderSizeED)
+ {
+ messages::arraySizeTooLong(
+ asyncResp->res, "HttpHeaders", maxHeaderSizeED);
+ return;
+ }
+ subValue->httpHeaders.set(item.first, *value);
+ }
}
}
- subValue->resourceTypes = *resTypes;
- }
- if (msgIds)
- {
- std::vector<std::string> registryPrefix;
+ if (regPrefixes)
+ {
+ for (const std::string& it : *regPrefixes)
+ {
+ if (std::ranges::find(supportedRegPrefixes, it) ==
+ supportedRegPrefixes.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res, it,
+ "RegistryPrefixes");
+ return;
+ }
+ }
+ subValue->registryPrefixes = *regPrefixes;
+ }
- // If no registry prefixes are mentioned, consider all
- // supported prefixes
- if (subValue->registryPrefixes.empty())
+ if (originResources)
{
- registryPrefix.assign(supportedRegPrefixes.begin(),
- supportedRegPrefixes.end());
+ subValue->originResources = *originResources;
}
- else
+
+ if (resTypes)
{
- registryPrefix = subValue->registryPrefixes;
+ for (const std::string& it : *resTypes)
+ {
+ if (std::ranges::find(supportedResourceTypes, it) ==
+ supportedResourceTypes.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res, it,
+ "ResourceTypes");
+ return;
+ }
+ }
+ subValue->resourceTypes = *resTypes;
}
- for (const std::string& id : *msgIds)
+ if (msgIds)
{
- bool validId = false;
+ std::vector<std::string> registryPrefix;
- // Check for Message ID in each of the selected Registry
- for (const std::string& it : registryPrefix)
+ // If no registry prefixes are mentioned, consider all
+ // supported prefixes
+ if (subValue->registryPrefixes.empty())
+ {
+ registryPrefix.assign(supportedRegPrefixes.begin(),
+ supportedRegPrefixes.end());
+ }
+ else
{
- const std::span<const redfish::registries::MessageEntry>
- registry =
- redfish::registries::getRegistryFromPrefix(it);
+ registryPrefix = subValue->registryPrefixes;
+ }
- if (std::ranges::any_of(
- registry,
- [&id](const redfish::registries::MessageEntry&
- messageEntry) {
- return id == messageEntry.first;
- }))
+ for (const std::string& id : *msgIds)
+ {
+ bool validId = false;
+
+ // Check for Message ID in each of the selected Registry
+ for (const std::string& it : registryPrefix)
{
- validId = true;
- break;
+ const std::span<const redfish::registries::MessageEntry>
+ registry =
+ redfish::registries::getRegistryFromPrefix(it);
+
+ if (std::ranges::any_of(
+ registry,
+ [&id](const redfish::registries::MessageEntry&
+ messageEntry) {
+ return id == messageEntry.first;
+ }))
+ {
+ validId = true;
+ break;
+ }
+ }
+
+ if (!validId)
+ {
+ messages::propertyValueNotInList(asyncResp->res, id,
+ "MessageIds");
+ return;
}
}
- if (!validId)
+ subValue->registryMsgIds = *msgIds;
+ }
+
+ if (retryPolicy)
+ {
+ if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
+ supportedRetryPolicies.end())
{
- messages::propertyValueNotInList(asyncResp->res, id,
- "MessageIds");
+ messages::propertyValueNotInList(
+ asyncResp->res, *retryPolicy, "DeliveryRetryPolicy");
return;
}
+ subValue->retryPolicy = *retryPolicy;
}
-
- subValue->registryMsgIds = *msgIds;
- }
-
- if (retryPolicy)
- {
- if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
- supportedRetryPolicies.end())
+ else
{
- messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
- "DeliveryRetryPolicy");
- return;
+ // Default "TerminateAfterRetries"
+ subValue->retryPolicy = "TerminateAfterRetries";
}
- subValue->retryPolicy = *retryPolicy;
- }
- else
- {
- // Default "TerminateAfterRetries"
- subValue->retryPolicy = "TerminateAfterRetries";
- }
- if (mrdJsonArray)
- {
- for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
+ if (mrdJsonArray)
{
- std::string mrdUri;
+ for (nlohmann::json::object_t& mrdObj : *mrdJsonArray)
+ {
+ std::string mrdUri;
- if (!json_util::readJsonObject(mrdObj, asyncResp->res,
- "@odata.id", mrdUri))
+ if (!json_util::readJsonObject(mrdObj, asyncResp->res,
+ "@odata.id", mrdUri))
- {
- return;
+ {
+ return;
+ }
+ subValue->metricReportDefinitions.emplace_back(mrdUri);
}
- subValue->metricReportDefinitions.emplace_back(mrdUri);
}
- }
- std::string id =
- EventServiceManager::getInstance().addSubscription(subValue);
- if (id.empty())
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ std::string id =
+ EventServiceManager::getInstance().addPushSubscription(
+ subValue);
+ if (id.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- messages::created(asyncResp->res);
- asyncResp->res.addHeader(
- "Location", "/redfish/v1/EventService/Subscriptions/" + id);
- });
+ messages::created(asyncResp->res);
+ asyncResp->res.addHeader(
+ "Location", "/redfish/v1/EventService/Subscriptions/" + id);
+ });
}
inline void requestRoutesEventDestination(App& app)
@@ -633,55 +662,66 @@ inline void requestRoutesEventDestination(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (param.starts_with("snmp"))
- {
- getSnmpTrapClient(asyncResp, param);
- return;
- }
+ if (param.starts_with("snmp"))
+ {
+ getSnmpTrapClient(asyncResp, param);
+ return;
+ }
- std::shared_ptr<Subscription> subValue =
- EventServiceManager::getInstance().getSubscription(param);
- if (subValue == nullptr)
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
- const std::string& id = param;
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#EventDestination.v1_8_0.EventDestination";
- asyncResp->res.jsonValue["Protocol"] = "Redfish";
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/EventService/Subscriptions/{}", id);
- asyncResp->res.jsonValue["Id"] = id;
- asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
- asyncResp->res.jsonValue["Destination"] = subValue->destinationUrl;
- asyncResp->res.jsonValue["Context"] = subValue->customText;
- asyncResp->res.jsonValue["SubscriptionType"] =
- subValue->subscriptionType;
- asyncResp->res.jsonValue["HttpHeaders"] = nlohmann::json::array();
- asyncResp->res.jsonValue["EventFormatType"] = subValue->eventFormatType;
- asyncResp->res.jsonValue["RegistryPrefixes"] =
- subValue->registryPrefixes;
- asyncResp->res.jsonValue["ResourceTypes"] = subValue->resourceTypes;
-
- asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
- asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
-
- nlohmann::json::array_t mrdJsonArray;
- for (const auto& mdrUri : subValue->metricReportDefinitions)
- {
- nlohmann::json::object_t mdr;
- mdr["@odata.id"] = mdrUri;
- mrdJsonArray.emplace_back(std::move(mdr));
- }
- asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
- });
+ std::shared_ptr<Subscription> subValue =
+ EventServiceManager::getInstance().getSubscription(param);
+ if (subValue == nullptr)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::not_found);
+ return;
+ }
+ const std::string& id = param;
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EventDestination.v1_14_1.EventDestination";
+ asyncResp->res.jsonValue["Protocol"] =
+ event_destination::EventDestinationProtocol::Redfish;
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/EventService/Subscriptions/{}", id);
+ asyncResp->res.jsonValue["Id"] = id;
+ asyncResp->res.jsonValue["Name"] = "Event Destination " + id;
+ asyncResp->res.jsonValue["Destination"] =
+ subValue->destinationUrl;
+ asyncResp->res.jsonValue["Context"] = subValue->customText;
+ asyncResp->res.jsonValue["SubscriptionType"] =
+ subValue->subscriptionType;
+ asyncResp->res.jsonValue["HttpHeaders"] =
+ nlohmann::json::array();
+ asyncResp->res.jsonValue["EventFormatType"] =
+ subValue->eventFormatType;
+ asyncResp->res.jsonValue["RegistryPrefixes"] =
+ subValue->registryPrefixes;
+ asyncResp->res.jsonValue["ResourceTypes"] =
+ subValue->resourceTypes;
+
+ asyncResp->res.jsonValue["MessageIds"] =
+ subValue->registryMsgIds;
+ asyncResp->res.jsonValue["DeliveryRetryPolicy"] =
+ subValue->retryPolicy;
+ asyncResp->res.jsonValue["VerifyCertificate"] =
+ subValue->verifyCertificate;
+
+ nlohmann::json::array_t mrdJsonArray;
+ for (const auto& mdrUri : subValue->metricReportDefinitions)
+ {
+ nlohmann::json::object_t mdr;
+ mdr["@odata.id"] = mdrUri;
+ mrdJsonArray.emplace_back(std::move(mdr));
+ }
+ asyncResp->res.jsonValue["MetricReportDefinitions"] =
+ mrdJsonArray;
+ });
BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
// The below privilege is wrong, it should be ConfigureManager OR
// ConfigureSelf
@@ -692,70 +732,81 @@ inline void requestRoutesEventDestination(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- std::shared_ptr<Subscription> subValue =
- EventServiceManager::getInstance().getSubscription(param);
- if (subValue == nullptr)
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ std::shared_ptr<Subscription> subValue =
+ EventServiceManager::getInstance().getSubscription(param);
+ if (subValue == nullptr)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::not_found);
+ return;
+ }
- std::optional<std::string> context;
- std::optional<std::string> retryPolicy;
- std::optional<std::vector<nlohmann::json::object_t>> headers;
+ std::optional<std::string> context;
+ std::optional<std::string> retryPolicy;
+ std::optional<bool> verifyCertificate;
+ std::optional<std::vector<nlohmann::json::object_t>> headers;
- if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context,
- "DeliveryRetryPolicy", retryPolicy,
- "HttpHeaders", headers))
- {
- return;
- }
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "Context", context,
+ "VerifyCertificate", verifyCertificate,
+ "DeliveryRetryPolicy", retryPolicy, "HttpHeaders",
+ headers))
+ {
+ return;
+ }
- if (context)
- {
- subValue->customText = *context;
- }
+ if (context)
+ {
+ subValue->customText = *context;
+ }
- if (headers)
- {
- boost::beast::http::fields fields;
- for (const nlohmann::json::object_t& headerChunk : *headers)
- {
- for (const auto& it : headerChunk)
+ if (headers)
{
- const std::string* value =
- it.second.get_ptr<const std::string*>();
- if (value == nullptr)
+ boost::beast::http::fields fields;
+ for (const nlohmann::json::object_t& headerChunk : *headers)
{
- messages::propertyValueFormatError(
- asyncResp->res, it.second,
- "HttpHeaders/" + it.first);
+ for (const auto& it : headerChunk)
+ {
+ const std::string* value =
+ it.second.get_ptr<const std::string*>();
+ if (value == nullptr)
+ {
+ messages::propertyValueFormatError(
+ asyncResp->res, it.second,
+ "HttpHeaders/" + it.first);
+ return;
+ }
+ fields.set(it.first, *value);
+ }
+ }
+ subValue->httpHeaders = std::move(fields);
+ }
+
+ if (retryPolicy)
+ {
+ if (std::ranges::find(supportedRetryPolicies,
+ *retryPolicy) ==
+ supportedRetryPolicies.end())
+ {
+ messages::propertyValueNotInList(asyncResp->res,
+ *retryPolicy,
+ "DeliveryRetryPolicy");
return;
}
- fields.set(it.first, *value);
+ subValue->retryPolicy = *retryPolicy;
}
- }
- subValue->httpHeaders = std::move(fields);
- }
- if (retryPolicy)
- {
- if (std::ranges::find(supportedRetryPolicies, *retryPolicy) ==
- supportedRetryPolicies.end())
- {
- messages::propertyValueNotInList(asyncResp->res, *retryPolicy,
- "DeliveryRetryPolicy");
- return;
- }
- subValue->retryPolicy = *retryPolicy;
- }
+ if (verifyCertificate)
+ {
+ subValue->verifyCertificate = *verifyCertificate;
+ }
- EventServiceManager::getInstance().updateSubscriptionData();
- });
+ EventServiceManager::getInstance().updateSubscriptionData();
+ });
BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/")
// The below privilege is wrong, it should be ConfigureManager OR
// ConfigureSelf
@@ -766,25 +817,28 @@ inline void requestRoutesEventDestination(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (param.starts_with("snmp"))
- {
- deleteSnmpTrapClient(asyncResp, param);
- EventServiceManager::getInstance().deleteSubscription(param);
- return;
- }
+ if (param.starts_with("snmp"))
+ {
+ deleteSnmpTrapClient(asyncResp, param);
+ EventServiceManager::getInstance().deleteSubscription(
+ param);
+ return;
+ }
- if (!EventServiceManager::getInstance().isSubscriptionExist(param))
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
- EventServiceManager::getInstance().deleteSubscription(param);
- });
+ if (!EventServiceManager::getInstance().isSubscriptionExist(
+ param))
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::not_found);
+ return;
+ }
+ EventServiceManager::getInstance().deleteSubscription(param);
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/eventservice_sse.hpp b/redfish-core/lib/eventservice_sse.hpp
index 3cbca3bc8b..c0a9527e94 100644
--- a/redfish-core/lib/eventservice_sse.hpp
+++ b/redfish-core/lib/eventservice_sse.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "filter_expr_executor.hpp"
#include "privileges.hpp"
#include "registries/privilege_registry.hpp"
@@ -12,7 +13,8 @@
namespace redfish
{
-inline void createSubscription(crow::sse_socket::Connection& conn)
+inline void createSubscription(crow::sse_socket::Connection& conn,
+ const crow::Request& req)
{
EventServiceManager& manager =
EventServiceManager::getInstance(&conn.getIoContext());
@@ -23,6 +25,25 @@ inline void createSubscription(crow::sse_socket::Connection& conn)
conn.close("Max SSE subscriptions reached");
return;
}
+
+ std::optional<filter_ast::LogicalAnd> filter;
+
+ boost::urls::params_base::iterator filterIt =
+ req.url().params().find("$filter");
+
+ if (filterIt != req.url().params().end())
+ {
+ std::string_view filterValue = (*filterIt).value;
+ filter = parseFilter(filterValue);
+ if (!filter)
+ {
+ conn.close(std::format("Bad $filter param: {}", filterValue));
+ return;
+ }
+ }
+
+ std::string lastEventId(req.getHeaderValue("Last-Event-Id"));
+
std::shared_ptr<redfish::Subscription> subValue =
std::make_shared<redfish::Subscription>(conn);
@@ -32,8 +53,9 @@ inline void createSubscription(crow::sse_socket::Connection& conn)
subValue->protocol = "Redfish";
subValue->retryPolicy = "TerminateAfterRetries";
subValue->eventFormatType = "Event";
+ subValue->filter = filter;
- std::string id = manager.addSubscription(subValue, false);
+ std::string id = manager.addSSESubscription(subValue, lastEventId);
if (id.empty())
{
conn.close("Internal Error");
diff --git a/redfish-core/lib/fabric_adapters.hpp b/redfish-core/lib/fabric_adapters.hpp
index 11dc7c6973..20e6726c07 100644
--- a/redfish-core/lib/fabric_adapters.hpp
+++ b/redfish-core/lib/fabric_adapters.hpp
@@ -2,6 +2,7 @@
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
@@ -32,25 +33,25 @@ inline void getFabricAdapterLocation(
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
[asyncResp](const boost::system::error_code& ec,
const std::string& property) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Location");
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Location");
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- property;
- });
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+ property;
+ });
}
-inline void
- getFabricAdapterAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& serviceName,
- const std::string& fabricAdapterPath)
+inline void getFabricAdapterAsset(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& serviceName, const std::string& fabricAdapterPath)
{
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, serviceName, fabricAdapterPath,
@@ -58,112 +59,111 @@ inline void
[fabricAdapterPath, asyncResp{asyncResp}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Properties");
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Properties");
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- const std::string* serialNumber = nullptr;
- const std::string* model = nullptr;
- const std::string* partNumber = nullptr;
- const std::string* sparePartNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* model = nullptr;
+ const std::string* partNumber = nullptr;
+ const std::string* sparePartNumber = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList, "SerialNumber",
- serialNumber, "Model", model, "PartNumber", partNumber,
- "SparePartNumber", sparePartNumber);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList,
+ "SerialNumber", serialNumber, "Model", model, "PartNumber",
+ partNumber, "SparePartNumber", sparePartNumber);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (serialNumber != nullptr)
- {
- asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
- }
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
- if (model != nullptr)
- {
- asyncResp->res.jsonValue["Model"] = *model;
- }
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] = *model;
+ }
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] = *partNumber;
- }
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
- if (sparePartNumber != nullptr && !sparePartNumber->empty())
- {
- asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
- }
- });
+ if (sparePartNumber != nullptr && !sparePartNumber->empty())
+ {
+ asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
+ }
+ });
}
-inline void
- getFabricAdapterState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& serviceName,
- const std::string& fabricAdapterPath)
+inline void getFabricAdapterState(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& serviceName, const std::string& fabricAdapterPath)
{
sdbusplus::asio::getProperty<bool>(
*crow::connections::systemBus, serviceName, fabricAdapterPath,
"xyz.openbmc_project.Inventory.Item", "Present",
[asyncResp](const boost::system::error_code& ec, const bool present) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for State");
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for State");
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!present)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ if (!present)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ }
+ });
}
-inline void
- getFabricAdapterHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& serviceName,
- const std::string& fabricAdapterPath)
+inline void getFabricAdapterHealth(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& serviceName, const std::string& fabricAdapterPath)
{
sdbusplus::asio::getProperty<bool>(
*crow::connections::systemBus, serviceName, fabricAdapterPath,
"xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
[asyncResp](const boost::system::error_code& ec,
const bool functional) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Health");
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Health");
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!functional)
- {
- asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
- }
- });
+ if (!functional)
+ {
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::Critical;
+ }
+ });
}
-inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& adapterId,
- const std::string& fabricAdapterPath,
- const std::string& serviceName)
+inline void doAdapterGet(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& adapterId,
+ const std::string& fabricAdapterPath, const std::string& serviceName)
{
asyncResp->res.addHeader(
boost::beast::http::field::link,
@@ -175,8 +175,8 @@ inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
"/redfish/v1/Systems/{}/FabricAdapters/{}", systemName, adapterId);
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
getFabricAdapterLocation(asyncResp, serviceName, fabricAdapterPath);
getFabricAdapterAsset(asyncResp, serviceName, fabricAdapterPath);
@@ -256,11 +256,10 @@ inline void afterHandleFabricAdapterGet(
serviceName);
}
-inline void
- handleFabricAdapterGet(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& adapterId)
+inline void handleFabricAdapterGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& adapterId)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -381,11 +380,10 @@ inline void afterHandleFabricAdapterHead(
"</redfish/v1/JsonSchemas/FabricAdapter/FabricAdapter.json>; rel=describedby");
}
-inline void
- handleFabricAdapterHead(crow::App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& adapterId)
+inline void handleFabricAdapterHead(
+ crow::App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& adapterId)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
diff --git a/redfish-core/lib/fan.hpp b/redfish-core/lib/fan.hpp
index 39b9e2abd7..28b995e794 100644
--- a/redfish-core/lib/fan.hpp
+++ b/redfish-core/lib/fan.hpp
@@ -3,6 +3,7 @@
#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/chassis_utils.hpp"
@@ -64,19 +65,19 @@ inline void getFanPaths(
[asyncResp, callback](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR(
- "DBUS response error for getAssociatedSubTreePaths {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBUS response error for getAssociatedSubTreePaths {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- callback(subtreePaths);
- });
+ callback(subtreePaths);
+ });
}
inline void doFanCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -119,15 +120,16 @@ inline void
asyncResp, chassisId,
[asyncResp,
chassisId](const std::optional<std::string>& validChassisPath) {
- if (!validChassisPath)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- return;
- }
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby");
- });
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis",
+ chassisId);
+ return;
+ }
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/FanCollection/FanCollection.json>; rel=describedby");
+ });
}
inline void
@@ -165,7 +167,7 @@ inline bool checkFanId(const std::string& fanPath, const std::string& fanId)
return !(fanName.empty() || fanName != fanId);
}
-static inline void handleFanPath(
+inline void handleFanPath(
const std::string& fanId,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const dbus::utility::MapperGetSubTreePathsResponse& fanPaths,
@@ -183,15 +185,15 @@ static inline void handleFanPath(
[fanPath, asyncResp,
callback](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& object) {
- if (ec || object.empty())
- {
- BMCWEB_LOG_ERROR("DBUS response error on getDbusObject {}",
- ec.value());
- messages::internalError(asyncResp->res);
- return;
- }
- callback(fanPath, object.begin()->first);
- });
+ if (ec || object.empty())
+ {
+ BMCWEB_LOG_ERROR("DBUS response error on getDbusObject {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ callback(fanPath, object.begin()->first);
+ });
return;
}
@@ -209,8 +211,8 @@ inline void getValidFanPath(
asyncResp, validChassisPath,
[fanId, asyncResp, callback](
const dbus::utility::MapperGetSubTreePathsResponse& fanPaths) {
- handleFanPath(fanId, asyncResp, fanPaths, callback);
- });
+ handleFanPath(fanId, asyncResp, fanPaths, callback);
+ });
}
inline void addFanCommonProperties(crow::Response& resp,
@@ -224,8 +226,8 @@ inline void addFanCommonProperties(crow::Response& resp,
resp.jsonValue["Id"] = fanId;
resp.jsonValue["@odata.id"] = boost::urls::format(
"/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId, fanId);
- resp.jsonValue["Status"]["State"] = "Enabled";
- resp.jsonValue["Status"]["Health"] = "OK";
+ resp.jsonValue["Status"]["State"] = resource::State::Enabled;
+ resp.jsonValue["Status"]["Health"] = resource::Health::OK;
}
inline void getFanHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -235,22 +237,23 @@ inline void getFanHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
*crow::connections::systemBus, service, fanPath,
"xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
[asyncResp](const boost::system::error_code& ec, const bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Health {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Health {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!value)
- {
- asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
- }
- });
+ if (!value)
+ {
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::Critical;
+ }
+ });
}
inline void getFanState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -260,22 +263,23 @@ inline void getFanState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
*crow::connections::systemBus, service, fanPath,
"xyz.openbmc_project.Inventory.Item", "Present",
[asyncResp](const boost::system::error_code& ec, const bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for State {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for State {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!value)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ if (!value)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ }
+ });
}
inline void getFanAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -287,52 +291,53 @@ inline void getFanAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
[fanPath, asyncResp{asyncResp}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& assetList) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
+ {
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+ const std::string* manufacturer = nullptr;
+ const std::string* model = nullptr;
+ const std::string* partNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* sparePartNumber = nullptr;
+
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
+ manufacturer, "Model", model, "PartNumber", partNumber,
+ "SerialNumber", serialNumber, "SparePartNumber",
+ sparePartNumber);
+ if (!success)
{
- BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
- ec.value());
messages::internalError(asyncResp->res);
+ return;
}
- return;
- }
- const std::string* manufacturer = nullptr;
- const std::string* model = nullptr;
- const std::string* partNumber = nullptr;
- const std::string* serialNumber = nullptr;
- const std::string* sparePartNumber = nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
- manufacturer, "Model", model, "PartNumber", partNumber,
- "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- if (manufacturer != nullptr)
- {
- asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
- }
- if (model != nullptr)
- {
- asyncResp->res.jsonValue["Model"] = *model;
- }
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] = *partNumber;
- }
- if (serialNumber != nullptr)
- {
- asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
- }
- if (sparePartNumber != nullptr && !sparePartNumber->empty())
- {
- asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
- }
- });
+ if (manufacturer != nullptr)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+ }
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] = *model;
+ }
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
+ if (sparePartNumber != nullptr && !sparePartNumber->empty())
+ {
+ asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
+ }
+ });
}
inline void getFanLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -344,19 +349,20 @@ inline void getFanLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
[asyncResp](const boost::system::error_code& ec,
const std::string& property) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Location{}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Location{}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- property;
- });
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+ property;
+ });
}
inline void
@@ -400,18 +406,20 @@ inline void handleFanHead(App& app, const crow::Request& req,
asyncResp, chassisId,
[asyncResp, chassisId,
fanId](const std::optional<std::string>& validChassisPath) {
- if (!validChassisPath)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- return;
- }
- getValidFanPath(asyncResp, *validChassisPath, fanId,
- [asyncResp](const std::string&, const std::string&) {
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby");
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis",
+ chassisId);
+ return;
+ }
+ getValidFanPath(
+ asyncResp, *validChassisPath, fanId,
+ [asyncResp](const std::string&, const std::string&) {
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby");
+ });
});
- });
}
inline void handleFanGet(App& app, const crow::Request& req,
diff --git a/redfish-core/lib/hypervisor_system.hpp b/redfish-core/lib/hypervisor_system.hpp
index 963fbfb84b..cc9d4c0313 100644
--- a/redfish-core/lib/hypervisor_system.hpp
+++ b/redfish-core/lib/hypervisor_system.hpp
@@ -5,6 +5,9 @@
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "ethernet.hpp"
+#include "generated/enums/action_info.hpp"
+#include "generated/enums/computer_system.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/ip_utils.hpp"
@@ -41,56 +44,69 @@ inline void
"xyz.openbmc_project.State.Host", "CurrentHostState",
[asyncResp](const boost::system::error_code& ec,
const std::string& hostState) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- // This is an optional D-Bus object so just return if
- // error occurs
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ // This is an optional D-Bus object so just return if
+ // error occurs
+ return;
+ }
- BMCWEB_LOG_DEBUG("Hypervisor state: {}", hostState);
- // Verify Host State
- if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- }
- else if (hostState == "xyz.openbmc_project.State.Host.HostState."
- "Quiesced")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "Quiesced";
- }
- else if (hostState == "xyz.openbmc_project.State.Host.HostState."
- "Standby")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
- }
- else if (hostState == "xyz.openbmc_project.State.Host.HostState."
- "TransitioningToRunning")
- {
- asyncResp->res.jsonValue["PowerState"] = "PoweringOn";
- asyncResp->res.jsonValue["Status"]["State"] = "Starting";
- }
- else if (hostState == "xyz.openbmc_project.State.Host.HostState."
- "TransitioningToOff")
- {
- asyncResp->res.jsonValue["PowerState"] = "PoweringOff";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- }
- else if (hostState == "xyz.openbmc_project.State.Host.HostState.Off")
- {
- asyncResp->res.jsonValue["PowerState"] = "Off";
- asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
- }
- else
- {
- messages::internalError(asyncResp->res);
- return;
- }
- });
+ BMCWEB_LOG_DEBUG("Hypervisor state: {}", hostState);
+ // Verify Host State
+ if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+ }
+ else if (hostState == "xyz.openbmc_project.State.Host.HostState."
+ "Quiesced")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Quiesced;
+ }
+ else if (hostState == "xyz.openbmc_project.State.Host.HostState."
+ "Standby")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::StandbyOffline;
+ }
+ else if (hostState == "xyz.openbmc_project.State.Host.HostState."
+ "TransitioningToRunning")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::PoweringOn;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Starting;
+ }
+ else if (hostState == "xyz.openbmc_project.State.Host.HostState."
+ "TransitioningToOff")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::PoweringOff;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+ }
+ else if (hostState ==
+ "xyz.openbmc_project.State.Host.HostState.Off")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::Off;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Disabled;
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ });
}
/**
@@ -115,37 +131,37 @@ inline void
const boost::system::error_code& ec,
const std::vector<std::pair<std::string, std::vector<std::string>>>&
objInfo) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- // This is an optional D-Bus object so just return if
- // error occurs
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ // This is an optional D-Bus object so just return if
+ // error occurs
+ return;
+ }
- if (objInfo.empty())
- {
- // As noted above, this is an optional interface so just return
- // if there is no instance found
- return;
- }
+ if (objInfo.empty())
+ {
+ // As noted above, this is an optional interface so just return
+ // if there is no instance found
+ return;
+ }
- if (objInfo.size() > 1)
- {
- // More then one hypervisor object is not supported and is an
- // error
- messages::internalError(asyncResp->res);
- return;
- }
+ if (objInfo.size() > 1)
+ {
+ // More then one hypervisor object is not supported and is an
+ // error
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Object present so system support limited ComputerSystem Action
- nlohmann::json& reset =
- asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"];
- reset["target"] =
- "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset";
- reset["@Redfish.ActionInfo"] =
- "/redfish/v1/Systems/hypervisor/ResetActionInfo";
- });
+ // Object present so system support limited ComputerSystem Action
+ nlohmann::json& reset =
+ asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"];
+ reset["target"] =
+ "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset";
+ reset["@Redfish.ActionInfo"] =
+ "/redfish/v1/Systems/hypervisor/ResetActionInfo";
+ });
}
inline bool extractHypervisorInterfaceData(
@@ -162,23 +178,8 @@ inline bool extractHypervisorInterfaceData(
"/xyz/openbmc_project/network/hypervisor/" + ethIfaceId)
{
idFound = true;
- if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
- {
- for (const auto& propertyPair : ifacePair.second)
- {
- if (propertyPair.first == "MACAddress")
- {
- const std::string* mac =
- std::get_if<std::string>(&propertyPair.second);
- if (mac != nullptr)
- {
- ethData.macAddress = *mac;
- }
- }
- }
- }
- else if (ifacePair.first ==
- "xyz.openbmc_project.Network.EthernetInterface")
+ if (ifacePair.first ==
+ "xyz.openbmc_project.Network.EthernetInterface")
{
for (const auto& propertyPair : ifacePair.second)
{
@@ -318,22 +319,22 @@ void getHypervisorIfaceData(const std::string& ethIfaceId,
callback = std::forward<CallbackFunc>(callback)](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& resp) mutable {
- EthernetInterfaceData ethData{};
- std::vector<IPv4AddressData> ipv4Data;
- if (ec)
- {
- callback(false, ethData, ipv4Data);
- return;
- }
+ EthernetInterfaceData ethData{};
+ std::vector<IPv4AddressData> ipv4Data;
+ if (ec)
+ {
+ callback(false, ethData, ipv4Data);
+ return;
+ }
- bool found = extractHypervisorInterfaceData(ethIfaceId, resp, ethData,
- ipv4Data);
- if (!found)
- {
- BMCWEB_LOG_INFO("Hypervisor Interface not found");
- }
- callback(found, ethData, ipv4Data);
- });
+ bool found = extractHypervisorInterfaceData(ethIfaceId, resp,
+ ethData, ipv4Data);
+ if (!found)
+ {
+ BMCWEB_LOG_INFO("Hypervisor Interface not found");
+ }
+ callback(found, ethData, ipv4Data);
+ });
}
/**
@@ -352,11 +353,11 @@ inline void setHypervisorIPv4Address(
BMCWEB_LOG_DEBUG("Setting the Hypervisor IPaddress : {} on Iface: {}",
ipv4Address, ethIfaceId);
- setDbusProperty(asyncResp, "IPv4StaticAddresses/1/Address",
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId +
- "/ipv4/addr0",
- "xyz.openbmc_project.Network.IP", "Address", ipv4Address);
+ setDbusProperty(
+ asyncResp, "IPv4StaticAddresses/1/Address",
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0",
+ "xyz.openbmc_project.Network.IP", "Address", ipv4Address);
}
/**
@@ -375,11 +376,11 @@ inline void
BMCWEB_LOG_DEBUG("Setting the Hypervisor subnet : {} on Iface: {}", subnet,
ethIfaceId);
- setDbusProperty(asyncResp, "IPv4StaticAddresses/1/SubnetMask",
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId +
- "/ipv4/addr0",
- "xyz.openbmc_project.Network.IP", "PrefixLength", subnet);
+ setDbusProperty(
+ asyncResp, "IPv4StaticAddresses/1/SubnetMask",
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0",
+ "xyz.openbmc_project.Network.IP", "PrefixLength", subnet);
}
/**
@@ -456,8 +457,6 @@ inline void parseInterfaceData(nlohmann::json& jsonResponse,
jsonResponse["@odata.id"] = boost::urls::format(
"/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", ifaceId);
jsonResponse["InterfaceEnabled"] = true;
- jsonResponse["MACAddress"] = ethData.macAddress;
-
jsonResponse["HostName"] = ethData.hostName;
jsonResponse["DHCPv4"]["DHCPEnabled"] =
translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
@@ -512,11 +511,11 @@ inline void setDHCPEnabled(const std::string& ifaceId, bool ipv4DHCPEnabled,
origin = "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
}
- setDbusProperty(asyncResp, "IPv4StaticAddresses/1/AddressOrigin",
- "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor/" + ifaceId +
- "/ipv4/addr0",
- "xyz.openbmc_project.Network.IP", "Origin", origin);
+ setDbusProperty(
+ asyncResp, "IPv4StaticAddresses/1/AddressOrigin",
+ "xyz.openbmc_project.Settings",
+ "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0",
+ "xyz.openbmc_project.Network.IP", "Origin", origin);
}
inline void handleHypervisorIPv4StaticPatch(
@@ -625,39 +624,41 @@ inline void handleHypervisorEthernetInterfaceCollectionGet(
[asyncResp](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) {
- if (ec)
- {
- messages::resourceNotFound(asyncResp->res, "System", "hypervisor");
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EthernetInterfaceCollection."
- "EthernetInterfaceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/hypervisor/EthernetInterfaces";
- asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet "
- "Interface Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of Virtual Management "
- "Interfaces for the hypervisor";
-
- nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
- ifaceArray = nlohmann::json::array();
- for (const std::string& iface : ifaceList)
- {
- sdbusplus::message::object_path path(iface);
- std::string name = path.filename();
- if (name.empty())
+ if (ec)
{
- continue;
+ messages::resourceNotFound(asyncResp->res, "System",
+ "hypervisor");
+ return;
}
- nlohmann::json::object_t ethIface;
- ethIface["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", name);
- ifaceArray.emplace_back(std::move(ethIface));
- }
- asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
- });
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EthernetInterfaceCollection."
+ "EthernetInterfaceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces";
+ asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet "
+ "Interface Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Virtual Management "
+ "Interfaces for the hypervisor";
+
+ nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
+ ifaceArray = nlohmann::json::array();
+ for (const std::string& iface : ifaceList)
+ {
+ sdbusplus::message::object_path path(iface);
+ std::string name = path.filename();
+ if (name.empty())
+ {
+ continue;
+ }
+ nlohmann::json::object_t ethIface;
+ ethIface["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}",
+ name);
+ ifaceArray.emplace_back(std::move(ethIface));
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
+ });
}
inline void handleHypervisorEthernetInterfaceGet(
@@ -672,58 +673,43 @@ inline void handleHypervisorEthernetInterfaceGet(
id, [asyncResp, ifaceId{std::string(id)}](
bool success, const EthernetInterfaceData& ethData,
const std::vector<IPv4AddressData>& ipv4Data) {
- if (!success)
- {
- messages::resourceNotFound(asyncResp->res, "EthernetInterface",
- ifaceId);
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#EthernetInterface.v1_9_0.EthernetInterface";
- asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface";
- asyncResp->res.jsonValue["Description"] =
- "Hypervisor's Virtual Management Ethernet Interface";
- parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData,
- ipv4Data);
- });
+ if (!success)
+ {
+ messages::resourceNotFound(asyncResp->res, "EthernetInterface",
+ ifaceId);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#EthernetInterface.v1_9_0.EthernetInterface";
+ asyncResp->res.jsonValue["Name"] = "Hypervisor Ethernet Interface";
+ asyncResp->res.jsonValue["Description"] =
+ "Hypervisor's Virtual Management Ethernet Interface";
+ parseInterfaceData(asyncResp->res.jsonValue, ifaceId, ethData,
+ ipv4Data);
+ });
}
inline void handleHypervisorSystemGet(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
- sdbusplus::asio::getProperty<std::string>(
- *crow::connections::systemBus, "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
- [asyncResp](const boost::system::error_code& ec,
- const std::string& /*hostName*/) {
- if (ec)
- {
- messages::resourceNotFound(asyncResp->res, "System", "hypervisor");
- return;
- }
- BMCWEB_LOG_DEBUG("Hypervisor is available");
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#ComputerSystem.v1_6_0.ComputerSystem";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/hypervisor";
- asyncResp->res.jsonValue["Description"] = "Hypervisor";
- asyncResp->res.jsonValue["Name"] = "Hypervisor";
- asyncResp->res.jsonValue["Id"] = "hypervisor";
- asyncResp->res.jsonValue["SystemType"] = "OS";
- nlohmann::json::array_t managedBy;
- nlohmann::json::object_t manager;
- manager["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME);
- managedBy.emplace_back(std::move(manager));
- asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
- asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] =
- "/redfish/v1/Systems/hypervisor/EthernetInterfaces";
- getHypervisorState(asyncResp);
- getHypervisorActions(asyncResp);
- // TODO: Add "SystemType" : "hypervisor"
- });
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ComputerSystem.v1_6_0.ComputerSystem";
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/hypervisor";
+ asyncResp->res.jsonValue["Description"] = "Hypervisor";
+ asyncResp->res.jsonValue["Name"] = "Hypervisor";
+ asyncResp->res.jsonValue["Id"] = "hypervisor";
+ asyncResp->res.jsonValue["SystemType"] = computer_system::SystemType::OS;
+ nlohmann::json::array_t managedBy;
+ nlohmann::json::object_t manager;
+ manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ managedBy.emplace_back(std::move(manager));
+ asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
+ asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] =
+ "/redfish/v1/Systems/hypervisor/EthernetInterfaces";
+ getHypervisorState(asyncResp);
+ getHypervisorActions(asyncResp);
+ // TODO: Add "SystemType" : "hypervisor"
}
inline void handleHypervisorEthernetInterfacePatch(
@@ -742,10 +728,10 @@ inline void handleHypervisorEthernetInterfacePatch(
std::optional<std::vector<nlohmann::json::object_t>> ipv4Addresses;
std::optional<bool> ipv4DHCPEnabled;
- if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", hostName,
- "IPv4StaticAddresses", ipv4StaticAddresses,
- "IPv4Addresses", ipv4Addresses,
- "DHCPv4/DHCPEnabled", ipv4DHCPEnabled))
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "HostName", hostName, "IPv4StaticAddresses",
+ ipv4StaticAddresses, "IPv4Addresses", ipv4Addresses,
+ "DHCPv4/DHCPEnabled", ipv4DHCPEnabled))
{
return;
}
@@ -762,67 +748,70 @@ inline void handleHypervisorEthernetInterfacePatch(
ipv4StaticAddresses = std::move(ipv4StaticAddresses),
ipv4DHCPEnabled](bool success, const EthernetInterfaceData& ethData,
const std::vector<IPv4AddressData>&) mutable {
- if (!success)
- {
- messages::resourceNotFound(asyncResp->res, "EthernetInterface",
- ifaceId);
- return;
- }
-
- if (ipv4StaticAddresses)
- {
- std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>&
- ipv4Static = *ipv4StaticAddresses;
- if (ipv4Static.begin() == ipv4Static.end())
+ if (!success)
{
- messages::propertyValueTypeError(asyncResp->res,
- std::vector<std::string>(),
- "IPv4StaticAddresses");
+ messages::resourceNotFound(asyncResp->res, "EthernetInterface",
+ ifaceId);
return;
}
- // One and only one hypervisor instance supported
- if (ipv4Static.size() != 1)
+ if (ipv4StaticAddresses)
{
- messages::propertyValueFormatError(asyncResp->res, "[]",
- "IPv4StaticAddresses");
- return;
+ std::vector<std::variant<nlohmann::json::object_t,
+ std::nullptr_t>>& ipv4Static =
+ *ipv4StaticAddresses;
+ if (ipv4Static.begin() == ipv4Static.end())
+ {
+ messages::propertyValueTypeError(asyncResp->res,
+ std::vector<std::string>(),
+ "IPv4StaticAddresses");
+ return;
+ }
+
+ // One and only one hypervisor instance supported
+ if (ipv4Static.size() != 1)
+ {
+ messages::propertyValueFormatError(asyncResp->res, "[]",
+ "IPv4StaticAddresses");
+ return;
+ }
+
+ std::variant<nlohmann::json::object_t, std::nullptr_t>&
+ ipv4Json = ipv4Static[0];
+ // Check if the param is 'null'. If its null, it means
+ // that user wants to delete the IP address. Deleting
+ // the IP address is allowed only if its statically
+ // configured. Deleting the address originated from DHCP
+ // is not allowed.
+ if (std::holds_alternative<std::nullptr_t>(ipv4Json) &&
+ translateDhcpEnabledToBool(ethData.dhcpEnabled, true))
+ {
+ BMCWEB_LOG_INFO(
+ "Ignoring the delete on ipv4StaticAddresses "
+ "as the interface is DHCP enabled");
+ }
+ else
+ {
+ handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static,
+ asyncResp);
+ }
}
- std::variant<nlohmann::json::object_t, std::nullptr_t>& ipv4Json =
- ipv4Static[0];
- // Check if the param is 'null'. If its null, it means
- // that user wants to delete the IP address. Deleting
- // the IP address is allowed only if its statically
- // configured. Deleting the address originated from DHCP
- // is not allowed.
- if (std::holds_alternative<std::nullptr_t>(ipv4Json) &&
- translateDhcpEnabledToBool(ethData.dhcpEnabled, true))
+ if (hostName)
{
- BMCWEB_LOG_INFO("Ignoring the delete on ipv4StaticAddresses "
- "as the interface is DHCP enabled");
+ handleHypervisorHostnamePatch(*hostName, asyncResp);
}
- else
+
+ if (ipv4DHCPEnabled)
{
- handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, asyncResp);
+ setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp);
}
- }
-
- if (hostName)
- {
- handleHypervisorHostnamePatch(*hostName, asyncResp);
- }
- if (ipv4DHCPEnabled)
- {
- setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp);
- }
-
- // Set this interface to disabled/inactive. This will be set
- // to enabled/active by the pldm once the hypervisor
- // consumes the updated settings from the user.
- setIPv4InterfaceEnabled(ifaceId, false, asyncResp);
- });
+ // Set this interface to disabled/inactive. This will be set
+ // to enabled/active by the pldm once the hypervisor
+ // consumes the updated settings from the user.
+ setIPv4InterfaceEnabled(ifaceId, false, asyncResp);
+ });
asyncResp->res.result(boost::beast::http::status::accepted);
}
@@ -838,60 +827,56 @@ inline void handleHypervisorResetActionGet(
const boost::system::error_code& ec,
const std::vector<std::pair<std::string, std::vector<std::string>>>&
objInfo) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
-
- // No hypervisor objects found by mapper
- if (ec.value() == boost::system::errc::io_error)
+ if (ec)
{
- messages::resourceNotFound(asyncResp->res, "hypervisor",
- "ResetActionInfo");
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+
+ // No hypervisor objects found by mapper
+ if (ec.value() == boost::system::errc::io_error)
+ {
+ messages::resourceNotFound(asyncResp->res, "hypervisor",
+ "ResetActionInfo");
+ return;
+ }
+
+ messages::internalError(asyncResp->res);
return;
}
- messages::internalError(asyncResp->res);
- return;
- }
-
- // One and only one hypervisor instance supported
- if (objInfo.size() != 1)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ // One and only one hypervisor instance supported
+ if (objInfo.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // The hypervisor object only support the ability to
- // turn On The system object Action should be utilized
- // for other operations
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#ActionInfo.v1_1_2.ActionInfo";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/hypervisor/ResetActionInfo";
- asyncResp->res.jsonValue["Name"] = "Reset Action Info";
- asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
- nlohmann::json::array_t parameters;
- nlohmann::json::object_t parameter;
- parameter["Name"] = "ResetType";
- parameter["Required"] = true;
- parameter["DataType"] = "String";
- nlohmann::json::array_t allowed;
- allowed.emplace_back("On");
- parameter["AllowableValues"] = std::move(allowed);
- parameters.emplace_back(std::move(parameter));
- asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
- });
+ // The hypervisor object only support the ability to
+ // turn On The system object Action should be utilized
+ // for other operations
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ActionInfo.v1_1_2.ActionInfo";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/hypervisor/ResetActionInfo";
+ asyncResp->res.jsonValue["Name"] = "Reset Action Info";
+ asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
+ nlohmann::json::array_t parameters;
+ nlohmann::json::object_t parameter;
+ parameter["Name"] = "ResetType";
+ parameter["Required"] = true;
+ parameter["DataType"] = action_info::ParameterTypes::String;
+ nlohmann::json::array_t allowed;
+ allowed.emplace_back("On");
+ parameter["AllowableValues"] = std::move(allowed);
+ parameters.emplace_back(std::move(parameter));
+ asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
+ });
}
inline void handleHypervisorSystemResetPost(
- App& app, const crow::Request& req,
+ const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
std::optional<std::string> resetType;
if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType))
{
@@ -916,12 +901,12 @@ inline void handleHypervisorSystemResetPost(
std::string command = "xyz.openbmc_project.State.Host.Transition.On";
- setDbusPropertyAction(asyncResp, "xyz.openbmc_project.State.Hypervisor",
- sdbusplus::message::object_path(
- "/xyz/openbmc_project/state/hypervisor0"),
- "xyz.openbmc_project.State.Host",
- "RequestedHostTransition", "ResetType",
- "ComputerSystem.Reset", command);
+ setDbusPropertyAction(
+ asyncResp, "xyz.openbmc_project.State.Hypervisor",
+ sdbusplus::message::object_path(
+ "/xyz/openbmc_project/state/hypervisor0"),
+ "xyz.openbmc_project.State.Host", "RequestedHostTransition",
+ "ResetType", "ComputerSystem.Reset", command);
}
inline void requestRoutesHypervisorSystems(App& app)
@@ -947,11 +932,5 @@ inline void requestRoutesHypervisorSystems(App& app)
.privileges(redfish::privileges::patchEthernetInterface)
.methods(boost::beast::http::verb::patch)(std::bind_front(
handleHypervisorEthernetInterfacePatch, std::ref(app)));
-
- BMCWEB_ROUTE(app,
- "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/")
- .privileges(redfish::privileges::postComputerSystem)
- .methods(boost::beast::http::verb::post)(
- std::bind_front(handleHypervisorSystemResetPost, std::ref(app)));
}
} // namespace redfish
diff --git a/redfish-core/lib/led.hpp b/redfish-core/lib/led.hpp
index 8cbe86ac94..1acde11dc8 100644
--- a/redfish-core/lib/led.hpp
+++ b/redfish-core/lib/led.hpp
@@ -1,23 +1,24 @@
/*
-// Copyright (c) 2019 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2019 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/chassis.hpp"
#include "redfish_util.hpp"
#include <sdbusplus/asio/property.hpp>
@@ -41,53 +42,56 @@ inline void
"/xyz/openbmc_project/led/groups/enclosure_identify_blink",
"xyz.openbmc_project.Led.Group", "Asserted",
[asyncResp](const boost::system::error_code& ec, const bool blinking) {
- // Some systems may not have enclosure_identify_blink object so
- // proceed to get enclosure_identify state.
- if (ec == boost::system::errc::invalid_argument)
- {
- BMCWEB_LOG_DEBUG(
- "Get identity blinking LED failed, mismatch in property type");
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Blinking ON, no need to check enclosure_identify assert.
- if (!ec && blinking)
- {
- asyncResp->res.jsonValue["IndicatorLED"] = "Blinking";
- return;
- }
-
- sdbusplus::asio::getProperty<bool>(
- *crow::connections::systemBus,
- "xyz.openbmc_project.LED.GroupManager",
- "/xyz/openbmc_project/led/groups/enclosure_identify",
- "xyz.openbmc_project.Led.Group", "Asserted",
- [asyncResp](const boost::system::error_code& ec2,
- const bool ledOn) {
- if (ec2 == boost::system::errc::invalid_argument)
+ // Some systems may not have enclosure_identify_blink object so
+ // proceed to get enclosure_identify state.
+ if (ec == boost::system::errc::invalid_argument)
{
BMCWEB_LOG_DEBUG(
- "Get enclosure identity led failed, mismatch in property type");
+ "Get identity blinking LED failed, mismatch in property type");
messages::internalError(asyncResp->res);
return;
}
- if (ec2)
+ // Blinking ON, no need to check enclosure_identify assert.
+ if (!ec && blinking)
{
+ asyncResp->res.jsonValue["IndicatorLED"] =
+ chassis::IndicatorLED::Blinking;
return;
}
- if (ledOn)
- {
- asyncResp->res.jsonValue["IndicatorLED"] = "Lit";
- }
- else
- {
- asyncResp->res.jsonValue["IndicatorLED"] = "Off";
- }
+ sdbusplus::asio::getProperty<bool>(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.LED.GroupManager",
+ "/xyz/openbmc_project/led/groups/enclosure_identify",
+ "xyz.openbmc_project.Led.Group", "Asserted",
+ [asyncResp](const boost::system::error_code& ec2,
+ const bool ledOn) {
+ if (ec2 == boost::system::errc::invalid_argument)
+ {
+ BMCWEB_LOG_DEBUG(
+ "Get enclosure identity led failed, mismatch in property type");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (ec2)
+ {
+ return;
+ }
+
+ if (ledOn)
+ {
+ asyncResp->res.jsonValue["IndicatorLED"] =
+ chassis::IndicatorLED::Lit;
+ }
+ else
+ {
+ asyncResp->res.jsonValue["IndicatorLED"] =
+ chassis::IndicatorLED::Off;
+ }
+ });
});
- });
}
/**
@@ -128,22 +132,23 @@ inline void
"xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng,
[asyncResp, ledOn,
ledBlinkng](const boost::system::error_code& ec) mutable {
- if (ec)
- {
- // Some systems may not have enclosure_identify_blink object so
- // Lets set enclosure_identify state to true if Blinking is
- // true.
- if (ledBlinkng)
+ if (ec)
{
- ledOn = true;
+ // Some systems may not have enclosure_identify_blink object so
+ // Lets set enclosure_identify state to true if Blinking is
+ // true.
+ if (ledBlinkng)
+ {
+ ledOn = true;
+ }
}
- }
- setDbusProperty(
- asyncResp, "IndicatorLED", "xyz.openbmc_project.LED.GroupManager",
- sdbusplus::message::object_path(
- "/xyz/openbmc_project/led/groups/enclosure_identify"),
- "xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng);
- });
+ setDbusProperty(
+ asyncResp, "IndicatorLED",
+ "xyz.openbmc_project.LED.GroupManager",
+ sdbusplus::message::object_path(
+ "/xyz/openbmc_project/led/groups/enclosure_identify"),
+ "xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng);
+ });
}
/**
@@ -162,46 +167,46 @@ inline void getSystemLocationIndicatorActive(
"/xyz/openbmc_project/led/groups/enclosure_identify_blink",
"xyz.openbmc_project.Led.Group", "Asserted",
[asyncResp](const boost::system::error_code& ec, const bool blinking) {
- // Some systems may not have enclosure_identify_blink object so
- // proceed to get enclosure_identify state.
- if (ec == boost::system::errc::invalid_argument)
- {
- BMCWEB_LOG_DEBUG(
- "Get identity blinking LED failed, mismatch in property type");
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Blinking ON, no need to check enclosure_identify assert.
- if (!ec && blinking)
- {
- asyncResp->res.jsonValue["LocationIndicatorActive"] = true;
- return;
- }
-
- sdbusplus::asio::getProperty<bool>(
- *crow::connections::systemBus,
- "xyz.openbmc_project.LED.GroupManager",
- "/xyz/openbmc_project/led/groups/enclosure_identify",
- "xyz.openbmc_project.Led.Group", "Asserted",
- [asyncResp](const boost::system::error_code& ec2,
- const bool ledOn) {
- if (ec2 == boost::system::errc::invalid_argument)
+ // Some systems may not have enclosure_identify_blink object so
+ // proceed to get enclosure_identify state.
+ if (ec == boost::system::errc::invalid_argument)
{
BMCWEB_LOG_DEBUG(
- "Get enclosure identity led failed, mismatch in property type");
+ "Get identity blinking LED failed, mismatch in property type");
messages::internalError(asyncResp->res);
return;
}
- if (ec2)
+ // Blinking ON, no need to check enclosure_identify assert.
+ if (!ec && blinking)
{
+ asyncResp->res.jsonValue["LocationIndicatorActive"] = true;
return;
}
- asyncResp->res.jsonValue["LocationIndicatorActive"] = ledOn;
+ sdbusplus::asio::getProperty<bool>(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.LED.GroupManager",
+ "/xyz/openbmc_project/led/groups/enclosure_identify",
+ "xyz.openbmc_project.Led.Group", "Asserted",
+ [asyncResp](const boost::system::error_code& ec2,
+ const bool ledOn) {
+ if (ec2 == boost::system::errc::invalid_argument)
+ {
+ BMCWEB_LOG_DEBUG(
+ "Get enclosure identity led failed, mismatch in property type");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (ec2)
+ {
+ return;
+ }
+
+ asyncResp->res.jsonValue["LocationIndicatorActive"] = ledOn;
+ });
});
- });
}
/**
@@ -222,18 +227,18 @@ inline void setSystemLocationIndicatorActive(
"/xyz/openbmc_project/led/groups/enclosure_identify_blink",
"xyz.openbmc_project.Led.Group", "Asserted", ledState,
[asyncResp, ledState](const boost::system::error_code& ec) {
- if (ec)
- {
- // Some systems may not have enclosure_identify_blink object so
- // lets set enclosure_identify state also if
- // enclosure_identify_blink failed
- setDbusProperty(
- asyncResp, "LocationIndicatorActive",
- "xyz.openbmc_project.LED.GroupManager",
- sdbusplus::message::object_path(
- "/xyz/openbmc_project/led/groups/enclosure_identify"),
- "xyz.openbmc_project.Led.Group", "Asserted", ledState);
- }
- });
+ if (ec)
+ {
+ // Some systems may not have enclosure_identify_blink object so
+ // lets set enclosure_identify state also if
+ // enclosure_identify_blink failed
+ setDbusProperty(
+ asyncResp, "LocationIndicatorActive",
+ "xyz.openbmc_project.LED.GroupManager",
+ sdbusplus::message::object_path(
+ "/xyz/openbmc_project/led/groups/enclosure_identify"),
+ "xyz.openbmc_project.Led.Group", "Asserted", ledState);
+ }
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index da2d1b55ad..639a31488c 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -19,6 +19,7 @@
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "generated/enums/log_entry.hpp"
+#include "generated/enums/log_service.hpp"
#include "gzfile.hpp"
#include "http_utility.hpp"
#include "human_sort.hpp"
@@ -29,12 +30,12 @@
#include "registries/privilege_registry.hpp"
#include "task.hpp"
#include "task_messages.hpp"
+#include "utils/dbus_event_log_entry.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/time_utils.hpp"
#include <systemd/sd-id128.h>
-#include <systemd/sd-journal.h>
#include <tinyxml2.h>
#include <unistd.h>
@@ -125,110 +126,7 @@ inline std::string getDumpPath(std::string_view dumpType)
return dbusDumpPath;
}
-inline int getJournalMetadata(sd_journal* journal, std::string_view field,
- std::string_view& contents)
-{
- const char* data = nullptr;
- size_t length = 0;
- int ret = 0;
- // Get the metadata from the requested field of the journal entry
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- const void** dataVoid = reinterpret_cast<const void**>(&data);
-
- ret = sd_journal_get_data(journal, field.data(), dataVoid, &length);
- if (ret < 0)
- {
- return ret;
- }
- contents = std::string_view(data, length);
- // Only use the content after the "=" character.
- contents.remove_prefix(std::min(contents.find('=') + 1, contents.size()));
- return ret;
-}
-
-inline int getJournalMetadata(sd_journal* journal, std::string_view field,
- const int& base, long int& contents)
-{
- int ret = 0;
- std::string_view metadata;
- // Get the metadata from the requested field of the journal entry
- ret = getJournalMetadata(journal, field, metadata);
- if (ret < 0)
- {
- return ret;
- }
- contents = strtol(metadata.data(), nullptr, base);
- return ret;
-}
-
-inline bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
-{
- int ret = 0;
- uint64_t timestamp = 0;
- ret = sd_journal_get_realtime_usec(journal, &timestamp);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}", strerror(-ret));
- return false;
- }
- entryTimestamp = redfish::time_utils::getDateTimeUintUs(timestamp);
- return true;
-}
-
-inline bool getUniqueEntryID(sd_journal* journal, std::string& entryID,
- const bool firstEntry = true)
-{
- int ret = 0;
- static sd_id128_t prevBootID{};
- static uint64_t prevTs = 0;
- static int index = 0;
- if (firstEntry)
- {
- prevBootID = {};
- prevTs = 0;
- }
-
- // Get the entry timestamp
- uint64_t curTs = 0;
- sd_id128_t curBootID{};
- ret = sd_journal_get_monotonic_usec(journal, &curTs, &curBootID);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}", strerror(-ret));
- return false;
- }
- // If the timestamp isn't unique on the same boot, increment the index
- bool sameBootIDs = sd_id128_equal(curBootID, prevBootID) != 0;
- if (sameBootIDs && (curTs == prevTs))
- {
- index++;
- }
- else
- {
- // Otherwise, reset it
- index = 0;
- }
-
- if (!sameBootIDs)
- {
- // Save the bootID
- prevBootID = curBootID;
- }
- // Save the timestamp
- prevTs = curTs;
-
- // make entryID as <bootID>_<timestamp>[_<index>]
- std::array<char, SD_ID128_STRING_MAX> bootIDStr{};
- sd_id128_to_string(curBootID, bootIDStr.data());
- entryID = std::format("{}_{}", bootIDStr.data(), curTs);
- if (index > 0)
- {
- entryID += "_" + std::to_string(index);
- }
- return true;
-}
-
-static bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
+inline bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
const bool firstEntry = true)
{
static time_t prevTs = 0;
@@ -267,70 +165,7 @@ static bool getUniqueEntryID(const std::string& logEntry, std::string& entryID,
return true;
}
-// Entry is formed like "BootID_timestamp" or "BootID_timestamp_index"
inline bool
- getTimestampFromID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- std::string_view entryIDStrView, sd_id128_t& bootID,
- uint64_t& timestamp, uint64_t& index)
-{
- // Convert the unique ID back to a bootID + timestamp to find the entry
- auto underscore1Pos = entryIDStrView.find('_');
- if (underscore1Pos == std::string_view::npos)
- {
- // EntryID has no bootID or timestamp
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
- return false;
- }
-
- // EntryID has bootID + timestamp
-
- // Convert entryIDViewString to BootID
- // NOTE: bootID string which needs to be null-terminated for
- // sd_id128_from_string()
- std::string bootIDStr(entryIDStrView.substr(0, underscore1Pos));
- if (sd_id128_from_string(bootIDStr.c_str(), &bootID) < 0)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
- return false;
- }
-
- // Get the timestamp from entryID
- entryIDStrView.remove_prefix(underscore1Pos + 1);
-
- auto [timestampEnd, tstampEc] = std::from_chars(
- entryIDStrView.begin(), entryIDStrView.end(), timestamp);
- if (tstampEc != std::errc())
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
- return false;
- }
- entryIDStrView = std::string_view(
- timestampEnd,
- static_cast<size_t>(std::distance(timestampEnd, entryIDStrView.end())));
- if (entryIDStrView.empty())
- {
- index = 0U;
- return true;
- }
- // Timestamp might include optional index, if two events happened at the
- // same "time".
- if (entryIDStrView[0] != '_')
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
- return false;
- }
- entryIDStrView.remove_prefix(1);
- auto [ptr, indexEc] = std::from_chars(entryIDStrView.begin(),
- entryIDStrView.end(), index);
- if (indexEc != std::errc() || ptr != entryIDStrView.end())
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
- return false;
- }
- return true;
-}
-
-static bool
getRedfishLogFiles(std::vector<std::filesystem::path>& redfishLogFiles)
{
static const std::filesystem::path redfishLogDir = "/var/log";
@@ -525,102 +360,103 @@ inline void
[asyncResp, entriesPath,
dumpType](const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& objects) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Remove ending slash
- std::string odataIdStr = entriesPath;
- if (!odataIdStr.empty())
- {
- odataIdStr.pop_back();
- }
+ // Remove ending slash
+ std::string odataIdStr = entriesPath;
+ if (!odataIdStr.empty())
+ {
+ odataIdStr.pop_back();
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
- asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
- asyncResp->res.jsonValue["Description"] = "Collection of " + dumpType +
- " Dump Entries";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
+ asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of " + dumpType + " Dump Entries";
- nlohmann::json::array_t entriesArray;
- std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
+ nlohmann::json::array_t entriesArray;
+ std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
- dbus::utility::ManagedObjectType resp(objects);
- std::ranges::sort(resp, [](const auto& l, const auto& r) {
- return AlphanumLess<std::string>()(l.first.filename(),
- r.first.filename());
- });
+ dbus::utility::ManagedObjectType resp(objects);
+ std::ranges::sort(resp, [](const auto& l, const auto& r) {
+ return AlphanumLess<std::string>()(l.first.filename(),
+ r.first.filename());
+ });
- for (auto& object : resp)
- {
- if (object.first.str.find(dumpEntryPath) == std::string::npos)
+ for (auto& object : resp)
{
- continue;
- }
- uint64_t timestampUs = 0;
- uint64_t size = 0;
- std::string dumpStatus;
- std::string originatorId;
- log_entry::OriginatorTypes originatorType =
- log_entry::OriginatorTypes::Internal;
- nlohmann::json::object_t thisEntry;
-
- std::string entryID = object.first.filename();
- if (entryID.empty())
- {
- continue;
- }
+ if (object.first.str.find(dumpEntryPath) == std::string::npos)
+ {
+ continue;
+ }
+ uint64_t timestampUs = 0;
+ uint64_t size = 0;
+ std::string dumpStatus;
+ std::string originatorId;
+ log_entry::OriginatorTypes originatorType =
+ log_entry::OriginatorTypes::Internal;
+ nlohmann::json::object_t thisEntry;
+
+ std::string entryID = object.first.filename();
+ if (entryID.empty())
+ {
+ continue;
+ }
- parseDumpEntryFromDbusObject(object, dumpStatus, size, timestampUs,
- originatorId, originatorType,
- asyncResp);
+ parseDumpEntryFromDbusObject(object, dumpStatus, size,
+ timestampUs, originatorId,
+ originatorType, asyncResp);
- if (dumpStatus !=
- "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
- !dumpStatus.empty())
- {
- // Dump status is not Complete, no need to enumerate
- continue;
- }
+ if (dumpStatus !=
+ "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
+ !dumpStatus.empty())
+ {
+ // Dump status is not Complete, no need to enumerate
+ continue;
+ }
- thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
- thisEntry["@odata.id"] = entriesPath + entryID;
- thisEntry["Id"] = entryID;
- thisEntry["EntryType"] = "Event";
- thisEntry["Name"] = dumpType + " Dump Entry";
- thisEntry["Created"] =
- redfish::time_utils::getDateTimeUintUs(timestampUs);
+ thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
+ thisEntry["@odata.id"] = entriesPath + entryID;
+ thisEntry["Id"] = entryID;
+ thisEntry["EntryType"] = "Event";
+ thisEntry["Name"] = dumpType + " Dump Entry";
+ thisEntry["Created"] =
+ redfish::time_utils::getDateTimeUintUs(timestampUs);
- if (!originatorId.empty())
- {
- thisEntry["Originator"] = originatorId;
- thisEntry["OriginatorType"] = originatorType;
- }
+ if (!originatorId.empty())
+ {
+ thisEntry["Originator"] = originatorId;
+ thisEntry["OriginatorType"] = originatorType;
+ }
- if (dumpType == "BMC")
- {
- thisEntry["DiagnosticDataType"] = "Manager";
- thisEntry["AdditionalDataURI"] = entriesPath + entryID +
- "/attachment";
- thisEntry["AdditionalDataSizeBytes"] = size;
- }
- else if (dumpType == "System")
- {
- thisEntry["DiagnosticDataType"] = "OEM";
- thisEntry["OEMDiagnosticDataType"] = "System";
- thisEntry["AdditionalDataURI"] = entriesPath + entryID +
- "/attachment";
- thisEntry["AdditionalDataSizeBytes"] = size;
+ if (dumpType == "BMC")
+ {
+ thisEntry["DiagnosticDataType"] = "Manager";
+ thisEntry["AdditionalDataURI"] =
+ entriesPath + entryID + "/attachment";
+ thisEntry["AdditionalDataSizeBytes"] = size;
+ }
+ else if (dumpType == "System")
+ {
+ thisEntry["DiagnosticDataType"] = "OEM";
+ thisEntry["OEMDiagnosticDataType"] = "System";
+ thisEntry["AdditionalDataURI"] =
+ entriesPath + entryID + "/attachment";
+ thisEntry["AdditionalDataSizeBytes"] = size;
+ }
+ entriesArray.emplace_back(std::move(thisEntry));
}
- entriesArray.emplace_back(std::move(thisEntry));
- }
- asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
- asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
- });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ entriesArray.size();
+ asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
+ });
}
inline void
@@ -640,85 +476,86 @@ inline void
[asyncResp, entryID, dumpType,
entriesPath](const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& resp) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- bool foundDumpEntry = false;
- std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
-
- for (const auto& objectPath : resp)
- {
- if (objectPath.first.str != dumpEntryPath + entryID)
- {
- continue;
- }
-
- foundDumpEntry = true;
- uint64_t timestampUs = 0;
- uint64_t size = 0;
- std::string dumpStatus;
- std::string originatorId;
- log_entry::OriginatorTypes originatorType =
- log_entry::OriginatorTypes::Internal;
-
- parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
- timestampUs, originatorId,
- originatorType, asyncResp);
-
- if (dumpStatus !=
- "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
- !dumpStatus.empty())
+ if (ec)
{
- // Dump status is not Complete
- // return not found until status is changed to Completed
- messages::resourceNotFound(asyncResp->res, dumpType + " dump",
- entryID);
+ BMCWEB_LOG_ERROR("DumpEntry resp_handler got error {}", ec);
+ messages::internalError(asyncResp->res);
return;
}
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntry.v1_11_0.LogEntry";
- asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
- asyncResp->res.jsonValue["Id"] = entryID;
- asyncResp->res.jsonValue["EntryType"] = "Event";
- asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
- asyncResp->res.jsonValue["Created"] =
- redfish::time_utils::getDateTimeUintUs(timestampUs);
-
- if (!originatorId.empty())
- {
- asyncResp->res.jsonValue["Originator"] = originatorId;
- asyncResp->res.jsonValue["OriginatorType"] = originatorType;
- }
+ bool foundDumpEntry = false;
+ std::string dumpEntryPath = getDumpPath(dumpType) + "/entry/";
- if (dumpType == "BMC")
+ for (const auto& objectPath : resp)
{
- asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
- asyncResp->res.jsonValue["AdditionalDataURI"] =
- entriesPath + entryID + "/attachment";
- asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
+ if (objectPath.first.str != dumpEntryPath + entryID)
+ {
+ continue;
+ }
+
+ foundDumpEntry = true;
+ uint64_t timestampUs = 0;
+ uint64_t size = 0;
+ std::string dumpStatus;
+ std::string originatorId;
+ log_entry::OriginatorTypes originatorType =
+ log_entry::OriginatorTypes::Internal;
+
+ parseDumpEntryFromDbusObject(objectPath, dumpStatus, size,
+ timestampUs, originatorId,
+ originatorType, asyncResp);
+
+ if (dumpStatus !=
+ "xyz.openbmc_project.Common.Progress.OperationStatus.Completed" &&
+ !dumpStatus.empty())
+ {
+ // Dump status is not Complete
+ // return not found until status is changed to Completed
+ messages::resourceNotFound(asyncResp->res,
+ dumpType + " dump", entryID);
+ return;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntry.v1_11_0.LogEntry";
+ asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
+ asyncResp->res.jsonValue["Id"] = entryID;
+ asyncResp->res.jsonValue["EntryType"] = "Event";
+ asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
+ asyncResp->res.jsonValue["Created"] =
+ redfish::time_utils::getDateTimeUintUs(timestampUs);
+
+ if (!originatorId.empty())
+ {
+ asyncResp->res.jsonValue["Originator"] = originatorId;
+ asyncResp->res.jsonValue["OriginatorType"] = originatorType;
+ }
+
+ if (dumpType == "BMC")
+ {
+ asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
+ asyncResp->res.jsonValue["AdditionalDataURI"] =
+ entriesPath + entryID + "/attachment";
+ asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
+ }
+ else if (dumpType == "System")
+ {
+ asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
+ asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
+ "System";
+ asyncResp->res.jsonValue["AdditionalDataURI"] =
+ entriesPath + entryID + "/attachment";
+ asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
+ }
}
- else if (dumpType == "System")
+ if (!foundDumpEntry)
{
- asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
- asyncResp->res.jsonValue["OEMDiagnosticDataType"] = "System";
- asyncResp->res.jsonValue["AdditionalDataURI"] =
- entriesPath + entryID + "/attachment";
- asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
+ BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
+ messages::resourceNotFound(asyncResp->res, dumpType + " dump",
+ entryID);
+ return;
}
- }
- if (!foundDumpEntry)
- {
- BMCWEB_LOG_WARNING("Can't find Dump Entry {}", entryID);
- messages::resourceNotFound(asyncResp->res, dumpType + " dump",
- entryID);
- return;
- }
- });
+ });
}
inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -777,12 +614,11 @@ inline bool checkSizeLimit(int fd, crow::Response& res)
}
return true;
}
-inline void
- downloadEntryCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& entryID,
- const std::string& downloadEntryType,
- const boost::system::error_code& ec,
- const sdbusplus::message::unix_fd& unixfd)
+inline void downloadEntryCallback(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryID, const std::string& downloadEntryType,
+ const boost::system::error_code& ec,
+ const sdbusplus::message::unix_fd& unixfd)
{
if (ec.value() == EBADR)
{
@@ -850,26 +686,25 @@ inline void
return;
}
- std::string dumpEntryPath = std::format("{}/entry/{}",
- getDumpPath(dumpType), entryID);
+ std::string dumpEntryPath =
+ std::format("{}/entry/{}", getDumpPath(dumpType), entryID);
auto downloadDumpEntryHandler =
[asyncResp, entryID,
dumpType](const boost::system::error_code& ec,
const sdbusplus::message::unix_fd& unixfd) {
- downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
- };
+ downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
+ };
crow::connections::systemBus->async_method_call(
std::move(downloadDumpEntryHandler), "xyz.openbmc_project.Dump.Manager",
dumpEntryPath, "xyz.openbmc_project.Dump.Entry", "GetFileHandle");
}
-inline void
- downloadEventLogEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& entryID,
- const std::string& dumpType)
+inline void downloadEventLogEntry(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& entryID,
+ const std::string& dumpType)
{
if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
{
@@ -893,8 +728,8 @@ inline void
[asyncResp, entryID,
dumpType](const boost::system::error_code& ec,
const sdbusplus::message::unix_fd& unixfd) {
- downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
- };
+ downloadEntryCallback(asyncResp, entryID, dumpType, ec, unixfd);
+ };
crow::connections::systemBus->async_method_call(
std::move(downloadEventLogEntryHandler), "xyz.openbmc_project.Logging",
@@ -942,7 +777,7 @@ inline std::string getDumpEntryPath(const std::string& dumpPath)
if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry")
{
return std::format("/redfish/v1/Managers/{}/LogServices/Dump/Entries/",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
}
if (dumpPath == "/xyz/openbmc_project/dump/system/entry")
{
@@ -974,114 +809,121 @@ inline void createDumpTaskCallback(
dumpEntryPath{std::move(dumpEntryPath)},
dumpId](const boost::system::error_code& ec,
const std::string& introspectXml) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
- ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Check if the created dump object has implemented Progress
- // interface to track dump completion. If yes, fetch the "Status"
- // property of the interface, modify the task state accordingly.
- // Else, return task completed.
- tinyxml2::XMLDocument doc;
-
- doc.Parse(introspectXml.data(), introspectXml.size());
- tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
- if (pRoot == nullptr)
- {
- BMCWEB_LOG_ERROR("XML document failed to parse");
- messages::internalError(asyncResp->res);
- return;
- }
- tinyxml2::XMLElement* interfaceNode =
- pRoot->FirstChildElement("interface");
-
- bool isProgressIntfPresent = false;
- while (interfaceNode != nullptr)
- {
- const char* thisInterfaceName = interfaceNode->Attribute("name");
- if (thisInterfaceName != nullptr)
+ if (ec)
{
- if (thisInterfaceName ==
- std::string_view("xyz.openbmc_project.Common.Progress"))
- {
- interfaceNode =
- interfaceNode->NextSiblingElement("interface");
- continue;
- }
- isProgressIntfPresent = true;
- break;
+ BMCWEB_LOG_ERROR("Introspect call failed with error: {}",
+ ec.message());
+ messages::internalError(asyncResp->res);
+ return;
}
- interfaceNode = interfaceNode->NextSiblingElement("interface");
- }
- std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
- [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
- const boost::system::error_code& ec2, sdbusplus::message_t& msg,
- const std::shared_ptr<task::TaskData>& taskData) {
- if (ec2)
+ // Check if the created dump object has implemented Progress
+ // interface to track dump completion. If yes, fetch the "Status"
+ // property of the interface, modify the task state accordingly.
+ // Else, return task completed.
+ tinyxml2::XMLDocument doc;
+
+ doc.Parse(introspectXml.data(), introspectXml.size());
+ tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
+ if (pRoot == nullptr)
{
- BMCWEB_LOG_ERROR("{}: Error in creating dump",
- createdObjPath.str);
- taskData->messages.emplace_back(messages::internalError());
- taskData->state = "Cancelled";
- return task::completed;
+ BMCWEB_LOG_ERROR("XML document failed to parse");
+ messages::internalError(asyncResp->res);
+ return;
}
+ tinyxml2::XMLElement* interfaceNode =
+ pRoot->FirstChildElement("interface");
- if (isProgressIntfPresent)
+ bool isProgressIntfPresent = false;
+ while (interfaceNode != nullptr)
{
- dbus::utility::DBusPropertiesMap values;
- std::string prop;
- msg.read(prop, values);
-
- DumpCreationProgress dumpStatus =
- getDumpCompletionStatus(values);
- if (dumpStatus == DumpCreationProgress::DUMP_CREATE_FAILED)
- {
- BMCWEB_LOG_ERROR("{}: Error in creating dump",
- createdObjPath.str);
- taskData->state = "Cancelled";
- return task::completed;
- }
-
- if (dumpStatus == DumpCreationProgress::DUMP_CREATE_INPROGRESS)
+ const char* thisInterfaceName =
+ interfaceNode->Attribute("name");
+ if (thisInterfaceName != nullptr)
{
- BMCWEB_LOG_DEBUG("{}: Dump creation task is in progress",
- createdObjPath.str);
- return !task::completed;
+ if (thisInterfaceName ==
+ std::string_view("xyz.openbmc_project.Common.Progress"))
+ {
+ interfaceNode =
+ interfaceNode->NextSiblingElement("interface");
+ continue;
+ }
+ isProgressIntfPresent = true;
+ break;
}
+ interfaceNode = interfaceNode->NextSiblingElement("interface");
}
- nlohmann::json retMessage = messages::success();
- taskData->messages.emplace_back(retMessage);
+ std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
+ [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
+ const boost::system::error_code& ec2,
+ sdbusplus::message_t& msg,
+ const std::shared_ptr<task::TaskData>& taskData) {
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR("{}: Error in creating dump",
+ createdObjPath.str);
+ taskData->messages.emplace_back(
+ messages::internalError());
+ taskData->state = "Cancelled";
+ return task::completed;
+ }
- boost::urls::url url = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
+ if (isProgressIntfPresent)
+ {
+ dbus::utility::DBusPropertiesMap values;
+ std::string prop;
+ msg.read(prop, values);
+
+ DumpCreationProgress dumpStatus =
+ getDumpCompletionStatus(values);
+ if (dumpStatus ==
+ DumpCreationProgress::DUMP_CREATE_FAILED)
+ {
+ BMCWEB_LOG_ERROR("{}: Error in creating dump",
+ createdObjPath.str);
+ taskData->state = "Cancelled";
+ return task::completed;
+ }
- std::string headerLoc = "Location: ";
- headerLoc += url.buffer();
+ if (dumpStatus ==
+ DumpCreationProgress::DUMP_CREATE_INPROGRESS)
+ {
+ BMCWEB_LOG_DEBUG(
+ "{}: Dump creation task is in progress",
+ createdObjPath.str);
+ return !task::completed;
+ }
+ }
+
+ nlohmann::json retMessage = messages::success();
+ taskData->messages.emplace_back(retMessage);
- taskData->payload->httpHeaders.emplace_back(std::move(headerLoc));
+ boost::urls::url url = boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/Dump/Entries/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, dumpId);
- BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
- createdObjPath.str);
- taskData->state = "Completed";
- return task::completed;
+ std::string headerLoc = "Location: ";
+ headerLoc += url.buffer();
+
+ taskData->payload->httpHeaders.emplace_back(
+ std::move(headerLoc));
+
+ BMCWEB_LOG_DEBUG("{}: Dump creation task completed",
+ createdObjPath.str);
+ taskData->state = "Completed";
+ return task::completed;
+ },
+ "type='signal',interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',path='" +
+ createdObjPath.str + "'");
+
+ // The task timer is set to max time limit within which the
+ // requested dump will be collected.
+ task->startTimer(std::chrono::minutes(6));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(payload);
},
- "type='signal',interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged',path='" +
- createdObjPath.str + "'");
-
- // The task timer is set to max time limit within which the
- // requested dump will be collected.
- task->startTimer(std::chrono::minutes(6));
- task->populateResp(asyncResp->res);
- task->payload.emplace(payload);
- },
"xyz.openbmc_project.Dump.Manager", createdObjPath,
"org.freedesktop.DBus.Introspectable", "Introspect");
}
@@ -1172,52 +1014,52 @@ inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
dumpPath](const boost::system::error_code& ec,
const sdbusplus::message_t& msg,
const sdbusplus::message::object_path& objPath) mutable {
- if (ec)
- {
- BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
- const sd_bus_error* dbusError = msg.get_error();
- if (dbusError == nullptr)
+ if (ec)
{
- messages::internalError(asyncResp->res);
- return;
- }
+ BMCWEB_LOG_ERROR("CreateDump resp_handler got error {}", ec);
+ const sd_bus_error* dbusError = msg.get_error();
+ if (dbusError == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
- dbusError->name, dbusError->message);
- if (std::string_view(
- "xyz.openbmc_project.Common.Error.NotAllowed") ==
- dbusError->name)
- {
- messages::resourceInStandby(asyncResp->res);
- return;
- }
- if (std::string_view(
- "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
- dbusError->name)
- {
- messages::serviceDisabled(asyncResp->res, dumpPath);
- return;
- }
- if (std::string_view(
- "xyz.openbmc_project.Common.Error.Unavailable") ==
- dbusError->name)
- {
- messages::resourceInUse(asyncResp->res);
+ BMCWEB_LOG_ERROR("CreateDump DBus error: {} and error msg: {}",
+ dbusError->name, dbusError->message);
+ if (std::string_view(
+ "xyz.openbmc_project.Common.Error.NotAllowed") ==
+ dbusError->name)
+ {
+ messages::resourceInStandby(asyncResp->res);
+ return;
+ }
+ if (std::string_view(
+ "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
+ dbusError->name)
+ {
+ messages::serviceDisabled(asyncResp->res, dumpPath);
+ return;
+ }
+ if (std::string_view(
+ "xyz.openbmc_project.Common.Error.Unavailable") ==
+ dbusError->name)
+ {
+ messages::resourceInUse(asyncResp->res);
+ return;
+ }
+ // Other Dbus errors such as:
+ // xyz.openbmc_project.Common.Error.InvalidArgument &
+ // org.freedesktop.DBus.Error.InvalidArgs are all related to
+ // the dbus call that is made here in the bmcweb
+ // implementation and has nothing to do with the client's
+ // input in the request. Hence, returning internal error
+ // back to the client.
+ messages::internalError(asyncResp->res);
return;
}
- // Other Dbus errors such as:
- // xyz.openbmc_project.Common.Error.InvalidArgument &
- // org.freedesktop.DBus.Error.InvalidArgs are all related to
- // the dbus call that is made here in the bmcweb
- // implementation and has nothing to do with the client's
- // input in the request. Hence, returning internal error
- // back to the client.
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
- createDumpTaskCallback(std::move(payload), asyncResp, objPath);
- },
+ BMCWEB_LOG_DEBUG("Dump Created. Path: {}", objPath.str);
+ createDumpTaskCallback(std::move(payload), asyncResp, objPath);
+ },
"xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
"xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
}
@@ -1227,21 +1069,20 @@ inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
{
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("clearDump resp_handler got error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
"xyz.openbmc_project.Dump.Manager", getDumpPath(dumpType),
"xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
}
-inline void
- parseCrashdumpParameters(const dbus::utility::DBusPropertiesMap& params,
- std::string& filename, std::string& timestamp,
- std::string& logfile)
+inline void parseCrashdumpParameters(
+ const dbus::utility::DBusPropertiesMap& params, std::string& filename,
+ std::string& timestamp, std::string& logfile)
{
const std::string* filenamePtr = nullptr;
const std::string* timestampPtr = nullptr;
@@ -1279,189 +1120,192 @@ inline void requestRoutesSystemLogServiceCollection(App& app)
*/
BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
.privileges(redfish::privileges::getLogServiceCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogServiceCollection.LogServiceCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of LogServices for this Computer System";
- nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
- logServiceArray = nlohmann::json::array();
- nlohmann::json::object_t eventLog;
- eventLog["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- logServiceArray.emplace_back(std::move(eventLog));
- if constexpr (BMCWEB_REDFISH_DUMP_LOG)
- {
- nlohmann::json::object_t dumpLog;
- dumpLog["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/Dump",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- logServiceArray.emplace_back(std::move(dumpLog));
- }
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- if constexpr (BMCWEB_REDFISH_CPU_LOG)
- {
- nlohmann::json::object_t crashdump;
- crashdump["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogServiceCollection.LogServiceCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices",
BMCWEB_REDFISH_SYSTEM_URI_NAME);
- logServiceArray.emplace_back(std::move(crashdump));
- }
-
- if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
- {
- nlohmann::json::object_t hostlogger;
- hostlogger["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
+ asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of LogServices for this Computer System";
+ nlohmann::json& logServiceArray =
+ asyncResp->res.jsonValue["Members"];
+ logServiceArray = nlohmann::json::array();
+ nlohmann::json::object_t eventLog;
+ eventLog["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
BMCWEB_REDFISH_SYSTEM_URI_NAME);
- logServiceArray.emplace_back(std::move(hostlogger));
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArray.size();
-
- constexpr std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.State.Boot.PostCode"};
- dbus::utility::getSubTreePaths(
- "/", 0, interfaces,
- [asyncResp](const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse&
- subtreePath) {
- if (ec)
+ logServiceArray.emplace_back(std::move(eventLog));
+ if constexpr (BMCWEB_REDFISH_DUMP_LOG)
{
- BMCWEB_LOG_ERROR("{}", ec);
- return;
+ nlohmann::json::object_t dumpLog;
+ dumpLog["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/Dump",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ logServiceArray.emplace_back(std::move(dumpLog));
}
- for (const auto& pathStr : subtreePath)
+ if constexpr (BMCWEB_REDFISH_CPU_LOG)
{
- if (pathStr.find("PostCode") != std::string::npos)
- {
- nlohmann::json& logServiceArrayLocal =
- asyncResp->res.jsonValue["Members"];
- nlohmann::json::object_t member;
- member["@odata.id"] = std::format(
- "/redfish/v1/Systems/{}/LogServices/PostCodes",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
-
- logServiceArrayLocal.emplace_back(std::move(member));
+ nlohmann::json::object_t crashdump;
+ crashdump["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ logServiceArray.emplace_back(std::move(crashdump));
+ }
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArrayLocal.size();
- return;
- }
+ if constexpr (BMCWEB_REDFISH_HOST_LOGGER)
+ {
+ nlohmann::json::object_t hostlogger;
+ hostlogger["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ logServiceArray.emplace_back(std::move(hostlogger));
}
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArray.size();
+
+ constexpr std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.State.Boot.PostCode"};
+ dbus::utility::getSubTreePaths(
+ "/", 0, interfaces,
+ [asyncResp](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse&
+ subtreePath) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("{}", ec);
+ return;
+ }
+
+ for (const auto& pathStr : subtreePath)
+ {
+ if (pathStr.find("PostCode") != std::string::npos)
+ {
+ nlohmann::json& logServiceArrayLocal =
+ asyncResp->res.jsonValue["Members"];
+ nlohmann::json::object_t member;
+ member["@odata.id"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/PostCodes",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+
+ logServiceArrayLocal.emplace_back(
+ std::move(member));
+
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArrayLocal.size();
+ return;
+ }
+ }
+ });
});
- });
}
inline void requestRoutesEventLogService(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/")
.privileges(redfish::privileges::getLogService)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Event Log Service";
- asyncResp->res.jsonValue["Description"] = "System Event Log Service";
- asyncResp->res.jsonValue["Id"] = "EventLog";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
-
- std::pair<std::string, std::string> redfishDateTimeOffset =
- redfish::time_utils::getDateTimeOffsetNow();
-
- asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
- asyncResp->res.jsonValue["DateTimeLocalOffset"] =
- redfishDateTimeOffset.second;
-
- asyncResp->res.jsonValue["Entries"]["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"]
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/EventLog",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Event Log Service";
+ asyncResp->res.jsonValue["Description"] =
+ "System Event Log Service";
+ asyncResp->res.jsonValue["Id"] = "EventLog";
+ asyncResp->res.jsonValue["OverWritePolicy"] =
+ log_service::OverWritePolicy::WrapsWhenFull;
+
+ std::pair<std::string, std::string> redfishDateTimeOffset =
+ redfish::time_utils::getDateTimeOffsetNow();
- = std::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+ redfishDateTimeOffset.second;
+
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
BMCWEB_REDFISH_SYSTEM_URI_NAME);
- });
+ asyncResp->res
+ .jsonValue["Actions"]["#LogService.ClearLog"]["target"]
+
+ = std::format(
+ "/redfish/v1/Systems/{}/LogServices/EventLog/Actions/LogService.ClearLog",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ });
}
-inline void requestRoutesJournalEventLogClear(App& app)
+inline void handleSystemsLogServicesEventLogActionsClearPost(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
{
- BMCWEB_ROUTE(
- app,
- "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
- .privileges({{"ConfigureComponents"}})
- .methods(boost::beast::http::verb::post)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- // Clear the EventLog by deleting the log files
- std::vector<std::filesystem::path> redfishLogFiles;
- if (getRedfishLogFiles(redfishLogFiles))
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ // Clear the EventLog by deleting the log files
+ std::vector<std::filesystem::path> redfishLogFiles;
+ if (getRedfishLogFiles(redfishLogFiles))
+ {
+ for (const std::filesystem::path& file : redfishLogFiles)
{
- for (const std::filesystem::path& file : redfishLogFiles)
- {
- std::error_code ec;
- std::filesystem::remove(file, ec);
- }
+ std::error_code ec;
+ std::filesystem::remove(file, ec);
}
+ }
- // Reload rsyslog so it knows to start new log files
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec) {
+ // Reload rsyslog so it knows to start new log files
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec) {
if (ec)
{
BMCWEB_LOG_ERROR("Failed to reload rsyslog: {}", ec);
@@ -1471,10 +1315,19 @@ inline void requestRoutesJournalEventLogClear(App& app)
messages::success(asyncResp->res);
},
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
- "replace");
- });
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service",
+ "replace");
+}
+
+inline void requestRoutesJournalEventLogClear(App& app)
+{
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/LogService.ClearLog/")
+ .privileges({{"ConfigureComponents"}})
+ .methods(boost::beast::http::verb::post)(std::bind_front(
+ handleSystemsLogServicesEventLogActionsClearPost, std::ref(app)));
}
enum class LogParseError
@@ -1484,10 +1337,9 @@ enum class LogParseError
messageIdNotInRegistry,
};
-static LogParseError
- fillEventLogEntryJson(const std::string& logEntryID,
- const std::string& logEntry,
- nlohmann::json::object_t& logEntryJson)
+static LogParseError fillEventLogEntryJson(
+ const std::string& logEntryID, const std::string& logEntry,
+ nlohmann::json::object_t& logEntryJson)
{
// The redfish log format is "<Timestamp> <MessageId>,<MessageArgs>"
// First get the Timestamp
@@ -1529,8 +1381,8 @@ static LogParseError
logEntryFields.end());
messageArgs.resize(message->numberOfArgs);
- std::string msg = redfish::registries::fillMessageArgs(messageArgs,
- message->message);
+ std::string msg =
+ redfish::registries::fillMessageArgs(messageArgs, message->message);
if (msg.empty())
{
return LogParseError::parseFailed;
@@ -1562,194 +1414,318 @@ static LogParseError
return LogParseError::success;
}
-inline void requestRoutesJournalEventLogEntryCollection(App& app)
+inline void fillEventLogLogEntryFromPropertyMap(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const dbus::utility::DBusPropertiesMap& resp,
+ nlohmann::json& objectToFillOut)
{
- BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
- .privileges(redfish::privileges::getLogEntryCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- query_param::QueryCapabilities capabilities = {
- .canDelegateTop = true,
- .canDelegateSkip = true,
- };
- query_param::Query delegatedQuery;
- if (!redfish::setUpRedfishRouteWithDelegation(
- app, req, asyncResp, delegatedQuery, capabilities))
+ std::optional<DbusEventLogEntry> optEntry =
+ fillDbusEventLogEntryFromPropertyMap(resp);
+
+ if (!optEntry.has_value())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ DbusEventLogEntry entry = optEntry.value();
+
+ objectToFillOut["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+ objectToFillOut["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
+ objectToFillOut["Name"] = "System Event Log Entry";
+ objectToFillOut["Id"] = std::to_string(entry.Id);
+ objectToFillOut["Message"] = entry.Message;
+ objectToFillOut["Resolved"] = entry.Resolved;
+ std::optional<bool> notifyAction =
+ getProviderNotifyAction(entry.ServiceProviderNotify);
+ if (notifyAction)
+ {
+ objectToFillOut["ServiceProviderNotified"] = *notifyAction;
+ }
+ if ((entry.Resolution != nullptr) && !entry.Resolution->empty())
+ {
+ objectToFillOut["Resolution"] = *entry.Resolution;
+ }
+ objectToFillOut["EntryType"] = "Event";
+ objectToFillOut["Severity"] =
+ translateSeverityDbusToRedfish(entry.Severity);
+ objectToFillOut["Created"] =
+ redfish::time_utils::getDateTimeUintMs(entry.Timestamp);
+ objectToFillOut["Modified"] =
+ redfish::time_utils::getDateTimeUintMs(entry.UpdateTimestamp);
+ if (entry.Path != nullptr)
+ {
+ objectToFillOut["AdditionalDataURI"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}/attachment",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(entry.Id));
+ }
+}
+
+inline void afterLogEntriesGetManagedObjects(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec,
+ const dbus::utility::ManagedObjectType& resp)
+{
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR("getLogEntriesIfaceData resp_handler got error {}",
+ ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json::array_t entriesArray;
+ for (const auto& objectPath : resp)
+ {
+ dbus::utility::DBusPropertiesMap propsFlattened;
+ auto isEntry =
+ std::ranges::find_if(objectPath.second, [](const auto& object) {
+ return object.first == "xyz.openbmc_project.Logging.Entry";
+ });
+ if (isEntry == objectPath.second.end())
{
- return;
+ continue;
}
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ for (const auto& interfaceMap : objectPath.second)
{
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
+ for (const auto& propertyMap : interfaceMap.second)
+ {
+ propsFlattened.emplace_back(propertyMap.first,
+ propertyMap.second);
+ }
}
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ fillEventLogLogEntryFromPropertyMap(asyncResp, propsFlattened,
+ entriesArray.emplace_back());
+ }
+
+ std::ranges::sort(entriesArray, [](const nlohmann::json& left,
+ const nlohmann::json& right) {
+ return (left["Id"] <= right["Id"]);
+ });
+ asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();
+ asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
+}
+
+inline void handleSystemsLogServiceEventLogLogEntryCollection(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ query_param::QueryCapabilities capabilities = {
+ .canDelegateTop = true,
+ .canDelegateSkip = true,
+ };
+ query_param::Query delegatedQuery;
+ if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
+ delegatedQuery, capabilities))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
+ size_t skip = delegatedQuery.skip.value_or(0);
+
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
+
+ nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
+ // Go through the log files and create a unique ID for each
+ // entry
+ std::vector<std::filesystem::path> redfishLogFiles;
+ getRedfishLogFiles(redfishLogFiles);
+ uint64_t entryCount = 0;
+ std::string logEntry;
+
+ // Oldest logs are in the last file, so start there and loop
+ // backwards
+ for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
+ {
+ std::ifstream logStream(*it);
+ if (!logStream.is_open())
{
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
+ continue;
}
- size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
- size_t skip = delegatedQuery.skip.value_or(0);
-
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- // Go through the log files and create a unique ID for each
- // entry
- std::vector<std::filesystem::path> redfishLogFiles;
- getRedfishLogFiles(redfishLogFiles);
- uint64_t entryCount = 0;
- std::string logEntry;
-
- // Oldest logs are in the last file, so start there and loop
- // backwards
- for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend();
- it++)
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ while (std::getline(logStream, logEntry))
{
- std::ifstream logStream(*it);
- if (!logStream.is_open())
+ std::string idStr;
+ if (!getUniqueEntryID(logEntry, idStr, firstEntry))
{
continue;
}
+ firstEntry = false;
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- while (std::getline(logStream, logEntry))
+ nlohmann::json::object_t bmcLogEntry;
+ LogParseError status =
+ fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
+ if (status == LogParseError::messageIdNotInRegistry)
{
- std::string idStr;
- if (!getUniqueEntryID(logEntry, idStr, firstEntry))
- {
- continue;
- }
- firstEntry = false;
-
- nlohmann::json::object_t bmcLogEntry;
- LogParseError status = fillEventLogEntryJson(idStr, logEntry,
- bmcLogEntry);
- if (status == LogParseError::messageIdNotInRegistry)
- {
- continue;
- }
- if (status != LogParseError::success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- entryCount++;
- // Handle paging using skip (number of entries to skip from the
- // start) and top (number of entries to display)
- if (entryCount <= skip || entryCount > skip + top)
- {
- continue;
- }
+ continue;
+ }
+ if (status != LogParseError::success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- logEntryArray.emplace_back(std::move(bmcLogEntry));
+ entryCount++;
+ // Handle paging using skip (number of entries to skip from the
+ // start) and top (number of entries to display)
+ if (entryCount <= skip || entryCount > skip + top)
+ {
+ continue;
}
+
+ logEntryArray.emplace_back(std::move(bmcLogEntry));
}
- asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
- if (skip + top < entryCount)
- {
- asyncResp->res
- .jsonValue["Members@odata.nextLink"] = boost::urls::format(
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
+ if (skip + top < entryCount)
+ {
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ boost::urls::format(
"/redfish/v1/Systems/{}/LogServices/EventLog/Entries?$skip={}",
BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(skip + top));
- }
- });
+ }
}
-inline void requestRoutesJournalEventLogEntry(App& app)
+inline void requestRoutesJournalEventLogEntryCollection(App& app)
{
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/")
+ .privileges(redfish::privileges::getLogEntryCollection)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServiceEventLogLogEntryCollection, std::ref(app)));
+}
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+inline void handleSystemsLogServiceEventLogEntriesGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& param)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- const std::string& targetID = param;
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ const std::string& targetID = param;
- // Go through the log files and check the unique ID for each
- // entry to find the target entry
- std::vector<std::filesystem::path> redfishLogFiles;
- getRedfishLogFiles(redfishLogFiles);
- std::string logEntry;
+ // Go through the log files and check the unique ID for each
+ // entry to find the target entry
+ std::vector<std::filesystem::path> redfishLogFiles;
+ getRedfishLogFiles(redfishLogFiles);
+ std::string logEntry;
- // Oldest logs are in the last file, so start there and loop
- // backwards
- for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend();
- it++)
+ // Oldest logs are in the last file, so start there and loop
+ // backwards
+ for (auto it = redfishLogFiles.rbegin(); it < redfishLogFiles.rend(); it++)
+ {
+ std::ifstream logStream(*it);
+ if (!logStream.is_open())
{
- std::ifstream logStream(*it);
- if (!logStream.is_open())
+ continue;
+ }
+
+ // Reset the unique ID on the first entry
+ bool firstEntry = true;
+ while (std::getline(logStream, logEntry))
+ {
+ std::string idStr;
+ if (!getUniqueEntryID(logEntry, idStr, firstEntry))
{
continue;
}
+ firstEntry = false;
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- while (std::getline(logStream, logEntry))
+ if (idStr == targetID)
{
- std::string idStr;
- if (!getUniqueEntryID(logEntry, idStr, firstEntry))
- {
- continue;
- }
- firstEntry = false;
-
- if (idStr == targetID)
+ nlohmann::json::object_t bmcLogEntry;
+ LogParseError status =
+ fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
+ if (status != LogParseError::success)
{
- nlohmann::json::object_t bmcLogEntry;
- LogParseError status =
- fillEventLogEntryJson(idStr, logEntry, bmcLogEntry);
- if (status != LogParseError::success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue.update(bmcLogEntry);
+ messages::internalError(asyncResp->res);
return;
}
+ asyncResp->res.jsonValue.update(bmcLogEntry);
+ return;
}
}
- // Requested ID was not found
- messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
- });
+ }
+ // Requested ID was not found
+ messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
+}
+
+inline void requestRoutesJournalEventLogEntry(App& app)
+{
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServiceEventLogEntriesGet, std::ref(app)));
+}
+
+inline void dBusEventLogEntryCollection(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of System Event Log Entries";
+
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
+ dbus::utility::getManagedObjects(
+ "xyz.openbmc_project.Logging", path,
+ [asyncResp](const boost::system::error_code& ec,
+ const dbus::utility::ManagedObjectType& resp) {
+ afterLogEntriesGetManagedObjects(asyncResp, ec, resp);
+ });
}
inline void requestRoutesDBusEventLogEntryCollection(App& app)
@@ -1760,234 +1736,39 @@ inline void requestRoutesDBusEventLogEntryCollection(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/EventLog/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "System Event Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of System Event Log Entries";
-
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- sdbusplus::message::object_path path("/xyz/openbmc_project/logging");
- dbus::utility::getManagedObjects(
- "xyz.openbmc_project.Logging", path,
- [asyncResp](const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& resp) {
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR(
- "getLogEntriesIfaceData resp_handler got error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json::array_t entriesArray;
- for (const auto& objectPath : resp)
- {
- const uint32_t* id = nullptr;
- const uint64_t* timestamp = nullptr;
- const uint64_t* updateTimestamp = nullptr;
- const std::string* severity = nullptr;
- const std::string* message = nullptr;
- const std::string* filePath = nullptr;
- const std::string* resolution = nullptr;
- bool resolved = false;
- const std::string* notify = nullptr;
-
- for (const auto& interfaceMap : objectPath.second)
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- if (interfaceMap.first ==
- "xyz.openbmc_project.Logging.Entry")
- {
- for (const auto& propertyMap : interfaceMap.second)
- {
- if (propertyMap.first == "Id")
- {
- id = std::get_if<uint32_t>(&propertyMap.second);
- }
- else if (propertyMap.first == "Timestamp")
- {
- timestamp =
- std::get_if<uint64_t>(&propertyMap.second);
- }
- else if (propertyMap.first == "UpdateTimestamp")
- {
- updateTimestamp =
- std::get_if<uint64_t>(&propertyMap.second);
- }
- else if (propertyMap.first == "Severity")
- {
- severity = std::get_if<std::string>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Resolution")
- {
- resolution = std::get_if<std::string>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Message")
- {
- message = std::get_if<std::string>(
- &propertyMap.second);
- }
- else if (propertyMap.first == "Resolved")
- {
- const bool* resolveptr =
- std::get_if<bool>(&propertyMap.second);
- if (resolveptr == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- resolved = *resolveptr;
- }
- else if (propertyMap.first ==
- "ServiceProviderNotify")
- {
- notify = std::get_if<std::string>(
- &propertyMap.second);
- if (notify == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
- }
- if (id == nullptr || message == nullptr ||
- severity == nullptr)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- }
- else if (interfaceMap.first ==
- "xyz.openbmc_project.Common.FilePath")
- {
- for (const auto& propertyMap : interfaceMap.second)
- {
- if (propertyMap.first == "Path")
- {
- filePath = std::get_if<std::string>(
- &propertyMap.second);
- }
- }
- }
- }
- // Object path without the
- // xyz.openbmc_project.Logging.Entry interface, ignore
- // and continue.
- if (id == nullptr || message == nullptr ||
- severity == nullptr || timestamp == nullptr ||
- updateTimestamp == nullptr)
- {
- continue;
- }
- nlohmann::json& thisEntry = entriesArray.emplace_back();
- thisEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
- thisEntry["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(*id));
- thisEntry["Name"] = "System Event Log Entry";
- thisEntry["Id"] = std::to_string(*id);
- thisEntry["Message"] = *message;
- thisEntry["Resolved"] = resolved;
- if ((resolution != nullptr) && (!(*resolution).empty()))
- {
- thisEntry["Resolution"] = *resolution;
+ return;
}
- std::optional<bool> notifyAction =
- getProviderNotifyAction(*notify);
- if (notifyAction)
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
{
- thisEntry["ServiceProviderNotified"] = *notifyAction;
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
}
- thisEntry["EntryType"] = "Event";
- thisEntry["Severity"] =
- translateSeverityDbusToRedfish(*severity);
- thisEntry["Created"] =
- redfish::time_utils::getDateTimeUintMs(*timestamp);
- thisEntry["Modified"] =
- redfish::time_utils::getDateTimeUintMs(*updateTimestamp);
- if (filePath != nullptr)
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
{
- thisEntry["AdditionalDataURI"] =
- std::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/",
- BMCWEB_REDFISH_SYSTEM_URI_NAME) +
- std::to_string(*id) + "/attachment";
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
}
- }
- std::ranges::sort(entriesArray, [](const nlohmann::json& left,
- const nlohmann::json& right) {
- return (left["Id"] <= right["Id"]);
+ dBusEventLogEntryCollection(asyncResp);
});
- asyncResp->res.jsonValue["Members@odata.count"] =
- entriesArray.size();
- asyncResp->res.jsonValue["Members"] = std::move(entriesArray);
- });
- });
}
-inline void requestRoutesDBusEventLogEntry(App& app)
+inline void dBusEventLogEntryGet(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
{
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- std::string entryID = param;
- dbus::utility::escapePathForDbus(entryID);
+ dbus::utility::escapePathForDbus(entryID);
- // DBus implementation of EventLog/Entries
- // Make call to Logging Service to find all log entry objects
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID, "",
- [asyncResp, entryID](const boost::system::error_code& ec,
- const dbus::utility::DBusPropertiesMap& resp) {
+ // DBus implementation of EventLog/Entries
+ // Make call to Logging Service to find all log entry objects
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID, "",
+ [asyncResp, entryID](const boost::system::error_code& ec,
+ const dbus::utility::DBusPropertiesMap& resp) {
if (ec.value() == EBADR)
{
messages::resourceNotFound(asyncResp->res, "EventLogEntry",
@@ -2001,73 +1782,96 @@ inline void requestRoutesDBusEventLogEntry(App& app)
messages::internalError(asyncResp->res);
return;
}
- const uint32_t* id = nullptr;
- const uint64_t* timestamp = nullptr;
- const uint64_t* updateTimestamp = nullptr;
- const std::string* severity = nullptr;
- const std::string* message = nullptr;
- const std::string* filePath = nullptr;
- const std::string* resolution = nullptr;
- bool resolved = false;
- const std::string* notify = nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), resp, "Id", id, "Timestamp",
- timestamp, "UpdateTimestamp", updateTimestamp, "Severity",
- severity, "Message", message, "Resolved", resolved,
- "Resolution", resolution, "Path", filePath,
- "ServiceProviderNotify", notify);
-
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- if (id == nullptr || message == nullptr || severity == nullptr ||
- timestamp == nullptr || updateTimestamp == nullptr ||
- notify == nullptr)
+ fillEventLogLogEntryFromPropertyMap(asyncResp, resp,
+ asyncResp->res.jsonValue);
+ });
+}
+
+inline void
+ dBusEventLogEntryPatch(const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryId)
+{
+ std::optional<bool> resolved;
+
+ if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", resolved))
+ {
+ return;
+ }
+ BMCWEB_LOG_DEBUG("Set Resolved");
+
+ setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryId,
+ "xyz.openbmc_project.Logging.Entry", "Resolved",
+ resolved.value_or(false));
+}
+
+inline void dBusEventLogEntryDelete(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string entryID)
+{
+ BMCWEB_LOG_DEBUG("Do delete single event entries.");
+
+ dbus::utility::escapePathForDbus(entryID);
+
+ // Process response from Logging service.
+ auto respHandler = [asyncResp,
+ entryID](const boost::system::error_code& ec) {
+ BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
+ if (ec)
+ {
+ if (ec.value() == EBADR)
{
- messages::internalError(asyncResp->res);
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
return;
}
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR(
+ "EventLogEntry (DBus) doDelete respHandler got error {}", ec);
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntry.v1_9_0.LogEntry";
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, std::to_string(*id));
- asyncResp->res.jsonValue["Name"] = "System Event Log Entry";
- asyncResp->res.jsonValue["Id"] = std::to_string(*id);
- asyncResp->res.jsonValue["Message"] = *message;
- asyncResp->res.jsonValue["Resolved"] = resolved;
- std::optional<bool> notifyAction = getProviderNotifyAction(*notify);
- if (notifyAction)
- {
- asyncResp->res.jsonValue["ServiceProviderNotified"] =
- *notifyAction;
- }
- if ((resolution != nullptr) && (!(*resolution).empty()))
- {
- asyncResp->res.jsonValue["Resolution"] = *resolution;
- }
- asyncResp->res.jsonValue["EntryType"] = "Event";
- asyncResp->res.jsonValue["Severity"] =
- translateSeverityDbusToRedfish(*severity);
- asyncResp->res.jsonValue["Created"] =
- redfish::time_utils::getDateTimeUintMs(*timestamp);
- asyncResp->res.jsonValue["Modified"] =
- redfish::time_utils::getDateTimeUintMs(*updateTimestamp);
- if (filePath != nullptr)
- {
- asyncResp->res.jsonValue["AdditionalDataURI"] =
- std::format(
- "/redfish/v1/Systems/{}/LogServices/EventLog/Entries/",
- BMCWEB_REDFISH_SYSTEM_URI_NAME) +
- std::to_string(*id) + "/attachment";
- }
- });
- });
+ asyncResp->res.result(boost::beast::http::status::ok);
+ };
+
+ // Make call to Logging service to request Delete Log
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging/entry/" + entryID,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+}
+
+inline void requestRoutesDBusEventLogEntry(App& app)
+{
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& entryId) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ dBusEventLogEntryGet(asyncResp, entryId);
+ });
BMCWEB_ROUTE(
app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
@@ -2076,37 +1880,26 @@ inline void requestRoutesDBusEventLogEntry(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName, const std::string& entryId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- std::optional<bool> resolved;
-
- if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved",
- resolved))
- {
- return;
- }
- BMCWEB_LOG_DEBUG("Set Resolved");
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- setDbusProperty(asyncResp, "Resolved", "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryId,
- "xyz.openbmc_project.Logging.Entry", "Resolved",
- *resolved);
- });
+ dBusEventLogEntryPatch(req, asyncResp, entryId);
+ });
BMCWEB_ROUTE(
app, "/redfish/v1/Systems/<str>/LogServices/EventLog/Entries/<str>/")
@@ -2116,59 +1909,25 @@ inline void requestRoutesDBusEventLogEntry(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName, const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- BMCWEB_LOG_DEBUG("Do delete single event entries.");
-
- std::string entryID = param;
-
- dbus::utility::escapePathForDbus(entryID);
-
- // Process response from Logging service.
- auto respHandler = [asyncResp,
- entryID](const boost::system::error_code& ec) {
- BMCWEB_LOG_DEBUG("EventLogEntry (DBus) doDelete callback: Done");
- if (ec)
- {
- if (ec.value() == EBADR)
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- messages::resourceNotFound(asyncResp->res, "LogEntry",
- entryID);
return;
}
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR(
- "EventLogEntry (DBus) doDelete respHandler got error {}",
- ec);
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::ok);
- };
-
- // Make call to Logging service to request Delete Log
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging/entry/" + entryID,
- "xyz.openbmc_project.Object.Delete", "Delete");
- });
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ dBusEventLogEntryDelete(asyncResp, param);
+ });
}
constexpr const char* hostLoggerFolderPath = "/var/log/console";
@@ -2231,226 +1990,6 @@ inline bool getHostLoggerEntries(
return true;
}
-inline void fillHostLoggerEntryJson(std::string_view logEntryID,
- std::string_view msg,
- nlohmann::json::object_t& logEntryJson)
-{
- // Fill in the log entry with the gathered data.
- logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
- logEntryJson["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
- logEntryJson["Name"] = "Host Logger Entry";
- logEntryJson["Id"] = logEntryID;
- logEntryJson["Message"] = msg;
- logEntryJson["EntryType"] = "Oem";
- logEntryJson["Severity"] = "OK";
- logEntryJson["OemRecordFormat"] = "Host Logger Entry";
-}
-
-inline void requestRoutesSystemHostLogger(App& app)
-{
- BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/")
- .privileges(redfish::privileges::getLogService)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Host Logger Service";
- asyncResp->res.jsonValue["Description"] = "Host Logger Service";
- asyncResp->res.jsonValue["Id"] = "HostLogger";
- asyncResp->res.jsonValue["Entries"]["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- });
-}
-
-inline void requestRoutesSystemHostLoggerCollection(App& app)
-{
- BMCWEB_ROUTE(app,
- "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- query_param::QueryCapabilities capabilities = {
- .canDelegateTop = true,
- .canDelegateSkip = true,
- };
- query_param::Query delegatedQuery;
- if (!redfish::setUpRedfishRouteWithDelegation(
- app, req, asyncResp, delegatedQuery, capabilities))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["Name"] = "HostLogger Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of HostLogger Entries";
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- std::vector<std::filesystem::path> hostLoggerFiles;
- if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
- {
- BMCWEB_LOG_DEBUG("Failed to get host log file path");
- return;
- }
- // If we weren't provided top and skip limits, use the defaults.
- size_t skip = delegatedQuery.skip.value_or(0);
- size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
- size_t logCount = 0;
- // This vector only store the entries we want to expose that
- // control by skip and top.
- std::vector<std::string> logEntries;
- if (!getHostLoggerEntries(hostLoggerFiles, skip, top, logEntries,
- logCount))
- {
- messages::internalError(asyncResp->res);
- return;
- }
- // If vector is empty, that means skip value larger than total
- // log count
- if (logEntries.empty())
- {
- asyncResp->res.jsonValue["Members@odata.count"] = logCount;
- return;
- }
- if (!logEntries.empty())
- {
- for (size_t i = 0; i < logEntries.size(); i++)
- {
- nlohmann::json::object_t hostLogEntry;
- fillHostLoggerEntryJson(std::to_string(skip + i), logEntries[i],
- hostLogEntry);
- logEntryArray.emplace_back(std::move(hostLogEntry));
- }
-
- asyncResp->res.jsonValue["Members@odata.count"] = logCount;
- if (skip + top < logCount)
- {
- asyncResp->res.jsonValue["Members@odata.nextLink"] =
- std::format(
- "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries?$skip=",
- BMCWEB_REDFISH_SYSTEM_URI_NAME) +
- std::to_string(skip + top);
- }
- }
- });
-}
-
-inline void requestRoutesSystemHostLoggerLogEntry(App& app)
-{
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/<str>/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- std::string_view targetID = param;
-
- uint64_t idInt = 0;
-
- auto [ptr, ec] = std::from_chars(targetID.begin(), targetID.end(),
- idInt);
- if (ec != std::errc{} || ptr != targetID.end())
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", param);
- return;
- }
-
- std::vector<std::filesystem::path> hostLoggerFiles;
- if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
- {
- BMCWEB_LOG_DEBUG("Failed to get host log file path");
- return;
- }
-
- size_t logCount = 0;
- size_t top = 1;
- std::vector<std::string> logEntries;
- // We can get specific entry by skip and top. For example, if we
- // want to get nth entry, we can set skip = n-1 and top = 1 to
- // get that entry
- if (!getHostLoggerEntries(hostLoggerFiles, idInt, top, logEntries,
- logCount))
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (!logEntries.empty())
- {
- nlohmann::json::object_t hostLogEntry;
- fillHostLoggerEntryJson(targetID, logEntries[0], hostLogEntry);
- asyncResp->res.jsonValue.update(hostLogEntry);
- return;
- }
-
- // Requested ID was not found
- messages::resourceNotFound(asyncResp->res, "LogEntry", param);
- });
-}
-
inline void handleBMCLogServicesCollectionGet(
crow::App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -2499,42 +2038,43 @@ inline void handleBMCLogServicesCollectionGet(
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse&
subTreePaths) {
- if (ec)
- {
- BMCWEB_LOG_ERROR(
- "handleBMCLogServicesCollectionGet respHandler got error {}",
- ec);
- // Assume that getting an error simply means there are no dump
- // LogServices. Return without adding any error response.
- return;
- }
-
- nlohmann::json& logServiceArrayLocal =
- asyncResp->res.jsonValue["Members"];
-
- for (const std::string& path : subTreePaths)
- {
- if (path == "/xyz/openbmc_project/dump/bmc")
+ if (ec)
{
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/Dump",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- logServiceArrayLocal.emplace_back(std::move(member));
+ BMCWEB_LOG_ERROR(
+ "handleBMCLogServicesCollectionGet respHandler got error {}",
+ ec);
+ // Assume that getting an error simply means there are no
+ // dump LogServices. Return without adding any error
+ // response.
+ return;
}
- else if (path == "/xyz/openbmc_project/dump/faultlog")
+
+ nlohmann::json& logServiceArrayLocal =
+ asyncResp->res.jsonValue["Members"];
+
+ for (const std::string& path : subTreePaths)
{
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/FaultLog",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- logServiceArrayLocal.emplace_back(std::move(member));
+ if (path == "/xyz/openbmc_project/dump/bmc")
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/Dump",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ logServiceArrayLocal.emplace_back(std::move(member));
+ }
+ else if (path == "/xyz/openbmc_project/dump/faultlog")
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/FaultLog",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ logServiceArrayLocal.emplace_back(std::move(member));
+ }
}
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- logServiceArrayLocal.size();
- });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logServiceArrayLocal.size();
+ });
}
}
@@ -2546,318 +2086,34 @@ inline void requestRoutesBMCLogServiceCollection(App& app)
std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
}
-inline void requestRoutesBMCJournalLogService(App& app)
-{
- BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Journal/")
- .privileges(redfish::privileges::getLogService)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "Open BMC Journal Log Service";
- asyncResp->res.jsonValue["Description"] = "BMC Journal Log Service";
- asyncResp->res.jsonValue["Id"] = "Journal";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
-
- std::pair<std::string, std::string> redfishDateTimeOffset =
- redfish::time_utils::getDateTimeOffsetNow();
- asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
- asyncResp->res.jsonValue["DateTimeLocalOffset"] =
- redfishDateTimeOffset.second;
-
- asyncResp->res.jsonValue["Entries"]["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/Journal/Entries",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- });
-}
-
-static int
- fillBMCJournalLogEntryJson(const std::string& bmcJournalLogEntryID,
- sd_journal* journal,
- nlohmann::json::object_t& bmcJournalLogEntryJson)
-{
- // Get the Log Entry contents
- int ret = 0;
-
- std::string message;
- std::string_view syslogID;
- ret = getJournalMetadata(journal, "SYSLOG_IDENTIFIER", syslogID);
- if (ret < 0)
- {
- BMCWEB_LOG_DEBUG("Failed to read SYSLOG_IDENTIFIER field: {}",
- strerror(-ret));
- }
- if (!syslogID.empty())
- {
- message += std::string(syslogID) + ": ";
- }
-
- std::string_view msg;
- ret = getJournalMetadata(journal, "MESSAGE", msg);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR("Failed to read MESSAGE field: {}", strerror(-ret));
- return 1;
- }
- message += std::string(msg);
-
- // Get the severity from the PRIORITY field
- long int severity = 8; // Default to an invalid priority
- ret = getJournalMetadata(journal, "PRIORITY", 10, severity);
- if (ret < 0)
- {
- BMCWEB_LOG_DEBUG("Failed to read PRIORITY field: {}", strerror(-ret));
- }
-
- // Get the Created time from the timestamp
- std::string entryTimeStr;
- if (!getEntryTimestamp(journal, entryTimeStr))
- {
- return 1;
- }
-
- // Fill in the log entry with the gathered data
- bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
- bmcJournalLogEntryJson["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/Journal/Entries/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, bmcJournalLogEntryID);
- bmcJournalLogEntryJson["Name"] = "BMC Journal Entry";
- bmcJournalLogEntryJson["Id"] = bmcJournalLogEntryID;
- bmcJournalLogEntryJson["Message"] = std::move(message);
- bmcJournalLogEntryJson["EntryType"] = "Oem";
- log_entry::EventSeverity severityEnum = log_entry::EventSeverity::OK;
- if (severity <= 2)
- {
- severityEnum = log_entry::EventSeverity::Critical;
- }
- else if (severity <= 4)
- {
- severityEnum = log_entry::EventSeverity::Warning;
- }
-
- bmcJournalLogEntryJson["Severity"] = severityEnum;
- bmcJournalLogEntryJson["OemRecordFormat"] = "BMC Journal Entry";
- bmcJournalLogEntryJson["Created"] = std::move(entryTimeStr);
- return 0;
-}
-
-inline void requestRoutesBMCJournalLogEntryCollection(App& app)
-{
- BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Journal/Entries/")
- .privileges(redfish::privileges::getLogEntryCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& managerId) {
- query_param::QueryCapabilities capabilities = {
- .canDelegateTop = true,
- .canDelegateSkip = true,
- };
- query_param::Query delegatedQuery;
- if (!redfish::setUpRedfishRouteWithDelegation(
- app, req, asyncResp, delegatedQuery, capabilities))
- {
- return;
- }
-
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
-
- size_t skip = delegatedQuery.skip.value_or(0);
- size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
-
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/Journal/Entries",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of BMC Journal Entries";
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
-
- // Go through the journal and use the timestamp to create a
- // unique ID for each entry
- sd_journal* journalTmp = nullptr;
- int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR("failed to open journal: {}", strerror(-ret));
- messages::internalError(asyncResp->res);
- return;
- }
- std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
- journalTmp, sd_journal_close);
- journalTmp = nullptr;
- uint64_t entryCount = 0;
- // Reset the unique ID on the first entry
- bool firstEntry = true;
- SD_JOURNAL_FOREACH(journal.get())
- {
- entryCount++;
- // Handle paging using skip (number of entries to skip from
- // the start) and top (number of entries to display)
- if (entryCount <= skip || entryCount > skip + top)
- {
- continue;
- }
-
- std::string idStr;
- if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
- {
- continue;
- }
- firstEntry = false;
-
- nlohmann::json::object_t bmcJournalLogEntry;
- if (fillBMCJournalLogEntryJson(idStr, journal.get(),
- bmcJournalLogEntry) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- logEntryArray.emplace_back(std::move(bmcJournalLogEntry));
- }
- asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
- if (skip + top < entryCount)
- {
- asyncResp->res
- .jsonValue["Members@odata.nextLink"] = boost::urls::format(
- "/redfish/v1/Managers/{}/LogServices/Journal/Entries?$skip={}",
- BMCWEB_REDFISH_MANAGER_URI_NAME, std::to_string(skip + top));
- }
- });
-}
-
-inline void requestRoutesBMCJournalLogEntry(App& app)
-{
- BMCWEB_ROUTE(
- app, "/redfish/v1/Managers/<str>/LogServices/Journal/Entries/<str>/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& managerId, const std::string& entryID) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
-
- // Convert the unique ID back to a timestamp to find the entry
- sd_id128_t bootID{};
- uint64_t ts = 0;
- uint64_t index = 0;
- if (!getTimestampFromID(asyncResp, entryID, bootID, ts, index))
- {
- return;
- }
-
- sd_journal* journalTmp = nullptr;
- int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR("failed to open journal: {}", strerror(-ret));
- messages::internalError(asyncResp->res);
- return;
- }
- std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
- journalTmp, sd_journal_close);
- journalTmp = nullptr;
- // Go to the timestamp in the log and move to the entry at the
- // index tracking the unique ID
- std::string idStr;
- bool firstEntry = true;
- ret = sd_journal_seek_monotonic_usec(journal.get(), bootID, ts);
- if (ret < 0)
- {
- BMCWEB_LOG_ERROR("failed to seek to an entry in journal{}",
- strerror(-ret));
- messages::internalError(asyncResp->res);
- return;
- }
- for (uint64_t i = 0; i <= index; i++)
- {
- sd_journal_next(journal.get());
- if (!getUniqueEntryID(journal.get(), idStr, firstEntry))
- {
- messages::internalError(asyncResp->res);
- return;
- }
- firstEntry = false;
- }
- // Confirm that the entry ID matches what was requested
- if (idStr != entryID)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
- return;
- }
-
- nlohmann::json::object_t bmcJournalLogEntry;
- if (fillBMCJournalLogEntryJson(entryID, journal.get(),
- bmcJournalLogEntry) != 0)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue.update(bmcJournalLogEntry);
- });
-}
-
inline void
getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& dumpType)
{
std::string dumpPath;
- std::string overWritePolicy;
+ log_service::OverWritePolicy overWritePolicy =
+ log_service::OverWritePolicy::Invalid;
bool collectDiagnosticDataSupported = false;
if (dumpType == "BMC")
{
dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/Dump",
BMCWEB_REDFISH_MANAGER_URI_NAME);
- overWritePolicy = "WrapsWhenFull";
+ overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
collectDiagnosticDataSupported = true;
}
else if (dumpType == "FaultLog")
{
dumpPath = std::format("/redfish/v1/Managers/{}/LogServices/FaultLog",
BMCWEB_REDFISH_MANAGER_URI_NAME);
- overWritePolicy = "Unknown";
+ overWritePolicy = log_service::OverWritePolicy::Unknown;
collectDiagnosticDataSupported = false;
}
else if (dumpType == "System")
{
dumpPath = std::format("/redfish/v1/Systems/{}/LogServices/Dump",
BMCWEB_REDFISH_SYSTEM_URI_NAME);
- overWritePolicy = "WrapsWhenFull";
+ overWritePolicy = log_service::OverWritePolicy::WrapsWhenFull;
collectDiagnosticDataSupported = true;
}
else
@@ -2873,7 +2129,7 @@ inline void
asyncResp->res.jsonValue["Name"] = "Dump LogService";
asyncResp->res.jsonValue["Description"] = dumpType + " Dump LogService";
asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
- asyncResp->res.jsonValue["OverWritePolicy"] = std::move(overWritePolicy);
+ asyncResp->res.jsonValue["OverWritePolicy"] = overWritePolicy;
std::pair<std::string, std::string> redfishDateTimeOffset =
redfish::time_utils::getDateTimeOffsetNow();
@@ -2896,25 +2152,26 @@ inline void
[asyncResp, dumpType, dumpPath](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}", ec);
- // Assume that getting an error simply means there are no dump
- // LogServices. Return without adding any error response.
- return;
- }
- std::string dbusDumpPath = getDumpPath(dumpType);
- for (const std::string& path : subTreePaths)
- {
- if (path == dbusDumpPath)
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("getDumpServiceInfo respHandler got error {}",
+ ec);
+ // Assume that getting an error simply means there are no dump
+ // LogServices. Return without adding any error response.
+ return;
+ }
+ std::string dbusDumpPath = getDumpPath(dumpType);
+ for (const std::string& path : subTreePaths)
{
- asyncResp->res
- .jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
- dumpPath + "/Actions/LogService.ClearLog";
- break;
+ if (path == dbusDumpPath)
+ {
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
+ ["target"] =
+ dumpPath + "/Actions/LogService.ClearLog";
+ break;
+ }
}
- }
- });
+ });
}
inline void handleLogServicesDumpServiceGet(
@@ -3360,59 +2617,62 @@ inline void requestRoutesCrashdumpService(App& app)
// This is incorrect, should be:
//.privileges(redfish::privileges::getLogService)
.privileges({{"ConfigureManager"}})
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- // Copy over the static data to include the entries added by
- // SubRoute
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
- asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
- asyncResp->res.jsonValue["Id"] = "Crashdump";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
-
- std::pair<std::string, std::string> redfishDateTimeOffset =
- redfish::time_utils::getDateTimeOffsetNow();
- asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
- asyncResp->res.jsonValue["DateTimeLocalOffset"] =
- redfishDateTimeOffset.second;
-
- asyncResp->res.jsonValue["Entries"]["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
- ["target"] = std::format(
- "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
- ["target"] = std::format(
- "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- });
+ // Copy over the static data to include the entries added by
+ // SubRoute
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/Crashdump",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Open BMC Oem Crashdump Service";
+ asyncResp->res.jsonValue["Description"] = "Oem Crashdump Service";
+ asyncResp->res.jsonValue["Id"] = "Crashdump";
+ asyncResp->res.jsonValue["OverWritePolicy"] =
+ log_service::OverWritePolicy::WrapsWhenFull;
+ asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
+
+ std::pair<std::string, std::string> redfishDateTimeOffset =
+ redfish::time_utils::getDateTimeOffsetNow();
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+ redfishDateTimeOffset.second;
+
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
+ ["target"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.ClearLog",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res
+ .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
+ ["target"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ });
}
void inline requestRoutesCrashdumpClear(App& app)
@@ -3427,38 +2687,39 @@ void inline requestRoutesCrashdumpClear(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec,
- const std::string&) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- messages::success(asyncResp->res);
- },
- crashdumpObject, crashdumpPath, deleteAllInterface, "DeleteAll");
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec,
+ const std::string&) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ crashdumpObject, crashdumpPath, deleteAllInterface,
+ "DeleteAll");
+ });
}
-static void
+inline void
logCrashdumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& logID, nlohmann::json& logEntryJson)
{
@@ -3466,63 +2727,65 @@ static void
[asyncResp, logID,
&logEntryJson](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& params) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
- if (ec.value() ==
- boost::system::linux_error::bad_request_descriptor)
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
+ if (ec.value() ==
+ boost::system::linux_error::bad_request_descriptor)
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry",
+ logID);
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+
+ std::string timestamp{};
+ std::string filename{};
+ std::string logfile{};
+ parseCrashdumpParameters(params, filename, timestamp, logfile);
+
+ if (filename.empty() || timestamp.empty())
{
messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
+ return;
+ }
+
+ std::string crashdumpURI =
+ std::format(
+ "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME) +
+ logID + "/" + filename;
+ nlohmann::json::object_t logEntry;
+ logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+ logEntry["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
+ logEntry["Name"] = "CPU Crashdump";
+ logEntry["Id"] = logID;
+ logEntry["EntryType"] = log_entry::LogEntryType::Oem;
+ logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
+ logEntry["DiagnosticDataType"] = "OEM";
+ logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
+ logEntry["Created"] = std::move(timestamp);
+
+ // If logEntryJson references an array of LogEntry resources
+ // ('Members' list), then push this as a new entry, otherwise set it
+ // directly
+ if (logEntryJson.is_array())
+ {
+ logEntryJson.push_back(logEntry);
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logEntryJson.size();
}
else
{
- messages::internalError(asyncResp->res);
+ logEntryJson.update(logEntry);
}
- return;
- }
-
- std::string timestamp{};
- std::string filename{};
- std::string logfile{};
- parseCrashdumpParameters(params, filename, timestamp, logfile);
-
- if (filename.empty() || timestamp.empty())
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
- return;
- }
-
- std::string crashdumpURI =
- std::format("/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/",
- BMCWEB_REDFISH_SYSTEM_URI_NAME) +
- logID + "/" + filename;
- nlohmann::json::object_t logEntry;
- logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
- logEntry["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, logID);
- logEntry["Name"] = "CPU Crashdump";
- logEntry["Id"] = logID;
- logEntry["EntryType"] = "Oem";
- logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
- logEntry["DiagnosticDataType"] = "OEM";
- logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
- logEntry["Created"] = std::move(timestamp);
-
- // If logEntryJson references an array of LogEntry resources
- // ('Members' list), then push this as a new entry, otherwise set it
- // directly
- if (logEntryJson.is_array())
- {
- logEntryJson.push_back(logEntry);
- asyncResp->res.jsonValue["Members@odata.count"] =
- logEntryJson.size();
- }
- else
- {
- logEntryJson.update(logEntry);
- }
- };
+ };
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, crashdumpObject,
crashdumpPath + std::string("/") + logID, crashdumpInterface,
@@ -3541,71 +2804,74 @@ inline void requestRoutesCrashdumpEntryCollection(App& app)
// This is incorrect, should be.
//.privileges(redfish::privileges::postLogEntryCollection)
.privileges({{"ConfigureComponents"}})
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- constexpr std::array<std::string_view, 1> interfaces = {
- crashdumpInterface};
- dbus::utility::getSubTreePaths(
- "/", 0, interfaces,
- [asyncResp](const boost::system::error_code& ec,
- const std::vector<std::string>& resp) {
- if (ec)
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- if (ec.value() !=
- boost::system::errc::no_such_file_or_directory)
- {
- BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
- ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
+ return;
}
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] = std::format(
- "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of Crashdump Entries";
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- for (const std::string& path : resp)
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
{
- const sdbusplus::message::object_path objPath(path);
- // Get the log ID
- std::string logID = objPath.filename();
- if (logID.empty())
- {
- continue;
- }
- // Add the log entry to the array
- logCrashdumpEntry(asyncResp, logID,
- asyncResp->res.jsonValue["Members"]);
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
}
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ constexpr std::array<std::string_view, 1> interfaces = {
+ crashdumpInterface};
+ dbus::utility::getSubTreePaths(
+ "/", 0, interfaces,
+ [asyncResp](const boost::system::error_code& ec,
+ const std::vector<std::string>& resp) {
+ if (ec)
+ {
+ if (ec.value() !=
+ boost::system::errc::no_such_file_or_directory)
+ {
+ BMCWEB_LOG_DEBUG("failed to get entries ec: {}",
+ ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/Crashdump/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["Name"] =
+ "Open BMC Crashdump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Crashdump Entries";
+ asyncResp->res.jsonValue["Members"] =
+ nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ for (const std::string& path : resp)
+ {
+ const sdbusplus::message::object_path objPath(path);
+ // Get the log ID
+ std::string logID = objPath.filename();
+ if (logID.empty())
+ {
+ continue;
+ }
+ // Add the log entry to the array
+ logCrashdumpEntry(asyncResp, logID,
+ asyncResp->res.jsonValue["Members"]);
+ }
+ });
});
- });
}
inline void requestRoutesCrashdumpEntry(App& app)
@@ -3622,26 +2888,26 @@ inline void requestRoutesCrashdumpEntry(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName, const std::string& param) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- const std::string& logID = param;
- logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ const std::string& logID = param;
+ logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue);
+ });
}
inline void requestRoutesCrashdumpFile(App& app)
@@ -3657,73 +2923,80 @@ inline void requestRoutesCrashdumpFile(App& app)
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName, const std::string& logID,
const std::string& fileName) {
- // Do not call getRedfishRoute here since the crashdump file is not a
- // Redfish resource.
+ // Do not call getRedfishRoute here since the crashdump file is
+ // not a Redfish resource.
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- auto getStoredLogCallback =
- [asyncResp, logID, fileName, url(boost::urls::url(req.url()))](
- const boost::system::error_code& ec,
- const std::vector<
- std::pair<std::string, dbus::utility::DbusVariantType>>&
- resp) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("failed to get log ec: {}", ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
+ auto getStoredLogCallback =
+ [asyncResp, logID, fileName,
+ url(boost::urls::url(req.url()))](
+ const boost::system::error_code& ec,
+ const std::vector<std::pair<
+ std::string, dbus::utility::DbusVariantType>>&
+ resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("failed to get log ec: {}",
+ ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
- std::string dbusFilename{};
- std::string dbusTimestamp{};
- std::string dbusFilepath{};
+ std::string dbusFilename{};
+ std::string dbusTimestamp{};
+ std::string dbusFilepath{};
- parseCrashdumpParameters(resp, dbusFilename, dbusTimestamp,
- dbusFilepath);
+ parseCrashdumpParameters(resp, dbusFilename,
+ dbusTimestamp, dbusFilepath);
- if (dbusFilename.empty() || dbusTimestamp.empty() ||
- dbusFilepath.empty())
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
- return;
- }
+ if (dbusFilename.empty() || dbusTimestamp.empty() ||
+ dbusFilepath.empty())
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "LogEntry", logID);
+ return;
+ }
- // Verify the file name parameter is correct
- if (fileName != dbusFilename)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
- return;
- }
+ // Verify the file name parameter is correct
+ if (fileName != dbusFilename)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "LogEntry", logID);
+ return;
+ }
- if (!asyncResp->res.openFile(dbusFilepath))
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
- return;
- }
+ if (asyncResp->res.openFile(dbusFilepath) !=
+ crow::OpenCode::Success)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "LogEntry", logID);
+ return;
+ }
- // Configure this to be a file download when accessed
- // from a browser
- asyncResp->res.addHeader(
- boost::beast::http::field::content_disposition, "attachment");
- };
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, crashdumpObject,
- crashdumpPath + std::string("/") + logID, crashdumpInterface,
- std::move(getStoredLogCallback));
- });
+ // Configure this to be a file download when accessed
+ // from a browser
+ asyncResp->res.addHeader(
+ boost::beast::http::field::content_disposition,
+ "attachment");
+ };
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, crashdumpObject,
+ crashdumpPath + std::string("/") + logID,
+ crashdumpInterface, std::move(getStoredLogCallback));
+ });
}
enum class OEMDiagnosticType
@@ -3761,122 +3034,158 @@ inline void requestRoutesCrashdumpCollect(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- std::string diagnosticDataType;
- std::string oemDiagnosticDataType;
- if (!redfish::json_util::readJsonAction(
- req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
- "OEMDiagnosticDataType", oemDiagnosticDataType))
- {
- return;
- }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- if (diagnosticDataType != "OEM")
- {
- BMCWEB_LOG_ERROR(
- "Only OEM DiagnosticDataType supported for Crashdump");
- messages::actionParameterValueFormatError(
- asyncResp->res, diagnosticDataType, "DiagnosticDataType",
- "CollectDiagnosticData");
- return;
- }
+ std::string diagnosticDataType;
+ std::string oemDiagnosticDataType;
+ if (!redfish::json_util::readJsonAction(
+ req, asyncResp->res, "DiagnosticDataType",
+ diagnosticDataType, "OEMDiagnosticDataType",
+ oemDiagnosticDataType))
+ {
+ return;
+ }
- OEMDiagnosticType oemDiagType =
- getOEMDiagnosticType(oemDiagnosticDataType);
+ if (diagnosticDataType != "OEM")
+ {
+ BMCWEB_LOG_ERROR(
+ "Only OEM DiagnosticDataType supported for Crashdump");
+ messages::actionParameterValueFormatError(
+ asyncResp->res, diagnosticDataType,
+ "DiagnosticDataType", "CollectDiagnosticData");
+ return;
+ }
- std::string iface;
- std::string method;
- std::string taskMatchStr;
- if (oemDiagType == OEMDiagnosticType::onDemand)
- {
- iface = crashdumpOnDemandInterface;
- method = "GenerateOnDemandLog";
- taskMatchStr = "type='signal',"
- "interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged',"
- "arg0namespace='com.intel.crashdump'";
- }
- else if (oemDiagType == OEMDiagnosticType::telemetry)
- {
- iface = crashdumpTelemetryInterface;
- method = "GenerateTelemetryLog";
- taskMatchStr = "type='signal',"
- "interface='org.freedesktop.DBus.Properties',"
- "member='PropertiesChanged',"
- "arg0namespace='com.intel.crashdump'";
- }
- else
- {
- BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
- oemDiagnosticDataType);
- messages::actionParameterValueFormatError(
- asyncResp->res, oemDiagnosticDataType, "OEMDiagnosticDataType",
- "CollectDiagnosticData");
- return;
- }
+ OEMDiagnosticType oemDiagType =
+ getOEMDiagnosticType(oemDiagnosticDataType);
- auto collectCrashdumpCallback =
- [asyncResp, payload(task::Payload(req)),
- taskMatchStr](const boost::system::error_code& ec,
- const std::string&) mutable {
- if (ec)
- {
- if (ec.value() == boost::system::errc::operation_not_supported)
+ std::string iface;
+ std::string method;
+ std::string taskMatchStr;
+ if (oemDiagType == OEMDiagnosticType::onDemand)
{
- messages::resourceInStandby(asyncResp->res);
+ iface = crashdumpOnDemandInterface;
+ method = "GenerateOnDemandLog";
+ taskMatchStr =
+ "type='signal',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',"
+ "arg0namespace='com.intel.crashdump'";
}
- else if (ec.value() ==
- boost::system::errc::device_or_resource_busy)
+ else if (oemDiagType == OEMDiagnosticType::telemetry)
{
- messages::serviceTemporarilyUnavailable(asyncResp->res,
- "60");
+ iface = crashdumpTelemetryInterface;
+ method = "GenerateTelemetryLog";
+ taskMatchStr =
+ "type='signal',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',"
+ "arg0namespace='com.intel.crashdump'";
}
else
{
- messages::internalError(asyncResp->res);
- }
- return;
- }
- std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
- [](const boost::system::error_code& ec2, sdbusplus::message_t&,
- const std::shared_ptr<task::TaskData>& taskData) {
- if (!ec2)
- {
- taskData->messages.emplace_back(messages::taskCompletedOK(
- std::to_string(taskData->index)));
- taskData->state = "Completed";
+ BMCWEB_LOG_ERROR("Unsupported OEMDiagnosticDataType: {}",
+ oemDiagnosticDataType);
+ messages::actionParameterValueFormatError(
+ asyncResp->res, oemDiagnosticDataType,
+ "OEMDiagnosticDataType", "CollectDiagnosticData");
+ return;
}
- return task::completed;
- },
- taskMatchStr);
- task->startTimer(std::chrono::minutes(5));
- task->populateResp(asyncResp->res);
- task->payload.emplace(std::move(payload));
- };
+ auto collectCrashdumpCallback =
+ [asyncResp, payload(task::Payload(req)),
+ taskMatchStr](const boost::system::error_code& ec,
+ const std::string&) mutable {
+ if (ec)
+ {
+ if (ec.value() ==
+ boost::system::errc::operation_not_supported)
+ {
+ messages::resourceInStandby(asyncResp->res);
+ }
+ else if (ec.value() == boost::system::errc::
+ device_or_resource_busy)
+ {
+ messages::serviceTemporarilyUnavailable(
+ asyncResp->res, "60");
+ }
+ else
+ {
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+ std::shared_ptr<task::TaskData> task =
+ task::TaskData::createTask(
+ [](const boost::system::error_code& ec2,
+ sdbusplus::message_t&,
+ const std::shared_ptr<task::TaskData>&
+ taskData) {
+ if (!ec2)
+ {
+ taskData->messages.emplace_back(
+ messages::taskCompletedOK(
+ std::to_string(
+ taskData->index)));
+ taskData->state = "Completed";
+ }
+ return task::completed;
+ },
+ taskMatchStr);
+
+ task->startTimer(std::chrono::minutes(5));
+ task->populateResp(asyncResp->res);
+ task->payload.emplace(std::move(payload));
+ };
+
+ crow::connections::systemBus->async_method_call(
+ std::move(collectCrashdumpCallback), crashdumpObject,
+ crashdumpPath, iface, method);
+ });
+}
- crow::connections::systemBus->async_method_call(
- std::move(collectCrashdumpCallback), crashdumpObject, crashdumpPath,
- iface, method);
- });
+inline void dBusLogServiceActionsClear(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ BMCWEB_LOG_DEBUG("Do delete all entries.");
+
+ // Process response from Logging service.
+ auto respHandler = [asyncResp](const boost::system::error_code& ec) {
+ BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ };
+
+ // Make call to Logging service to request Clear Log
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.Logging",
+ "/xyz/openbmc_project/logging",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
}
/**
@@ -3898,638 +3207,25 @@ inline void requestRoutesDBusLogServiceActionsClear(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- BMCWEB_LOG_DEBUG("Do delete all entries.");
-
- // Process response from Logging service.
- auto respHandler = [asyncResp](const boost::system::error_code& ec) {
- BMCWEB_LOG_DEBUG("doClearLog resp_handler callback: Done");
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR("doClearLog resp_handler got error {}", ec);
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::no_content);
- };
-
- // Make call to Logging service to request Clear Log
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
- });
-}
-
-/****************************************************
- * Redfish PostCode interfaces
- * using DBUS interface: getPostCodesTS
- ******************************************************/
-inline void requestRoutesPostCodesLogService(App& app)
-{
- BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/")
- .privileges(redfish::privileges::getLogService)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/PostCodes",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogService.v1_2_0.LogService";
- asyncResp->res.jsonValue["Name"] = "POST Code Log Service";
- asyncResp->res.jsonValue["Description"] = "POST Code Log Service";
- asyncResp->res.jsonValue["Id"] = "PostCodes";
- asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
- asyncResp->res.jsonValue["Entries"]["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/PostCodes/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
-
- std::pair<std::string, std::string> redfishDateTimeOffset =
- redfish::time_utils::getDateTimeOffsetNow();
- asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
- asyncResp->res.jsonValue["DateTimeLocalOffset"] =
- redfishDateTimeOffset.second;
-
- asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]
- ["target"] = std::format(
- "/redfish/v1/Systems/{}/LogServices/PostCodes/Actions/LogService.ClearLog",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- });
-}
-
-inline void requestRoutesPostCodesClear(App& app)
-{
- BMCWEB_ROUTE(
- app,
- "/redfish/v1/Systems/<str>/LogServices/PostCodes/Actions/LogService.ClearLog/")
- // The following privilege is incorrect; It should be ConfigureManager
- //.privileges(redfish::privileges::postLogService)
- .privileges({{"ConfigureComponents"}})
- .methods(boost::beast::http::verb::post)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- BMCWEB_LOG_DEBUG("Do delete all postcodes entries.");
-
- // Make call to post-code service to request clear all
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- // TODO Handle for specific error code
- BMCWEB_LOG_ERROR("doClearPostCodes resp_handler got error {}",
- ec);
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- messages::internalError(asyncResp->res);
- return;
- }
- messages::success(asyncResp->res);
- },
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
- });
-}
-
-/**
- * @brief Parse post code ID and get the current value and index value
- * eg: postCodeID=B1-2, currentValue=1, index=2
- *
- * @param[in] postCodeID Post Code ID
- * @param[out] currentValue Current value
- * @param[out] index Index value
- *
- * @return bool true if the parsing is successful, false the parsing fails
- */
-inline bool parsePostCode(std::string_view postCodeID, uint64_t& currentValue,
- uint16_t& index)
-{
- std::vector<std::string> split;
- bmcweb::split(split, postCodeID, '-');
- if (split.size() != 2)
- {
- return false;
- }
- std::string_view postCodeNumber = split[0];
- if (postCodeNumber.size() < 2)
- {
- return false;
- }
- if (postCodeNumber[0] != 'B')
- {
- return false;
- }
- postCodeNumber.remove_prefix(1);
- auto [ptrIndex, ecIndex] = std::from_chars(postCodeNumber.begin(),
- postCodeNumber.end(), index);
- if (ptrIndex != postCodeNumber.end() || ecIndex != std::errc())
- {
- return false;
- }
-
- std::string_view postCodeIndex = split[1];
-
- auto [ptrValue, ecValue] = std::from_chars(
- postCodeIndex.begin(), postCodeIndex.end(), currentValue);
-
- return ptrValue == postCodeIndex.end() && ecValue == std::errc();
-}
-
-static bool fillPostCodeEntry(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const boost::container::flat_map<
- uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& postcode,
- const uint16_t bootIndex, const uint64_t codeIndex = 0,
- const uint64_t skip = 0, const uint64_t top = 0)
-{
- // Get the Message from the MessageRegistry
- const registries::Message* message =
- registries::getMessage("OpenBMC.0.2.BIOSPOSTCode");
- if (message == nullptr)
- {
- BMCWEB_LOG_ERROR("Couldn't find known message?");
- return false;
- }
- uint64_t currentCodeIndex = 0;
- uint64_t firstCodeTimeUs = 0;
- for (const std::pair<uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
- code : postcode)
- {
- currentCodeIndex++;
- std::string postcodeEntryID =
- "B" + std::to_string(bootIndex) + "-" +
- std::to_string(currentCodeIndex); // 1 based index in EntryID string
-
- uint64_t usecSinceEpoch = code.first;
- uint64_t usTimeOffset = 0;
-
- if (1 == currentCodeIndex)
- { // already incremented
- firstCodeTimeUs = code.first;
- }
- else
- {
- usTimeOffset = code.first - firstCodeTimeUs;
- }
-
- // skip if no specific codeIndex is specified and currentCodeIndex does
- // not fall between top and skip
- if ((codeIndex == 0) &&
- (currentCodeIndex <= skip || currentCodeIndex > top))
- {
- continue;
- }
-
- // skip if a specific codeIndex is specified and does not match the
- // currentIndex
- if ((codeIndex > 0) && (currentCodeIndex != codeIndex))
- {
- // This is done for simplicity. 1st entry is needed to calculate
- // time offset. To improve efficiency, one can get to the entry
- // directly (possibly with flatmap's nth method)
- continue;
- }
-
- // currentCodeIndex is within top and skip or equal to specified code
- // index
-
- // Get the Created time from the timestamp
- std::string entryTimeStr;
- entryTimeStr = redfish::time_utils::getDateTimeUintUs(usecSinceEpoch);
-
- // assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
- std::ostringstream hexCode;
- hexCode << "0x" << std::setfill('0') << std::setw(2) << std::hex
- << std::get<0>(code.second);
- std::ostringstream timeOffsetStr;
- // Set Fixed -Point Notation
- timeOffsetStr << std::fixed;
- // Set precision to 4 digits
- timeOffsetStr << std::setprecision(4);
- // Add double to stream
- timeOffsetStr << static_cast<double>(usTimeOffset) / 1000 / 1000;
-
- std::string bootIndexStr = std::to_string(bootIndex);
- std::string timeOffsetString = timeOffsetStr.str();
- std::string hexCodeStr = hexCode.str();
-
- std::array<std::string_view, 3> messageArgs = {
- bootIndexStr, timeOffsetString, hexCodeStr};
-
- std::string msg =
- redfish::registries::fillMessageArgs(messageArgs, message->message);
- if (msg.empty())
- {
- messages::internalError(asyncResp->res);
- return false;
- }
-
- // Get Severity template from message registry
- std::string severity;
- if (message != nullptr)
- {
- severity = message->messageSeverity;
- }
-
- // Format entry
- nlohmann::json::object_t bmcLogEntry;
- bmcLogEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
- bmcLogEntry["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, postcodeEntryID);
- bmcLogEntry["Name"] = "POST Code Log Entry";
- bmcLogEntry["Id"] = postcodeEntryID;
- bmcLogEntry["Message"] = std::move(msg);
- bmcLogEntry["MessageId"] = "OpenBMC.0.2.BIOSPOSTCode";
- bmcLogEntry["MessageArgs"] = messageArgs;
- bmcLogEntry["EntryType"] = "Event";
- bmcLogEntry["Severity"] = std::move(severity);
- bmcLogEntry["Created"] = entryTimeStr;
- if (!std::get<std::vector<uint8_t>>(code.second).empty())
- {
- bmcLogEntry["AdditionalDataURI"] =
- std::format(
- "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries/",
- BMCWEB_REDFISH_SYSTEM_URI_NAME) +
- postcodeEntryID + "/attachment";
- }
-
- // codeIndex is only specified when querying single entry, return only
- // that entry in this case
- if (codeIndex != 0)
- {
- asyncResp->res.jsonValue.update(bmcLogEntry);
- return true;
- }
-
- nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
- logEntryArray.emplace_back(std::move(bmcLogEntry));
- }
-
- // Return value is always false when querying multiple entries
- return false;
-}
-
-static void
- getPostCodeForEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& entryId)
-{
- uint16_t bootIndex = 0;
- uint64_t codeIndex = 0;
- if (!parsePostCode(entryId, codeIndex, bootIndex))
- {
- // Requested ID was not found
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
- return;
- }
-
- if (bootIndex == 0 || codeIndex == 0)
- {
- // 0 is an invalid index
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
- return;
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, entryId, bootIndex,
- codeIndex](const boost::system::error_code& ec,
- const boost::container::flat_map<
- uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
- postcode) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS POST CODE PostCode response error");
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (postcode.empty())
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
- return;
- }
-
- if (!fillPostCodeEntry(asyncResp, postcode, bootIndex, codeIndex))
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
- return;
- }
- },
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp",
- bootIndex);
-}
-
-static void
- getPostCodeForBoot(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const uint16_t bootIndex, const uint16_t bootCount,
- const uint64_t entryCount, size_t skip, size_t top)
-{
- crow::connections::systemBus->async_method_call(
- [asyncResp, bootIndex, bootCount, entryCount, skip,
- top](const boost::system::error_code& ec,
- const boost::container::flat_map<
- uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
- postcode) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS POST CODE PostCode response error");
- messages::internalError(asyncResp->res);
- return;
- }
-
- uint64_t endCount = entryCount;
- if (!postcode.empty())
- {
- endCount = entryCount + postcode.size();
- if (skip < endCount && (top + skip) > entryCount)
- {
- uint64_t thisBootSkip = std::max(static_cast<uint64_t>(skip),
- entryCount) -
- entryCount;
- uint64_t thisBootTop =
- std::min(static_cast<uint64_t>(top + skip), endCount) -
- entryCount;
-
- fillPostCodeEntry(asyncResp, postcode, bootIndex, 0,
- thisBootSkip, thisBootTop);
- }
- asyncResp->res.jsonValue["Members@odata.count"] = endCount;
- }
-
- // continue to previous bootIndex
- if (bootIndex < bootCount)
- {
- getPostCodeForBoot(asyncResp, static_cast<uint16_t>(bootIndex + 1),
- bootCount, endCount, skip, top);
- }
- else if (skip + top < endCount)
- {
- asyncResp->res.jsonValue["Members@odata.nextLink"] =
- std::format(
- "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries?$skip=",
- BMCWEB_REDFISH_SYSTEM_URI_NAME) +
- std::to_string(skip + top);
- }
- },
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp",
- bootIndex);
-}
-
-static void
- getCurrentBootNumber(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- size_t skip, size_t top)
-{
- uint64_t entryCount = 0;
- sdbusplus::asio::getProperty<uint16_t>(
- *crow::connections::systemBus,
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount",
- [asyncResp, entryCount, skip, top](const boost::system::error_code& ec,
- const uint16_t bootCount) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- getPostCodeForBoot(asyncResp, 1, bootCount, entryCount, skip, top);
- });
-}
-
-inline void requestRoutesPostCodesEntryCollection(App& app)
-{
- BMCWEB_ROUTE(app,
- "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/")
- .privileges(redfish::privileges::getLogEntryCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- query_param::QueryCapabilities capabilities = {
- .canDelegateTop = true,
- .canDelegateSkip = true,
- };
- query_param::Query delegatedQuery;
- if (!redfish::setUpRedfishRouteWithDelegation(
- app, req, asyncResp, delegatedQuery, capabilities))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/LogServices/PostCodes/Entries",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of POST Code Log Entries";
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
- size_t skip = delegatedQuery.skip.value_or(0);
- size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
- getCurrentBootNumber(asyncResp, skip, top);
- });
-}
-
-inline void requestRoutesPostCodesEntryAdditionalData(App& app)
-{
- BMCWEB_ROUTE(
- app,
- "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/attachment/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& postCodeID) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (!http_helpers::isContentTypeAllowed(
- req.getHeaderValue("Accept"),
- http_helpers::ContentType::OctetStream, true))
- {
- asyncResp->res.result(boost::beast::http::status::bad_request);
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- uint64_t currentValue = 0;
- uint16_t index = 0;
- if (!parsePostCode(postCodeID, currentValue, index))
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry", postCodeID);
- return;
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, postCodeID, currentValue](
- const boost::system::error_code& ec,
- const std::vector<std::tuple<uint64_t, std::vector<uint8_t>>>&
- postcodes) {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "LogEntry",
- postCodeID);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- size_t value = static_cast<size_t>(currentValue) - 1;
- if (value == std::string::npos || postcodes.size() < currentValue)
- {
- BMCWEB_LOG_WARNING("Wrong currentValue value");
- messages::resourceNotFound(asyncResp->res, "LogEntry",
- postCodeID);
- return;
- }
-
- const auto& [tID, c] = postcodes[value];
- if (c.empty())
- {
- BMCWEB_LOG_WARNING("No found post code data");
- messages::resourceNotFound(asyncResp->res, "LogEntry",
- postCodeID);
- return;
- }
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- const char* d = reinterpret_cast<const char*>(c.data());
- std::string_view strData(d, c.size());
-
- asyncResp->res.addHeader(boost::beast::http::field::content_type,
- "application/octet-stream");
- asyncResp->res.addHeader(
- boost::beast::http::field::content_transfer_encoding, "Base64");
- asyncResp->res.write(crow::utility::base64encode(strData));
- },
- "xyz.openbmc_project.State.Boot.PostCode0",
- "/xyz/openbmc_project/State/Boot/PostCode0",
- "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodes", index);
- });
-}
-
-inline void requestRoutesPostCodesEntry(App& app)
-{
- BMCWEB_ROUTE(
- app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/")
- .privileges(redfish::privileges::getLogEntry)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& targetID) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- getPostCodeForEntry(asyncResp, targetID);
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ dBusLogServiceActionsClear(asyncResp);
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/manager_diagnostic_data.hpp b/redfish-core/lib/manager_diagnostic_data.hpp
index 1856e1f9e6..1ca80fdd54 100644
--- a/redfish-core/lib/manager_diagnostic_data.hpp
+++ b/redfish-core/lib/manager_diagnostic_data.hpp
@@ -106,8 +106,8 @@ inline void
}
static constexpr double roundFactor = 10000; // 4 decimal places
- asyncResp->res.jsonValue[jPtr] = std::round(userCPU * roundFactor) /
- roundFactor;
+ asyncResp->res.jsonValue[jPtr] =
+ std::round(userCPU * roundFactor) / roundFactor;
}
inline void managerGetProcessorStatistics(
diff --git a/redfish-core/lib/manager_logservices_journal.hpp b/redfish-core/lib/manager_logservices_journal.hpp
new file mode 100644
index 0000000000..17fb95bfc5
--- /dev/null
+++ b/redfish-core/lib/manager_logservices_journal.hpp
@@ -0,0 +1,655 @@
+#pragma once
+
+#include "app.hpp"
+#include "error_messages.hpp"
+#include "generated/enums/log_entry.hpp"
+#include "query.hpp"
+#include "registries/base_message_registry.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/time_utils.hpp"
+
+#include <systemd/sd-journal.h>
+
+#include <boost/beast/http/verb.hpp>
+
+#include <array>
+#include <memory>
+#include <string>
+#include <string_view>
+
+namespace redfish
+{
+// Entry is formed like "BootID_timestamp" or "BootID_timestamp_index"
+inline bool
+ getTimestampFromID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ std::string_view entryIDStrView, sd_id128_t& bootID,
+ uint64_t& timestamp, uint64_t& index)
+{
+ // Convert the unique ID back to a bootID + timestamp to find the entry
+ auto underscore1Pos = entryIDStrView.find('_');
+ if (underscore1Pos == std::string_view::npos)
+ {
+ // EntryID has no bootID or timestamp
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
+ return false;
+ }
+
+ // EntryID has bootID + timestamp
+
+ // Convert entryIDViewString to BootID
+ // NOTE: bootID string which needs to be null-terminated for
+ // sd_id128_from_string()
+ std::string bootIDStr(entryIDStrView.substr(0, underscore1Pos));
+ if (sd_id128_from_string(bootIDStr.c_str(), &bootID) < 0)
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
+ return false;
+ }
+
+ // Get the timestamp from entryID
+ entryIDStrView.remove_prefix(underscore1Pos + 1);
+
+ auto [timestampEnd, tstampEc] = std::from_chars(
+ entryIDStrView.begin(), entryIDStrView.end(), timestamp);
+ if (tstampEc != std::errc())
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
+ return false;
+ }
+ entryIDStrView = std::string_view(
+ timestampEnd,
+ static_cast<size_t>(std::distance(timestampEnd, entryIDStrView.end())));
+ if (entryIDStrView.empty())
+ {
+ index = 0U;
+ return true;
+ }
+ // Timestamp might include optional index, if two events happened at the
+ // same "time".
+ if (entryIDStrView[0] != '_')
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
+ return false;
+ }
+ entryIDStrView.remove_prefix(1);
+ auto [ptr, indexEc] =
+ std::from_chars(entryIDStrView.begin(), entryIDStrView.end(), index);
+ if (indexEc != std::errc() || ptr != entryIDStrView.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
+ return false;
+ }
+ if (index <= 1)
+ {
+ // Indexes go directly from no postfix (handled above) to _2
+ // so if we ever see _0 or _1, it's incorrect
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryIDStrView);
+ return false;
+ }
+
+ // URI indexes are one based, journald is zero based
+ index -= 1;
+ return true;
+}
+
+inline std::string getUniqueEntryID(uint64_t index, uint64_t curTs,
+ sd_id128_t& curBootID)
+{
+ // make entryID as <bootID>_<timestamp>[_<index>]
+ std::array<char, SD_ID128_STRING_MAX> bootIDStr{};
+ sd_id128_to_string(curBootID, bootIDStr.data());
+ std::string postfix;
+ if (index > 0)
+ {
+ postfix = std::format("_{}", index + 1);
+ }
+ return std::format("{}_{}{}", bootIDStr.data(), curTs, postfix);
+}
+
+inline int getJournalMetadata(sd_journal* journal, std::string_view field,
+ std::string_view& contents)
+{
+ const char* data = nullptr;
+ size_t length = 0;
+ int ret = 0;
+ // Get the metadata from the requested field of the journal entry
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ const void** dataVoid = reinterpret_cast<const void**>(&data);
+
+ ret = sd_journal_get_data(journal, field.data(), dataVoid, &length);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ contents = std::string_view(data, length);
+ // Only use the content after the "=" character.
+ contents.remove_prefix(std::min(contents.find('=') + 1, contents.size()));
+ return ret;
+}
+
+inline int getJournalMetadataInt(sd_journal* journal, std::string_view field,
+ const int& base, long int& contents)
+{
+ int ret = 0;
+ std::string_view metadata;
+ // Get the metadata from the requested field of the journal entry
+ ret = getJournalMetadata(journal, field, metadata);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ contents = strtol(metadata.data(), nullptr, base);
+ return ret;
+}
+
+inline bool getEntryTimestamp(sd_journal* journal, std::string& entryTimestamp)
+{
+ int ret = 0;
+ uint64_t timestamp = 0;
+ ret = sd_journal_get_realtime_usec(journal, &timestamp);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}", strerror(-ret));
+ return false;
+ }
+ entryTimestamp = redfish::time_utils::getDateTimeUintUs(timestamp);
+ return true;
+}
+
+inline bool fillBMCJournalLogEntryJson(
+ const std::string& bmcJournalLogEntryID, sd_journal* journal,
+ nlohmann::json::object_t& bmcJournalLogEntryJson)
+{
+ // Get the Log Entry contents
+ std::string message;
+ std::string_view syslogID;
+ int ret = getJournalMetadata(journal, "SYSLOG_IDENTIFIER", syslogID);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_DEBUG("Failed to read SYSLOG_IDENTIFIER field: {}",
+ strerror(-ret));
+ }
+ if (!syslogID.empty())
+ {
+ message += std::string(syslogID) + ": ";
+ }
+
+ std::string_view msg;
+ ret = getJournalMetadata(journal, "MESSAGE", msg);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("Failed to read MESSAGE field: {}", strerror(-ret));
+ return false;
+ }
+ message += std::string(msg);
+
+ // Get the severity from the PRIORITY field
+ long int severity = 8; // Default to an invalid priority
+ ret = getJournalMetadataInt(journal, "PRIORITY", 10, severity);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_DEBUG("Failed to read PRIORITY field: {}", strerror(-ret));
+ }
+
+ // Get the Created time from the timestamp
+ std::string entryTimeStr;
+ if (!getEntryTimestamp(journal, entryTimeStr))
+ {
+ return false;
+ }
+
+ // Fill in the log entry with the gathered data
+ bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+ bmcJournalLogEntryJson["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/Journal/Entries/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, bmcJournalLogEntryID);
+ bmcJournalLogEntryJson["Name"] = "BMC Journal Entry";
+ bmcJournalLogEntryJson["Id"] = bmcJournalLogEntryID;
+ bmcJournalLogEntryJson["Message"] = std::move(message);
+ bmcJournalLogEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
+ log_entry::EventSeverity severityEnum = log_entry::EventSeverity::OK;
+ if (severity <= 2)
+ {
+ severityEnum = log_entry::EventSeverity::Critical;
+ }
+ else if (severity <= 4)
+ {
+ severityEnum = log_entry::EventSeverity::Warning;
+ }
+
+ bmcJournalLogEntryJson["Severity"] = severityEnum;
+ bmcJournalLogEntryJson["OemRecordFormat"] = "BMC Journal Entry";
+ bmcJournalLogEntryJson["Created"] = std::move(entryTimeStr);
+ return true;
+}
+
+inline void handleManagersLogServiceJournalGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& managerId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+ return;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}/LogServices/Journal",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "Open BMC Journal Log Service";
+ asyncResp->res.jsonValue["Description"] = "BMC Journal Log Service";
+ asyncResp->res.jsonValue["Id"] = "Journal";
+ asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
+
+ std::pair<std::string, std::string> redfishDateTimeOffset =
+ redfish::time_utils::getDateTimeOffsetNow();
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+ redfishDateTimeOffset.second;
+
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/Journal/Entries",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+}
+
+struct JournalReadState
+{
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal;
+ uint64_t index = 0;
+ sd_id128_t prevBootID{};
+ uint64_t prevTs = 0;
+};
+
+inline void readJournalEntries(
+ uint64_t topEntryCount, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ JournalReadState&& readState)
+{
+ nlohmann::json& logEntry = asyncResp->res.jsonValue["Members"];
+ nlohmann::json::array_t* logEntryArray =
+ logEntry.get_ptr<nlohmann::json::array_t*>();
+ if (logEntryArray == nullptr)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // The Journal APIs unfortunately do blocking calls to the filesystem, and
+ // can be somewhat expensive. Short of creating our own io_uring based
+ // implementation of sd-journal, which would be difficult, the best thing we
+ // can do is to only parse a certain number of entries at a time. The
+ // current chunk size is selected arbitrarily to ensure that we're not
+ // trying to process thousands of entries at the same time.
+ // The implementation will process the number of entries, then return
+ // control to the io_context to let other operations continue.
+ size_t segmentCountRemaining = 10;
+
+ // Reset the unique ID on the first entry
+ for (uint64_t entryCount = logEntryArray->size();
+ entryCount < topEntryCount; entryCount++)
+ {
+ if (segmentCountRemaining == 0)
+ {
+ boost::asio::post(crow::connections::systemBus->get_io_context(),
+ [asyncResp, topEntryCount,
+ readState = std::move(readState)]() mutable {
+ readJournalEntries(topEntryCount, asyncResp,
+ std::move(readState));
+ });
+ return;
+ }
+
+ // Get the entry timestamp
+ sd_id128_t curBootID{};
+ uint64_t curTs = 0;
+ int ret = sd_journal_get_monotonic_usec(readState.journal.get(), &curTs,
+ &curBootID);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}",
+ strerror(-ret));
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // If the timestamp isn't unique on the same boot, increment the index
+ bool sameBootIDs = sd_id128_equal(curBootID, readState.prevBootID) != 0;
+ if (sameBootIDs && (curTs == readState.prevTs))
+ {
+ readState.index++;
+ }
+ else
+ {
+ // Otherwise, reset it
+ readState.index = 0;
+ }
+
+ // Save the bootID
+ readState.prevBootID = curBootID;
+
+ // Save the timestamp
+ readState.prevTs = curTs;
+
+ std::string idStr = getUniqueEntryID(readState.index, curTs, curBootID);
+
+ nlohmann::json::object_t bmcJournalLogEntry;
+ if (!fillBMCJournalLogEntryJson(idStr, readState.journal.get(),
+ bmcJournalLogEntry))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ logEntryArray->emplace_back(std::move(bmcJournalLogEntry));
+
+ ret = sd_journal_next(readState.journal.get());
+ if (ret < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (ret == 0)
+ {
+ break;
+ }
+ segmentCountRemaining--;
+ }
+}
+
+inline void handleManagersJournalLogEntryCollectionGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& managerId)
+{
+ query_param::QueryCapabilities capabilities = {
+ .canDelegateTop = true,
+ .canDelegateSkip = true,
+ };
+ query_param::Query delegatedQuery;
+ if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
+ delegatedQuery, capabilities))
+ {
+ return;
+ }
+
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+ return;
+ }
+
+ size_t skip = delegatedQuery.skip.value_or(0);
+ size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
+
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/Journal/Entries",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of BMC Journal Entries";
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array_t();
+
+ // Go through the journal and use the timestamp to create a
+ // unique ID for each entry
+ sd_journal* journalTmp = nullptr;
+ int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("failed to open journal: {}", strerror(-ret));
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
+ journalTmp, sd_journal_close);
+ journalTmp = nullptr;
+
+ // Seek to the end
+ if (sd_journal_seek_tail(journal.get()) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Get the last entry
+ if (sd_journal_previous(journal.get()) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Get the last sequence number
+ uint64_t endSeqNum = 0;
+#if LIBSYSTEMD_VERSION >= 254
+ {
+ if (sd_journal_get_seqnum(journal.get(), &endSeqNum, nullptr) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+#endif
+
+ // Seek to the beginning
+ if (sd_journal_seek_head(journal.get()) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Get the first entry
+ if (sd_journal_next(journal.get()) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Get the first sequence number
+ uint64_t startSeqNum = 0;
+#if LIBSYSTEMD_VERSION >= 254
+ {
+ if (sd_journal_get_seqnum(journal.get(), &startSeqNum, nullptr) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+#endif
+
+ BMCWEB_LOG_DEBUG("journal Sequence IDs start:{} end:{}", startSeqNum,
+ endSeqNum);
+
+ // Add 1 to account for the last entry
+ uint64_t totalEntries = endSeqNum - startSeqNum + 1;
+ asyncResp->res.jsonValue["Members@odata.count"] = totalEntries;
+ if (skip + top < totalEntries)
+ {
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ boost::urls::format(
+ "/redfish/v1/Managers/{}/LogServices/Journal/Entries?$skip={}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME, std::to_string(skip + top));
+ }
+ uint64_t index = 0;
+ sd_id128_t curBootID{};
+ uint64_t curTs = 0;
+ if (skip > 0)
+ {
+ if (sd_journal_next_skip(journal.get(), skip) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Get the entry timestamp
+ ret = sd_journal_get_monotonic_usec(journal.get(), &curTs, &curBootID);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("Failed to read entry timestamp: {}",
+ strerror(-ret));
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ uint64_t endChunkSeqNum = 0;
+#if LIBSYSTEMD_VERSION >= 254
+ {
+ if (sd_journal_get_seqnum(journal.get(), &endChunkSeqNum, nullptr) <
+ 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+#endif
+
+ // Seek to the first entry with the same timestamp and boot
+ ret = sd_journal_seek_monotonic_usec(journal.get(), curBootID, curTs);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("Failed to seek: {}", strerror(-ret));
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (sd_journal_next(journal.get()) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ uint64_t startChunkSeqNum = 0;
+#if LIBSYSTEMD_VERSION >= 254
+ {
+ if (sd_journal_get_seqnum(journal.get(), &startChunkSeqNum,
+ nullptr) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+#endif
+
+ // Get the difference between the start and end. Most of the time this
+ // will be 0
+ BMCWEB_LOG_DEBUG("start={} end={}", startChunkSeqNum, endChunkSeqNum);
+ index = endChunkSeqNum - startChunkSeqNum;
+ if (index > endChunkSeqNum)
+ {
+ // Detect underflows. Should never happen.
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (index > 0)
+ {
+ BMCWEB_LOG_DEBUG("index = {}", index);
+ if (sd_journal_next_skip(journal.get(), index) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ }
+ // If this is the first entry of this series, reset the timestamps so the
+ // Index doesn't increment
+ if (index == 0)
+ {
+ curBootID = {};
+ curTs = 0;
+ }
+ else
+ {
+ index -= 1;
+ }
+ BMCWEB_LOG_DEBUG("Index was {}", index);
+ readJournalEntries(top, asyncResp,
+ {std::move(journal), index, curBootID, curTs});
+}
+
+inline void handleManagersJournalEntriesLogEntryGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& managerId, const std::string& entryID)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager", managerId);
+ return;
+ }
+
+ // Convert the unique ID back to a timestamp to find the entry
+ sd_id128_t bootID{};
+ uint64_t ts = 0;
+ uint64_t index = 0;
+ if (!getTimestampFromID(asyncResp, entryID, bootID, ts, index))
+ {
+ return;
+ }
+
+ sd_journal* journalTmp = nullptr;
+ int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("failed to open journal: {}", strerror(-ret));
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
+ journalTmp, sd_journal_close);
+ journalTmp = nullptr;
+ // Go to the timestamp in the log and move to the entry at the
+ // index tracking the unique ID
+ ret = sd_journal_seek_monotonic_usec(journal.get(), bootID, ts);
+ if (ret < 0)
+ {
+ BMCWEB_LOG_ERROR("failed to seek to an entry in journal{}",
+ strerror(-ret));
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (sd_journal_next_skip(journal.get(), index + 1) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json::object_t bmcJournalLogEntry;
+ if (!fillBMCJournalLogEntryJson(entryID, journal.get(), bmcJournalLogEntry))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue.update(bmcJournalLogEntry);
+}
+
+inline void requestRoutesBMCJournalLogService(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Journal/")
+ .privileges(redfish::privileges::getLogService)
+ .methods(boost::beast::http::verb::get)(
+ std::bind_front(handleManagersLogServiceJournalGet, std::ref(app)));
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/LogServices/Journal/Entries/")
+ .privileges(redfish::privileges::getLogEntryCollection)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleManagersJournalLogEntryCollectionGet, std::ref(app)));
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Managers/<str>/LogServices/Journal/Entries/<str>/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleManagersJournalEntriesLogEntryGet, std::ref(app)));
+}
+} // namespace redfish
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index f0a4e0ab21..c4f9956cf5 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -19,6 +19,9 @@
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/action_info.hpp"
+#include "generated/enums/manager.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
#include "registries/privilege_registry.hpp"
@@ -67,16 +70,16 @@ inline void
*crow::connections::systemBus, processName, objectPath, interfaceName,
destProperty, propertyValue,
[asyncResp](const boost::system::error_code& ec) {
- // Use "Set" method to set the property value.
- if (ec)
- {
- BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ // Use "Set" method to set the property value.
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- messages::success(asyncResp->res);
- });
+ messages::success(asyncResp->res);
+ });
}
inline void
@@ -94,16 +97,16 @@ inline void
*crow::connections::systemBus, processName, objectPath, interfaceName,
destProperty, propertyValue,
[asyncResp](const boost::system::error_code& ec) {
- // Use "Set" method to set the property value.
- if (ec)
- {
- BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ // Use "Set" method to set the property value.
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("[Set] Bad D-Bus request error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- messages::success(asyncResp->res);
- });
+ messages::success(asyncResp->res);
+ });
}
/**
@@ -124,44 +127,46 @@ inline void requestRoutesManagerResetAction(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- BMCWEB_LOG_DEBUG("Post Manager Reset.");
+ BMCWEB_LOG_DEBUG("Post Manager Reset.");
- std::string resetType;
+ std::string resetType;
- if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
- resetType))
- {
- return;
- }
+ if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
+ resetType))
+ {
+ return;
+ }
- if (resetType == "GracefulRestart")
- {
- BMCWEB_LOG_DEBUG("Proceeding with {}", resetType);
- doBMCGracefulRestart(asyncResp);
- return;
- }
- if (resetType == "ForceRestart")
- {
- BMCWEB_LOG_DEBUG("Proceeding with {}", resetType);
- doBMCForceRestart(asyncResp);
- return;
- }
- BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}", resetType);
- messages::actionParameterNotSupported(asyncResp->res, resetType,
- "ResetType");
+ if (resetType == "GracefulRestart")
+ {
+ BMCWEB_LOG_DEBUG("Proceeding with {}", resetType);
+ doBMCGracefulRestart(asyncResp);
+ return;
+ }
+ if (resetType == "ForceRestart")
+ {
+ BMCWEB_LOG_DEBUG("Proceeding with {}", resetType);
+ doBMCForceRestart(asyncResp);
+ return;
+ }
+ BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}",
+ resetType);
+ messages::actionParameterNotSupported(asyncResp->res, resetType,
+ "ResetType");
- return;
- });
+ return;
+ });
}
/**
@@ -185,70 +190,73 @@ inline void requestRoutesManagerResetToDefaultsAction(App& app)
BMCWEB_ROUTE(app,
"/redfish/v1/Managers/<str>/Actions/Manager.ResetToDefaults/")
.privileges(redfish::privileges::postManager)
- .methods(boost::beast::http::verb::post)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ .methods(
+ boost::beast::http::verb::
+ post)([&app](
+ const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& managerId) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- BMCWEB_LOG_DEBUG("Post ResetToDefaults.");
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- std::optional<std::string> resetType;
- std::optional<std::string> resetToDefaultsType;
+ BMCWEB_LOG_DEBUG("Post ResetToDefaults.");
- if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
- resetType, "ResetToDefaultsType",
- resetToDefaultsType))
- {
- BMCWEB_LOG_DEBUG("Missing property ResetType.");
+ std::optional<std::string> resetType;
+ std::optional<std::string> resetToDefaultsType;
- messages::actionParameterMissing(asyncResp->res, "ResetToDefaults",
- "ResetType");
- return;
- }
+ if (!json_util::readJsonAction(req, asyncResp->res, "ResetType",
+ resetType, "ResetToDefaultsType",
+ resetToDefaultsType))
+ {
+ BMCWEB_LOG_DEBUG("Missing property ResetType.");
- if (resetToDefaultsType && !resetType)
- {
- BMCWEB_LOG_WARNING(
- "Using deprecated ResetToDefaultsType, should be ResetType."
- "Support for the ResetToDefaultsType will be dropped in 2Q24");
- resetType = resetToDefaultsType;
- }
+ messages::actionParameterMissing(
+ asyncResp->res, "ResetToDefaults", "ResetType");
+ return;
+ }
- if (resetType != "ResetAll")
- {
- BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}",
- *resetType);
- messages::actionParameterNotSupported(asyncResp->res, *resetType,
- "ResetType");
- return;
- }
+ if (resetToDefaultsType && !resetType)
+ {
+ BMCWEB_LOG_WARNING(
+ "Using deprecated ResetToDefaultsType, should be ResetType."
+ "Support for the ResetToDefaultsType will be dropped in 2Q24");
+ resetType = resetToDefaultsType;
+ }
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code& ec) {
- if (ec)
+ if (resetType != "ResetAll")
{
- BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", ec);
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG("Invalid property value for ResetType: {}",
+ *resetType);
+ messages::actionParameterNotSupported(asyncResp->res,
+ *resetType, "ResetType");
return;
}
- // Factory Reset doesn't actually happen until a reboot
- // Can't erase what the BMC is running on
- doBMCGracefulRestart(asyncResp);
- },
- "xyz.openbmc_project.Software.BMC.Updater",
- "/xyz/openbmc_project/software",
- "xyz.openbmc_project.Common.FactoryReset", "Reset");
- });
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("Failed to ResetToDefaults: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // Factory Reset doesn't actually happen until a reboot
+ // Can't erase what the BMC is running on
+ doBMCGracefulRestart(asyncResp);
+ },
+ "xyz.openbmc_project.Software.BMC.Updater",
+ "/xyz/openbmc_project/software",
+ "xyz.openbmc_project.Common.FactoryReset", "Reset");
+ });
}
/**
@@ -267,39 +275,40 @@ inline void requestRoutesManagerResetActionInfo(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#ActionInfo.v1_1_2.ActionInfo";
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["Name"] = "Reset Action Info";
- asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
- nlohmann::json::object_t parameter;
- parameter["Name"] = "ResetType";
- parameter["Required"] = true;
- parameter["DataType"] = "String";
-
- nlohmann::json::array_t allowableValues;
- allowableValues.emplace_back("GracefulRestart");
- allowableValues.emplace_back("ForceRestart");
- parameter["AllowableValues"] = std::move(allowableValues);
-
- nlohmann::json::array_t parameters;
- parameters.emplace_back(std::move(parameter));
-
- asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
- });
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ActionInfo.v1_1_2.ActionInfo";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/ResetActionInfo",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "Reset Action Info";
+ asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
+ nlohmann::json::object_t parameter;
+ parameter["Name"] = "ResetType";
+ parameter["Required"] = true;
+ parameter["DataType"] = action_info::ParameterTypes::String;
+
+ nlohmann::json::array_t allowableValues;
+ allowableValues.emplace_back("GracefulRestart");
+ allowableValues.emplace_back("ForceRestart");
+ parameter["AllowableValues"] = std::move(allowableValues);
+
+ nlohmann::json::array_t parameters;
+ parameters.emplace_back(std::move(parameter));
+
+ asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
+ });
}
static constexpr const char* objectManagerIface =
@@ -325,231 +334,221 @@ inline void
[asyncResp, currentProfile, supportedProfiles](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& managedObj) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("{}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json& configRoot =
- asyncResp->res.jsonValue["Oem"]["OpenBmc"]["Fan"];
- nlohmann::json& fans = configRoot["FanControllers"];
- fans["@odata.type"] = "#OemManager.FanControllers";
- fans["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanControllers",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- nlohmann::json& pids = configRoot["PidControllers"];
- pids["@odata.type"] = "#OemManager.PidControllers";
- pids["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/PidControllers",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- nlohmann::json& stepwise = configRoot["StepwiseControllers"];
- stepwise["@odata.type"] = "#OemManager.StepwiseControllers";
- stepwise["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/StepwiseControllers",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- nlohmann::json& zones = configRoot["FanZones"];
- zones["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanZones",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- zones["@odata.type"] = "#OemManager.FanZones";
- configRoot["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- configRoot["@odata.type"] = "#OemManager.Fan";
- configRoot["Profile@Redfish.AllowableValues"] = supportedProfiles;
-
- if (!currentProfile.empty())
- {
- configRoot["Profile"] = currentProfile;
- }
- BMCWEB_LOG_DEBUG("profile = {} !", currentProfile);
-
- for (const auto& pathPair : managedObj)
- {
- for (const auto& intfPair : pathPair.second)
+ if (ec)
{
- if (intfPair.first != pidConfigurationIface &&
- intfPair.first != pidZoneConfigurationIface &&
- intfPair.first != stepwiseConfigurationIface)
- {
- continue;
- }
+ BMCWEB_LOG_ERROR("{}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& configRoot =
+ asyncResp->res.jsonValue["Oem"]["OpenBmc"]["Fan"];
+ nlohmann::json& fans = configRoot["FanControllers"];
+ fans["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.FanControllers";
+ fans["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanControllers",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+ nlohmann::json& pids = configRoot["PidControllers"];
+ pids["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.PidControllers";
+ pids["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/PidControllers",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+ nlohmann::json& stepwise = configRoot["StepwiseControllers"];
+ stepwise["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.StepwiseControllers";
+ stepwise["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/StepwiseControllers",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+ nlohmann::json& zones = configRoot["FanZones"];
+ zones["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan/FanZones",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ zones["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager.FanZones";
+ configRoot["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc/Fan",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ configRoot["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager.Fan";
+ configRoot["Profile@Redfish.AllowableValues"] = supportedProfiles;
- std::string name;
+ if (!currentProfile.empty())
+ {
+ configRoot["Profile"] = currentProfile;
+ }
+ BMCWEB_LOG_DEBUG("profile = {} !", currentProfile);
- for (const std::pair<std::string,
- dbus::utility::DbusVariantType>& propPair :
- intfPair.second)
+ for (const auto& pathPair : managedObj)
+ {
+ for (const auto& intfPair : pathPair.second)
{
- if (propPair.first == "Name")
+ if (intfPair.first != pidConfigurationIface &&
+ intfPair.first != pidZoneConfigurationIface &&
+ intfPair.first != stepwiseConfigurationIface)
{
- const std::string* namePtr =
- std::get_if<std::string>(&propPair.second);
- if (namePtr == nullptr)
- {
- BMCWEB_LOG_ERROR("Pid Name Field illegal");
- messages::internalError(asyncResp->res);
- return;
- }
- name = *namePtr;
- dbus::utility::escapePathForDbus(name);
+ continue;
}
- else if (propPair.first == "Profiles")
+
+ std::string name;
+
+ for (const std::pair<std::string,
+ dbus::utility::DbusVariantType>&
+ propPair : intfPair.second)
{
- const std::vector<std::string>* profiles =
- std::get_if<std::vector<std::string>>(
- &propPair.second);
- if (profiles == nullptr)
+ if (propPair.first == "Name")
{
- BMCWEB_LOG_ERROR("Pid Profiles Field illegal");
- messages::internalError(asyncResp->res);
- return;
+ const std::string* namePtr =
+ std::get_if<std::string>(&propPair.second);
+ if (namePtr == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Pid Name Field illegal");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ name = *namePtr;
+ dbus::utility::escapePathForDbus(name);
}
- if (std::find(profiles->begin(), profiles->end(),
- currentProfile) == profiles->end())
+ else if (propPair.first == "Profiles")
{
- BMCWEB_LOG_INFO(
- "{} not supported in current profile", name);
- continue;
+ const std::vector<std::string>* profiles =
+ std::get_if<std::vector<std::string>>(
+ &propPair.second);
+ if (profiles == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Pid Profiles Field illegal");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (std::find(profiles->begin(), profiles->end(),
+ currentProfile) == profiles->end())
+ {
+ BMCWEB_LOG_INFO(
+ "{} not supported in current profile",
+ name);
+ continue;
+ }
}
}
- }
- nlohmann::json* config = nullptr;
- const std::string* classPtr = nullptr;
-
- for (const std::pair<std::string,
- dbus::utility::DbusVariantType>& propPair :
- intfPair.second)
- {
- if (propPair.first == "Class")
- {
- classPtr = std::get_if<std::string>(&propPair.second);
- }
- }
+ nlohmann::json* config = nullptr;
+ const std::string* classPtr = nullptr;
- boost::urls::url url(
- boost::urls::format("/redfish/v1/Managers/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME));
- if (intfPair.first == pidZoneConfigurationIface)
- {
- std::string chassis;
- if (!dbus::utility::getNthStringFromPath(pathPair.first.str,
- 5, chassis))
+ for (const std::pair<std::string,
+ dbus::utility::DbusVariantType>&
+ propPair : intfPair.second)
{
- chassis = "#IllegalValue";
- }
- nlohmann::json& zone = zones[name];
- zone["Chassis"]["@odata.id"] =
- boost::urls::format("/redfish/v1/Chassis/{}", chassis);
- url.set_fragment(
- ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / name)
- .to_string());
- zone["@odata.id"] = std::move(url);
- zone["@odata.type"] = "#OemManager.FanZone";
- config = &zone;
- }
-
- else if (intfPair.first == stepwiseConfigurationIface)
- {
- if (classPtr == nullptr)
- {
- BMCWEB_LOG_ERROR("Pid Class Field illegal");
- messages::internalError(asyncResp->res);
- return;
+ if (propPair.first == "Class")
+ {
+ classPtr =
+ std::get_if<std::string>(&propPair.second);
+ }
}
- nlohmann::json& controller = stepwise[name];
- config = &controller;
- url.set_fragment(
- ("/Oem/OpenBmc/Fan/StepwiseControllers"_json_pointer /
- name)
- .to_string());
- controller["@odata.id"] = std::move(url);
- controller["@odata.type"] =
- "#OemManager.StepwiseController";
-
- controller["Direction"] = *classPtr;
- }
-
- // pid and fans are off the same configuration
- else if (intfPair.first == pidConfigurationIface)
- {
- if (classPtr == nullptr)
- {
- BMCWEB_LOG_ERROR("Pid Class Field illegal");
- messages::internalError(asyncResp->res);
- return;
- }
- bool isFan = *classPtr == "fan";
- nlohmann::json& element = isFan ? fans[name] : pids[name];
- config = &element;
- if (isFan)
+ boost::urls::url url(
+ boost::urls::format("/redfish/v1/Managers/{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME));
+ if (intfPair.first == pidZoneConfigurationIface)
{
+ std::string chassis;
+ if (!dbus::utility::getNthStringFromPath(
+ pathPair.first.str, 5, chassis))
+ {
+ chassis = "#IllegalValue";
+ }
+ nlohmann::json& zone = zones[name];
+ zone["Chassis"]["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}", chassis);
url.set_fragment(
- ("/Oem/OpenBmc/Fan/FanControllers"_json_pointer /
- name)
+ ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / name)
.to_string());
- element["@odata.id"] = std::move(url);
- element["@odata.type"] = "#OemManager.FanController";
+ zone["@odata.id"] = std::move(url);
+ zone["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.FanZone";
+ config = &zone;
}
- else
+
+ else if (intfPair.first == stepwiseConfigurationIface)
{
+ if (classPtr == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Pid Class Field illegal");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json& controller = stepwise[name];
+ config = &controller;
url.set_fragment(
- ("/Oem/OpenBmc/Fan/PidControllers"_json_pointer /
+ ("/Oem/OpenBmc/Fan/StepwiseControllers"_json_pointer /
name)
.to_string());
- element["@odata.id"] = std::move(url);
- element["@odata.type"] = "#OemManager.PidController";
- }
- }
- else
- {
- BMCWEB_LOG_ERROR("Unexpected configuration");
- messages::internalError(asyncResp->res);
- return;
- }
-
- // used for making maps out of 2 vectors
- const std::vector<double>* keys = nullptr;
- const std::vector<double>* values = nullptr;
+ controller["@odata.id"] = std::move(url);
+ controller["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.StepwiseController";
- for (const auto& propertyPair : intfPair.second)
- {
- if (propertyPair.first == "Type" ||
- propertyPair.first == "Class" ||
- propertyPair.first == "Name")
- {
- continue;
+ controller["Direction"] = *classPtr;
}
- // zones
- if (intfPair.first == pidZoneConfigurationIface)
+ // pid and fans are off the same configuration
+ else if (intfPair.first == pidConfigurationIface)
{
- const double* ptr =
- std::get_if<double>(&propertyPair.second);
- if (ptr == nullptr)
+ if (classPtr == nullptr)
{
- BMCWEB_LOG_ERROR("Field Illegal {}",
- propertyPair.first);
+ BMCWEB_LOG_ERROR("Pid Class Field illegal");
messages::internalError(asyncResp->res);
return;
}
- (*config)[propertyPair.first] = *ptr;
+ bool isFan = *classPtr == "fan";
+ nlohmann::json& element =
+ isFan ? fans[name] : pids[name];
+ config = &element;
+ if (isFan)
+ {
+ url.set_fragment(
+ ("/Oem/OpenBmc/Fan/FanControllers"_json_pointer /
+ name)
+ .to_string());
+ element["@odata.id"] = std::move(url);
+ element["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.FanController";
+ }
+ else
+ {
+ url.set_fragment(
+ ("/Oem/OpenBmc/Fan/PidControllers"_json_pointer /
+ name)
+ .to_string());
+ element["@odata.id"] = std::move(url);
+ element["@odata.type"] =
+ "#OpenBMCManager.v1_0_0.Manager.PidController";
+ }
}
+ else
+ {
+ BMCWEB_LOG_ERROR("Unexpected configuration");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // used for making maps out of 2 vectors
+ const std::vector<double>* keys = nullptr;
+ const std::vector<double>* values = nullptr;
- if (intfPair.first == stepwiseConfigurationIface)
+ for (const auto& propertyPair : intfPair.second)
{
- if (propertyPair.first == "Reading" ||
- propertyPair.first == "Output")
+ if (propertyPair.first == "Type" ||
+ propertyPair.first == "Class" ||
+ propertyPair.first == "Name")
{
- const std::vector<double>* ptr =
- std::get_if<std::vector<double>>(
- &propertyPair.second);
+ continue;
+ }
+ // zones
+ if (intfPair.first == pidZoneConfigurationIface)
+ {
+ const double* ptr =
+ std::get_if<double>(&propertyPair.second);
if (ptr == nullptr)
{
BMCWEB_LOG_ERROR("Field Illegal {}",
@@ -557,178 +556,202 @@ inline void
messages::internalError(asyncResp->res);
return;
}
+ (*config)[propertyPair.first] = *ptr;
+ }
- if (propertyPair.first == "Reading")
- {
- keys = ptr;
- }
- else
- {
- values = ptr;
- }
- if (keys != nullptr && values != nullptr)
+ if (intfPair.first == stepwiseConfigurationIface)
+ {
+ if (propertyPair.first == "Reading" ||
+ propertyPair.first == "Output")
{
- if (keys->size() != values->size())
+ const std::vector<double>* ptr =
+ std::get_if<std::vector<double>>(
+ &propertyPair.second);
+
+ if (ptr == nullptr)
{
- BMCWEB_LOG_ERROR(
- "Reading and Output size don't match ");
+ BMCWEB_LOG_ERROR("Field Illegal {}",
+ propertyPair.first);
messages::internalError(asyncResp->res);
return;
}
- nlohmann::json& steps = (*config)["Steps"];
- steps = nlohmann::json::array();
- for (size_t ii = 0; ii < keys->size(); ii++)
+
+ if (propertyPair.first == "Reading")
+ {
+ keys = ptr;
+ }
+ else
{
- nlohmann::json::object_t step;
- step["Target"] = (*keys)[ii];
- step["Output"] = (*values)[ii];
- steps.emplace_back(std::move(step));
+ values = ptr;
+ }
+ if (keys != nullptr && values != nullptr)
+ {
+ if (keys->size() != values->size())
+ {
+ BMCWEB_LOG_ERROR(
+ "Reading and Output size don't match ");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& steps = (*config)["Steps"];
+ steps = nlohmann::json::array();
+ for (size_t ii = 0; ii < keys->size(); ii++)
+ {
+ nlohmann::json::object_t step;
+ step["Target"] = (*keys)[ii];
+ step["Output"] = (*values)[ii];
+ steps.emplace_back(std::move(step));
+ }
}
}
- }
- if (propertyPair.first == "NegativeHysteresis" ||
- propertyPair.first == "PositiveHysteresis")
- {
- const double* ptr =
- std::get_if<double>(&propertyPair.second);
- if (ptr == nullptr)
+ if (propertyPair.first == "NegativeHysteresis" ||
+ propertyPair.first == "PositiveHysteresis")
{
- BMCWEB_LOG_ERROR("Field Illegal {}",
- propertyPair.first);
- messages::internalError(asyncResp->res);
- return;
+ const double* ptr =
+ std::get_if<double>(&propertyPair.second);
+ if (ptr == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Field Illegal {}",
+ propertyPair.first);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ (*config)[propertyPair.first] = *ptr;
}
- (*config)[propertyPair.first] = *ptr;
}
- }
-
- // pid and fans are off the same configuration
- if (intfPair.first == pidConfigurationIface ||
- intfPair.first == stepwiseConfigurationIface)
- {
- if (propertyPair.first == "Zones")
- {
- const std::vector<std::string>* inputs =
- std::get_if<std::vector<std::string>>(
- &propertyPair.second);
- if (inputs == nullptr)
- {
- BMCWEB_LOG_ERROR("Zones Pid Field Illegal");
- messages::internalError(asyncResp->res);
- return;
- }
- auto& data = (*config)[propertyPair.first];
- data = nlohmann::json::array();
- for (std::string itemCopy : *inputs)
- {
- dbus::utility::escapePathForDbus(itemCopy);
- nlohmann::json::object_t input;
- boost::urls::url managerUrl = boost::urls::format(
- "/redfish/v1/Managers/{}#{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME,
- ("/Oem/OpenBmc/Fan/FanZones"_json_pointer /
- itemCopy)
- .to_string());
- input["@odata.id"] = std::move(managerUrl);
- data.emplace_back(std::move(input));
- }
- }
- // todo(james): may never happen, but this
- // assumes configuration data referenced in the
- // PID config is provided by the same daemon, we
- // could add another loop to cover all cases,
- // but I'm okay kicking this can down the road a
- // bit
-
- else if (propertyPair.first == "Inputs" ||
- propertyPair.first == "Outputs")
+ // pid and fans are off the same configuration
+ if (intfPair.first == pidConfigurationIface ||
+ intfPair.first == stepwiseConfigurationIface)
{
- auto& data = (*config)[propertyPair.first];
- const std::vector<std::string>* inputs =
- std::get_if<std::vector<std::string>>(
- &propertyPair.second);
-
- if (inputs == nullptr)
+ if (propertyPair.first == "Zones")
{
- BMCWEB_LOG_ERROR("Field Illegal {}",
- propertyPair.first);
- messages::internalError(asyncResp->res);
- return;
- }
- data = *inputs;
- }
- else if (propertyPair.first == "SetPointOffset")
- {
- const std::string* ptr =
- std::get_if<std::string>(&propertyPair.second);
+ const std::vector<std::string>* inputs =
+ std::get_if<std::vector<std::string>>(
+ &propertyPair.second);
- if (ptr == nullptr)
- {
- BMCWEB_LOG_ERROR("Field Illegal {}",
- propertyPair.first);
- messages::internalError(asyncResp->res);
- return;
- }
- // translate from dbus to redfish
- if (*ptr == "WarningHigh")
- {
- (*config)["SetPointOffset"] =
- "UpperThresholdNonCritical";
- }
- else if (*ptr == "WarningLow")
- {
- (*config)["SetPointOffset"] =
- "LowerThresholdNonCritical";
- }
- else if (*ptr == "CriticalHigh")
- {
- (*config)["SetPointOffset"] =
- "UpperThresholdCritical";
+ if (inputs == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Zones Pid Field Illegal");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ auto& data = (*config)[propertyPair.first];
+ data = nlohmann::json::array();
+ for (std::string itemCopy : *inputs)
+ {
+ dbus::utility::escapePathForDbus(itemCopy);
+ nlohmann::json::object_t input;
+ boost::urls::url managerUrl =
+ boost::urls::format(
+ "/redfish/v1/Managers/{}#{}",
+ BMCWEB_REDFISH_MANAGER_URI_NAME,
+ ("/Oem/OpenBmc/Fan/FanZones"_json_pointer /
+ itemCopy)
+ .to_string());
+ input["@odata.id"] = std::move(managerUrl);
+ data.emplace_back(std::move(input));
+ }
}
- else if (*ptr == "CriticalLow")
+ // todo(james): may never happen, but this
+ // assumes configuration data referenced in the
+ // PID config is provided by the same daemon, we
+ // could add another loop to cover all cases,
+ // but I'm okay kicking this can down the road a
+ // bit
+
+ else if (propertyPair.first == "Inputs" ||
+ propertyPair.first == "Outputs")
{
- (*config)["SetPointOffset"] =
- "LowerThresholdCritical";
+ auto& data = (*config)[propertyPair.first];
+ const std::vector<std::string>* inputs =
+ std::get_if<std::vector<std::string>>(
+ &propertyPair.second);
+
+ if (inputs == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Field Illegal {}",
+ propertyPair.first);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ data = *inputs;
}
- else
+ else if (propertyPair.first == "SetPointOffset")
{
- BMCWEB_LOG_ERROR("Value Illegal {}", *ptr);
- messages::internalError(asyncResp->res);
- return;
+ const std::string* ptr =
+ std::get_if<std::string>(
+ &propertyPair.second);
+
+ if (ptr == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Field Illegal {}",
+ propertyPair.first);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // translate from dbus to redfish
+ if (*ptr == "WarningHigh")
+ {
+ (*config)["SetPointOffset"] =
+ "UpperThresholdNonCritical";
+ }
+ else if (*ptr == "WarningLow")
+ {
+ (*config)["SetPointOffset"] =
+ "LowerThresholdNonCritical";
+ }
+ else if (*ptr == "CriticalHigh")
+ {
+ (*config)["SetPointOffset"] =
+ "UpperThresholdCritical";
+ }
+ else if (*ptr == "CriticalLow")
+ {
+ (*config)["SetPointOffset"] =
+ "LowerThresholdCritical";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR("Value Illegal {}", *ptr);
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
- }
- // doubles
- else if (propertyPair.first == "FFGainCoefficient" ||
- propertyPair.first == "FFOffCoefficient" ||
- propertyPair.first == "ICoefficient" ||
- propertyPair.first == "ILimitMax" ||
- propertyPair.first == "ILimitMin" ||
- propertyPair.first == "PositiveHysteresis" ||
- propertyPair.first == "NegativeHysteresis" ||
- propertyPair.first == "OutLimitMax" ||
- propertyPair.first == "OutLimitMin" ||
- propertyPair.first == "PCoefficient" ||
- propertyPair.first == "SetPoint" ||
- propertyPair.first == "SlewNeg" ||
- propertyPair.first == "SlewPos")
- {
- const double* ptr =
- std::get_if<double>(&propertyPair.second);
- if (ptr == nullptr)
+ // doubles
+ else if (propertyPair.first ==
+ "FFGainCoefficient" ||
+ propertyPair.first == "FFOffCoefficient" ||
+ propertyPair.first == "ICoefficient" ||
+ propertyPair.first == "ILimitMax" ||
+ propertyPair.first == "ILimitMin" ||
+ propertyPair.first ==
+ "PositiveHysteresis" ||
+ propertyPair.first ==
+ "NegativeHysteresis" ||
+ propertyPair.first == "OutLimitMax" ||
+ propertyPair.first == "OutLimitMin" ||
+ propertyPair.first == "PCoefficient" ||
+ propertyPair.first == "SetPoint" ||
+ propertyPair.first == "SlewNeg" ||
+ propertyPair.first == "SlewPos")
{
- BMCWEB_LOG_ERROR("Field Illegal {}",
- propertyPair.first);
- messages::internalError(asyncResp->res);
- return;
+ const double* ptr =
+ std::get_if<double>(&propertyPair.second);
+ if (ptr == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Field Illegal {}",
+ propertyPair.first);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ (*config)[propertyPair.first] = *ptr;
}
- (*config)[propertyPair.first] = *ptr;
}
}
}
}
- }
- });
+ });
}
enum class CreatePIDRet
@@ -841,14 +864,14 @@ inline CreatePIDRet createPidInterface(
// delete interface
crow::connections::systemBus->async_method_call(
[response, path](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Error patching {}: {}", path, ec);
- messages::internalError(response->res);
- return;
- }
- messages::success(response->res);
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error patching {}: {}", path, ec);
+ messages::internalError(response->res);
+ return;
+ }
+ messages::success(response->res);
+ },
"xyz.openbmc_project.EntityManager", path, iface, "Delete");
return CreatePIDRet::del;
}
@@ -909,8 +932,8 @@ inline CreatePIDRet createPidInterface(
return CreatePIDRet::fail;
}
if (std::find(curProfiles->begin(),
- curProfiles->end(),
- profile) == curProfiles->end())
+ curProfiles->end(), profile) ==
+ curProfiles->end())
{
std::vector<std::string> newProfiles =
*curProfiles;
@@ -1046,10 +1069,10 @@ inline CreatePIDRet createPidInterface(
std::optional<std::string> chassisId;
std::optional<double> failSafePercent;
std::optional<double> minThermalOutput;
- if (!redfish::json_util::readJson(jsonValue, response->res,
- "Chassis/@odata.id", chassisId,
- "FailSafePercent", failSafePercent,
- "MinThermalOutput", minThermalOutput))
+ if (!redfish::json_util::readJson(
+ jsonValue, response->res, "Chassis/@odata.id", chassisId,
+ "FailSafePercent", failSafePercent, "MinThermalOutput",
+ minThermalOutput))
{
return CreatePIDRet::fail;
}
@@ -1199,14 +1222,14 @@ struct GetPIDValues : std::enable_shared_from_this<GetPIDValues>
[self](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtreeLocal) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("{}", ec);
- messages::internalError(self->asyncResp->res);
- return;
- }
- self->complete.subtree = subtreeLocal;
- });
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("{}", ec);
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+ self->complete.subtree = subtreeLocal;
+ });
// at the same time get the selected profile
constexpr std::array<std::string_view, 1> thermalModeIfaces = {
@@ -1216,58 +1239,61 @@ struct GetPIDValues : std::enable_shared_from_this<GetPIDValues>
[self](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtreeLocal) {
- if (ec || subtreeLocal.empty())
- {
- return;
- }
- if (subtreeLocal[0].second.size() != 1)
- {
- // invalid mapper response, should never happen
- BMCWEB_LOG_ERROR("GetPIDValues: Mapper Error");
- messages::internalError(self->asyncResp->res);
- return;
- }
-
- const std::string& path = subtreeLocal[0].first;
- const std::string& owner = subtreeLocal[0].second[0].first;
-
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, owner, path, thermalModeIface,
- [path, owner,
- self](const boost::system::error_code& ec2,
- const dbus::utility::DBusPropertiesMap& resp) {
- if (ec2)
+ if (ec || subtreeLocal.empty())
{
- BMCWEB_LOG_ERROR(
- "GetPIDValues: Can't get thermalModeIface {}", path);
- messages::internalError(self->asyncResp->res);
return;
}
-
- const std::string* current = nullptr;
- const std::vector<std::string>* supported = nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), resp, "Current", current,
- "Supported", supported);
-
- if (!success)
+ if (subtreeLocal[0].second.size() != 1)
{
+ // invalid mapper response, should never happen
+ BMCWEB_LOG_ERROR("GetPIDValues: Mapper Error");
messages::internalError(self->asyncResp->res);
return;
}
- if (current == nullptr || supported == nullptr)
- {
- BMCWEB_LOG_ERROR(
- "GetPIDValues: thermal mode iface invalid {}", path);
- messages::internalError(self->asyncResp->res);
- return;
- }
- self->complete.currentProfile = *current;
- self->complete.supportedProfiles = *supported;
+ const std::string& path = subtreeLocal[0].first;
+ const std::string& owner = subtreeLocal[0].second[0].first;
+
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, owner, path,
+ thermalModeIface,
+ [path, owner,
+ self](const boost::system::error_code& ec2,
+ const dbus::utility::DBusPropertiesMap& resp) {
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "GetPIDValues: Can't get thermalModeIface {}",
+ path);
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+
+ const std::string* current = nullptr;
+ const std::vector<std::string>* supported = nullptr;
+
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), resp, "Current",
+ current, "Supported", supported);
+
+ if (!success)
+ {
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+
+ if (current == nullptr || supported == nullptr)
+ {
+ BMCWEB_LOG_ERROR(
+ "GetPIDValues: thermal mode iface invalid {}",
+ path);
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+ self->complete.currentProfile = *current;
+ self->complete.supportedProfiles = *supported;
+ });
});
- });
}
static void
@@ -1354,8 +1380,7 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
std::pair<std::string, std::optional<nlohmann::json::object_t>>>&&
configurationsIn,
std::optional<std::string>& profileIn) :
- asyncResp(asyncRespIn),
- configuration(std::move(configurationsIn)),
+ asyncResp(asyncRespIn), configuration(std::move(configurationsIn)),
profile(std::move(profileIn))
{}
@@ -1381,30 +1406,30 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
"xyz.openbmc_project.EntityManager", objPath,
[self](const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& mObj) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Error communicating to Entity Manager");
- messages::internalError(self->asyncResp->res);
- return;
- }
- const std::array<const char*, 3> configurations = {
- pidConfigurationIface, pidZoneConfigurationIface,
- stepwiseConfigurationIface};
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error communicating to Entity Manager");
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+ const std::array<const char*, 3> configurations = {
+ pidConfigurationIface, pidZoneConfigurationIface,
+ stepwiseConfigurationIface};
- for (const auto& [path, object] : mObj)
- {
- for (const auto& [interface, _] : object)
+ for (const auto& [path, object] : mObj)
{
- if (std::ranges::find(configurations, interface) !=
- configurations.end())
+ for (const auto& [interface, _] : object)
{
- self->objectCount++;
- break;
+ if (std::ranges::find(configurations, interface) !=
+ configurations.end())
+ {
+ self->objectCount++;
+ break;
+ }
}
}
- }
- self->managedObj = mObj;
- });
+ self->managedObj = mObj;
+ });
// at the same time get the profile information
constexpr std::array<std::string_view, 1> thermalModeIfaces = {
@@ -1413,57 +1438,61 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
"/", 0, thermalModeIfaces,
[self](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec || subtree.empty())
- {
- return;
- }
- if (subtree[0].second.empty())
- {
- // invalid mapper response, should never happen
- BMCWEB_LOG_ERROR("SetPIDValues: Mapper Error");
- messages::internalError(self->asyncResp->res);
- return;
- }
-
- const std::string& path = subtree[0].first;
- const std::string& owner = subtree[0].second[0].first;
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, owner, path, thermalModeIface,
- [self, path, owner](const boost::system::error_code& ec2,
- const dbus::utility::DBusPropertiesMap& r) {
- if (ec2)
+ if (ec || subtree.empty())
{
- BMCWEB_LOG_ERROR(
- "SetPIDValues: Can't get thermalModeIface {}", path);
- messages::internalError(self->asyncResp->res);
return;
}
- const std::string* current = nullptr;
- const std::vector<std::string>* supported = nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), r, "Current", current,
- "Supported", supported);
-
- if (!success)
+ if (subtree[0].second.empty())
{
+ // invalid mapper response, should never happen
+ BMCWEB_LOG_ERROR("SetPIDValues: Mapper Error");
messages::internalError(self->asyncResp->res);
return;
}
- if (current == nullptr || supported == nullptr)
- {
- BMCWEB_LOG_ERROR(
- "SetPIDValues: thermal mode iface invalid {}", path);
- messages::internalError(self->asyncResp->res);
- return;
- }
- self->currentProfile = *current;
- self->supportedProfiles = *supported;
- self->profileConnection = owner;
- self->profilePath = path;
+ const std::string& path = subtree[0].first;
+ const std::string& owner = subtree[0].second[0].first;
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, owner, path,
+ thermalModeIface,
+ [self, path,
+ owner](const boost::system::error_code& ec2,
+ const dbus::utility::DBusPropertiesMap& r) {
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "SetPIDValues: Can't get thermalModeIface {}",
+ path);
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+ const std::string* current = nullptr;
+ const std::vector<std::string>* supported = nullptr;
+
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), r, "Current",
+ current, "Supported", supported);
+
+ if (!success)
+ {
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+
+ if (current == nullptr || supported == nullptr)
+ {
+ BMCWEB_LOG_ERROR(
+ "SetPIDValues: thermal mode iface invalid {}",
+ path);
+ messages::internalError(self->asyncResp->res);
+ return;
+ }
+ self->currentProfile = *current;
+ self->supportedProfiles = *supported;
+ self->profileConnection = owner;
+ self->profilePath = path;
+ });
});
- });
}
void pidSetDone()
{
@@ -1486,12 +1515,12 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
*crow::connections::systemBus, profileConnection, profilePath,
thermalModeIface, "Current", *profile,
[response](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Error patching profile{}", ec);
- messages::internalError(response->res);
- }
- });
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error patching profile{}", ec);
+ messages::internalError(response->res);
+ }
+ });
}
for (auto& containerPair : configuration)
@@ -1512,8 +1541,8 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
auto pathItr = std::ranges::find_if(
managedObj, [&dbusObjName](const auto& obj) {
- return obj.first.filename() == dbusObjName;
- });
+ return obj.first.filename() == dbusObjName;
+ });
dbus::utility::DBusPropertiesMap output;
output.reserve(16); // The pid interface length
@@ -1614,15 +1643,15 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
[response,
propertyName{std::string(property.first)}](
const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Error patching {}: {}",
- propertyName, ec);
- messages::internalError(response->res);
- return;
- }
- messages::success(response->res);
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error patching {}: {}",
+ propertyName, ec);
+ messages::internalError(response->res);
+ return;
+ }
+ messages::success(response->res);
+ },
"xyz.openbmc_project.EntityManager", path,
"org.freedesktop.DBus.Properties", "Set", iface,
property.first, property.second);
@@ -1659,14 +1688,15 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues>
crow::connections::systemBus->async_method_call(
[response](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Error Adding Pid Object {}", ec);
- messages::internalError(response->res);
- return;
- }
- messages::success(response->res);
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error Adding Pid Object {}",
+ ec);
+ messages::internalError(response->res);
+ return;
+ }
+ messages::success(response->res);
+ },
"xyz.openbmc_project.EntityManager", chassis,
"xyz.openbmc_project.AddObject", "AddObject", output);
}
@@ -1717,17 +1747,18 @@ inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
[asyncResp](const boost::system::error_code& ec,
const std::string& property) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error for "
- "Location");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error for "
+ "Location");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- property;
- });
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+ property;
+ });
}
// avoid name collision systems.hpp
inline void
@@ -1741,20 +1772,20 @@ inline void
"LastRebootTime",
[asyncResp](const boost::system::error_code& ec,
const uint64_t lastResetTime) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
+ return;
+ }
- // LastRebootTime is epoch time, in milliseconds
- // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
- uint64_t lastResetTimeStamp = lastResetTime / 1000;
+ // LastRebootTime is epoch time, in milliseconds
+ // https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
+ uint64_t lastResetTimeStamp = lastResetTime / 1000;
- // Convert to ISO 8601 standard
- asyncResp->res.jsonValue["LastResetTime"] =
- redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
- });
+ // Convert to ISO 8601 standard
+ asyncResp->res.jsonValue["LastResetTime"] =
+ redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
+ });
}
/**
@@ -1795,81 +1826,80 @@ inline void
[asyncResp, firmwareId, runningFirmwareTarget](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("D-Bus response error getting objects.");
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (subtree.empty())
- {
- BMCWEB_LOG_DEBUG("Can't find image!");
- messages::internalError(asyncResp->res);
- return;
- }
-
- bool foundImage = false;
- for (const auto& object : subtree)
- {
- const std::string& path =
- static_cast<const std::string&>(object.first);
- std::size_t idPos2 = path.rfind('/');
-
- if (idPos2 == std::string::npos)
+ if (ec)
{
- continue;
+ BMCWEB_LOG_DEBUG("D-Bus response error getting objects.");
+ messages::internalError(asyncResp->res);
+ return;
}
- idPos2++;
- if (idPos2 >= path.size())
+ if (subtree.empty())
{
- continue;
+ BMCWEB_LOG_DEBUG("Can't find image!");
+ messages::internalError(asyncResp->res);
+ return;
}
- if (path.substr(idPos2) == firmwareId)
+ bool foundImage = false;
+ for (const auto& object : subtree)
{
- foundImage = true;
- break;
- }
- }
+ const std::string& path =
+ static_cast<const std::string&>(object.first);
+ std::size_t idPos2 = path.rfind('/');
- if (!foundImage)
- {
- messages::propertyValueNotInList(
- asyncResp->res, runningFirmwareTarget, "@odata.id");
- BMCWEB_LOG_DEBUG("Invalid firmware ID.");
- return;
- }
+ if (idPos2 == std::string::npos)
+ {
+ continue;
+ }
+
+ idPos2++;
+ if (idPos2 >= path.size())
+ {
+ continue;
+ }
+
+ if (path.substr(idPos2) == firmwareId)
+ {
+ foundImage = true;
+ break;
+ }
+ }
- BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.",
- firmwareId);
-
- // Only support Immediate
- // An addition could be a Redfish Setting like
- // ActiveSoftwareImageApplyTime and support OnReset
- sdbusplus::asio::setProperty(
- *crow::connections::systemBus,
- "xyz.openbmc_project.Software.BMC.Updater",
- "/xyz/openbmc_project/software/" + firmwareId,
- "xyz.openbmc_project.Software.RedundancyPriority", "Priority",
- static_cast<uint8_t>(0),
- [asyncResp](const boost::system::error_code& ec2) {
- if (ec2)
+ if (!foundImage)
{
- BMCWEB_LOG_DEBUG("D-Bus response error setting.");
- messages::internalError(asyncResp->res);
+ messages::propertyValueNotInList(
+ asyncResp->res, runningFirmwareTarget, "@odata.id");
+ BMCWEB_LOG_DEBUG("Invalid firmware ID.");
return;
}
- doBMCGracefulRestart(asyncResp);
+
+ BMCWEB_LOG_DEBUG("Setting firmware version {} to priority 0.",
+ firmwareId);
+
+ // Only support Immediate
+ // An addition could be a Redfish Setting like
+ // ActiveSoftwareImageApplyTime and support OnReset
+ sdbusplus::asio::setProperty(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.Software.BMC.Updater",
+ "/xyz/openbmc_project/software/" + firmwareId,
+ "xyz.openbmc_project.Software.RedundancyPriority", "Priority",
+ static_cast<uint8_t>(0),
+ [asyncResp](const boost::system::error_code& ec2) {
+ if (ec2)
+ {
+ BMCWEB_LOG_DEBUG("D-Bus response error setting.");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ doBMCGracefulRestart(asyncResp);
+ });
});
- });
}
-inline void
- afterSetDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const boost::system::error_code& ec,
- const sdbusplus::message_t& msg)
+inline void afterSetDateTime(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec, const sdbusplus::message_t& msg)
{
if (ec)
{
@@ -1914,8 +1944,8 @@ inline void setDateTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec,
const sdbusplus::message_t& msg) {
- afterSetDateTime(asyncResp, ec, msg);
- },
+ afterSetDateTime(asyncResp, ec, msg);
+ },
"org.freedesktop.timedate1", "/org/freedesktop/timedate1",
"org.freedesktop.timedate1", "SetTime", us->count(), relative,
interactive);
@@ -1930,18 +1960,21 @@ inline void
"org.freedesktop.systemd1.Unit", "ActiveState",
[asyncResp](const boost::system::error_code& ec,
const std::string& val) {
- if (!ec)
- {
- if (val == "active")
+ if (!ec)
{
- asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
- asyncResp->res.jsonValue["Status"]["State"] = "Quiesced";
- return;
+ if (val == "active")
+ {
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::Critical;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Quiesced;
+ return;
+ }
}
- }
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- });
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+ });
}
inline void requestRoutesManager(App& app)
@@ -1950,295 +1983,321 @@ inline void requestRoutesManager(App& app)
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/")
.privileges(redfish::privileges::getManager)
- .methods(boost::beast::http::verb::get)(
- [&app, uuid](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
-
- 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";
- asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME;
- asyncResp->res.jsonValue["Name"] = "OpenBmc Manager";
- asyncResp->res.jsonValue["Description"] =
- "Baseboard Management Controller";
- asyncResp->res.jsonValue["PowerState"] = "On";
-
- asyncResp->res.jsonValue["ManagerType"] = "BMC";
- asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid();
- asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid;
- asyncResp->res.jsonValue["Model"] = "OpenBmc"; // TODO(ed), get model
-
- asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/LogServices",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- if constexpr (BMCWEB_VM_NBDPROXY)
- {
- asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- }
-
- // default oem data
- nlohmann::json& oem = asyncResp->res.jsonValue["Oem"];
- nlohmann::json& oemOpenbmc = oem["OpenBmc"];
- oem["@odata.type"] = "#OemManager.Oem";
- oem["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}#/Oem",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc";
- oemOpenbmc["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- nlohmann::json::object_t certificates;
- certificates["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/Truststore/Certificates",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- oemOpenbmc["Certificates"] = std::move(certificates);
-
- // Manager.Reset (an action) can be many values, OpenBMC only
- // supports BMC reboot.
- nlohmann::json& managerReset =
- asyncResp->res.jsonValue["Actions"]["#Manager.Reset"];
- managerReset["target"] =
- boost::urls::format("/redfish/v1/Managers/{}/Actions/Manager.Reset",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- managerReset["@Redfish.ActionInfo"] =
- boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- // ResetToDefaults (Factory Reset) has values like
- // PreserveNetworkAndUsers and PreserveNetwork that aren't supported
- // on OpenBMC
- nlohmann::json& resetToDefaults =
- asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"];
- resetToDefaults["target"] = boost::urls::format(
- "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- resetToDefaults["ResetType@Redfish.AllowableValues"] =
- nlohmann::json::array_t({"ResetAll"});
-
- std::pair<std::string, std::string> redfishDateTimeOffset =
- redfish::time_utils::getDateTimeOffsetNow();
-
- asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
- asyncResp->res.jsonValue["DateTimeLocalOffset"] =
- redfishDateTimeOffset.second;
-
- // TODO (Gunnar): Remove these one day since moved to ComputerSystem
- // Still used by OCP profiles
- // https://github.com/opencomputeproject/OCP-Profiles/issues/23
- // Fill in SerialConsole info
- asyncResp->res.jsonValue["SerialConsole"]["ServiceEnabled"] = true;
- asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
- asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] =
- nlohmann::json::array_t({"IPMI", "SSH"});
- if constexpr (BMCWEB_KVM)
- {
- // Fill in GraphicalConsole info
- asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] =
- true;
- asyncResp->res
- .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4;
- asyncResp->res
- .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
- nlohmann::json::array_t({"KVMIP"});
- }
- if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] =
- 1;
-
- nlohmann::json::array_t managerForServers;
- nlohmann::json::object_t manager;
- manager["@odata.id"] = std::format("/redfish/v1/Systems/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
- managerForServers.emplace_back(std::move(manager));
-
- asyncResp->res.jsonValue["Links"]["ManagerForServers"] =
- std::move(managerForServers);
- }
-
- sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose,
- "FirmwareVersion", true);
-
- managerGetLastResetTime(asyncResp);
-
- // ManagerDiagnosticData is added for all BMCs.
- nlohmann::json& managerDiagnosticData =
- asyncResp->res.jsonValue["ManagerDiagnosticData"];
- managerDiagnosticData["@odata.id"] =
- boost::urls::format("/redfish/v1/Managers/{}/ManagerDiagnosticData",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
-
- if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA)
- {
- auto pids = std::make_shared<GetPIDValues>(asyncResp);
- pids->run();
- }
-
- getMainChassisId(asyncResp,
- [](const std::string& chassisId,
- const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
- aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 1;
- nlohmann::json::array_t managerForChassis;
- nlohmann::json::object_t managerObj;
- boost::urls::url chassiUrl =
- boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
- managerObj["@odata.id"] = chassiUrl;
- managerForChassis.emplace_back(std::move(managerObj));
- aRsp->res.jsonValue["Links"]["ManagerForChassis"] =
- std::move(managerForChassis);
- aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] =
- chassiUrl;
- });
-
- sdbusplus::asio::getProperty<double>(
- *crow::connections::systemBus, "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager",
- "Progress",
- [asyncResp](const boost::system::error_code& ec, double val) {
- if (ec)
+ .methods(
+ boost::beast::http::verb::
+ get)([&app,
+ uuid](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& managerId) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- BMCWEB_LOG_ERROR("Error while getting progress");
- messages::internalError(asyncResp->res);
return;
}
- if (val < 1.0)
+
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
{
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
- asyncResp->res.jsonValue["Status"]["State"] = "Starting";
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
return;
}
- checkForQuiesced(asyncResp);
- });
- constexpr std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Bmc"};
- dbus::utility::getSubTree(
- "/xyz/openbmc_project/inventory", 0, interfaces,
- [asyncResp](
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
+ 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";
+ asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME;
+ asyncResp->res.jsonValue["Name"] = "OpenBmc Manager";
+ asyncResp->res.jsonValue["Description"] =
+ "Baseboard Management Controller";
+ asyncResp->res.jsonValue["PowerState"] = resource::PowerState::On;
+
+ asyncResp->res.jsonValue["ManagerType"] = manager::ManagerType::BMC;
+ asyncResp->res.jsonValue["UUID"] = systemd_utils::getUuid();
+ asyncResp->res.jsonValue["ServiceEntryPointUUID"] = uuid;
+ asyncResp->res.jsonValue["Model"] =
+ "OpenBmc"; // TODO(ed), get model
+
+ asyncResp->res.jsonValue["LogServices"]["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}/LogServices",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] =
+ boost::urls::format(
+ "/redfish/v1/Managers/{}/EthernetInterfaces",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+ if constexpr (BMCWEB_VM_NBDPROXY)
{
- BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
- return;
+ asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
}
- if (subtree.empty())
+
+ // default oem data
+ nlohmann::json& oem = asyncResp->res.jsonValue["Oem"];
+ nlohmann::json& oemOpenbmc = oem["OpenBmc"];
+ oem["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}#/Oem",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ oemOpenbmc["@odata.type"] = "#OpenBMCManager.v1_0_0.Manager";
+ oemOpenbmc["@odata.id"] =
+ boost::urls::format("/redfish/v1/Managers/{}#/Oem/OpenBmc",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+ nlohmann::json::object_t certificates;
+ certificates["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/Truststore/Certificates",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ oemOpenbmc["Certificates"] = std::move(certificates);
+
+ // Manager.Reset (an action) can be many values, OpenBMC only
+ // supports BMC reboot.
+ nlohmann::json& managerReset =
+ asyncResp->res.jsonValue["Actions"]["#Manager.Reset"];
+ managerReset["target"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/Actions/Manager.Reset",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ managerReset["@Redfish.ActionInfo"] =
+ boost::urls::format("/redfish/v1/Managers/{}/ResetActionInfo",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+ // ResetToDefaults (Factory Reset) has values like
+ // PreserveNetworkAndUsers and PreserveNetwork that aren't supported
+ // on OpenBMC
+ nlohmann::json& resetToDefaults =
+ asyncResp->res.jsonValue["Actions"]["#Manager.ResetToDefaults"];
+ resetToDefaults["target"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/Actions/Manager.ResetToDefaults",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
+ resetToDefaults["ResetType@Redfish.AllowableValues"] =
+ nlohmann::json::array_t({"ResetAll"});
+
+ std::pair<std::string, std::string> redfishDateTimeOffset =
+ redfish::time_utils::getDateTimeOffsetNow();
+
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+ redfishDateTimeOffset.second;
+
+ // TODO (Gunnar): Remove these one day since moved to ComputerSystem
+ // Still used by OCP profiles
+ // https://github.com/opencomputeproject/OCP-Profiles/issues/23
+ // Fill in SerialConsole info
+ asyncResp->res.jsonValue["SerialConsole"]["ServiceEnabled"] = true;
+ asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] =
+ 15;
+ asyncResp->res.jsonValue["SerialConsole"]["ConnectTypesSupported"] =
+ nlohmann::json::array_t({"IPMI", "SSH"});
+ if constexpr (BMCWEB_KVM)
{
- BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!");
- return;
+ // Fill in GraphicalConsole info
+ asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] =
+ true;
+ asyncResp->res
+ .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4;
+ asyncResp->res
+ .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] =
+ nlohmann::json::array_t({"KVMIP"});
}
- // Assume only 1 bmc D-Bus object
- // Throw an error if there is more than 1
- if (subtree.size() > 1)
+ if constexpr (!BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
{
- BMCWEB_LOG_DEBUG("Found more than 1 bmc D-Bus object!");
- messages::internalError(asyncResp->res);
- return;
- }
+ asyncResp->res
+ .jsonValue["Links"]["ManagerForServers@odata.count"] = 1;
- if (subtree[0].first.empty() || subtree[0].second.size() != 1)
- {
- BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!");
- messages::internalError(asyncResp->res);
- return;
+ nlohmann::json::array_t managerForServers;
+ nlohmann::json::object_t manager;
+ manager["@odata.id"] = std::format(
+ "/redfish/v1/Systems/{}", BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ managerForServers.emplace_back(std::move(manager));
+
+ asyncResp->res.jsonValue["Links"]["ManagerForServers"] =
+ std::move(managerForServers);
}
- const std::string& path = subtree[0].first;
- const std::string& connectionName = subtree[0].second[0].first;
+ sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose,
+ "FirmwareVersion", true);
- for (const auto& interfaceName : subtree[0].second[0].second)
- {
- if (interfaceName ==
- "xyz.openbmc_project.Inventory.Decorator.Asset")
- {
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, connectionName, path,
- "xyz.openbmc_project.Inventory.Decorator.Asset",
- [asyncResp](const boost::system::error_code& ec2,
- const dbus::utility::DBusPropertiesMap&
- propertiesList) {
- if (ec2)
- {
- BMCWEB_LOG_DEBUG("Can't get bmc asset!");
- return;
- }
+ managerGetLastResetTime(asyncResp);
- const std::string* partNumber = nullptr;
- const std::string* serialNumber = nullptr;
- const std::string* manufacturer = nullptr;
- const std::string* model = nullptr;
- const std::string* sparePartNumber = nullptr;
+ // ManagerDiagnosticData is added for all BMCs.
+ nlohmann::json& managerDiagnosticData =
+ asyncResp->res.jsonValue["ManagerDiagnosticData"];
+ managerDiagnosticData["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/ManagerDiagnosticData",
+ BMCWEB_REDFISH_MANAGER_URI_NAME);
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList,
- "PartNumber", partNumber, "SerialNumber",
- serialNumber, "Manufacturer", manufacturer, "Model",
- model, "SparePartNumber", sparePartNumber);
+ if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA)
+ {
+ auto pids = std::make_shared<GetPIDValues>(asyncResp);
+ pids->run();
+ }
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ getMainChassisId(asyncResp, [](const std::string& chassisId,
+ const std::shared_ptr<
+ bmcweb::AsyncResp>& aRsp) {
+ aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] =
+ 1;
+ nlohmann::json::array_t managerForChassis;
+ nlohmann::json::object_t managerObj;
+ boost::urls::url chassiUrl =
+ boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
+ managerObj["@odata.id"] = chassiUrl;
+ managerForChassis.emplace_back(std::move(managerObj));
+ aRsp->res.jsonValue["Links"]["ManagerForChassis"] =
+ std::move(managerForChassis);
+ aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] =
+ chassiUrl;
+ });
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] =
- *partNumber;
- }
+ sdbusplus::asio::getProperty<double>(
+ *crow::connections::systemBus, "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager",
+ "Progress",
+ [asyncResp](const boost::system::error_code& ec, double val) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error while getting progress");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (val < 1.0)
+ {
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::OK;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Starting;
+ return;
+ }
+ checkForQuiesced(asyncResp);
+ });
- if (serialNumber != nullptr)
- {
- asyncResp->res.jsonValue["SerialNumber"] =
- *serialNumber;
- }
+ constexpr std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Bmc"};
+ dbus::utility::getSubTree(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ [asyncResp](
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG(
+ "D-Bus response error on GetSubTree {}", ec);
+ return;
+ }
+ if (subtree.empty())
+ {
+ BMCWEB_LOG_DEBUG("Can't find bmc D-Bus object!");
+ return;
+ }
+ // Assume only 1 bmc D-Bus object
+ // Throw an error if there is more than 1
+ if (subtree.size() > 1)
+ {
+ BMCWEB_LOG_DEBUG("Found more than 1 bmc D-Bus object!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (manufacturer != nullptr)
- {
- asyncResp->res.jsonValue["Manufacturer"] =
- *manufacturer;
- }
+ if (subtree[0].first.empty() ||
+ subtree[0].second.size() != 1)
+ {
+ BMCWEB_LOG_DEBUG("Error getting bmc D-Bus object!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string& path = subtree[0].first;
+ const std::string& connectionName =
+ subtree[0].second[0].first;
- if (model != nullptr)
+ for (const auto& interfaceName :
+ subtree[0].second[0].second)
+ {
+ if (interfaceName ==
+ "xyz.openbmc_project.Inventory.Decorator.Asset")
{
- asyncResp->res.jsonValue["Model"] = *model;
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, connectionName,
+ path,
+ "xyz.openbmc_project.Inventory.Decorator.Asset",
+ [asyncResp](
+ const boost::system::error_code& ec2,
+ const dbus::utility::DBusPropertiesMap&
+ propertiesList) {
+ if (ec2)
+ {
+ BMCWEB_LOG_DEBUG(
+ "Can't get bmc asset!");
+ return;
+ }
+
+ const std::string* partNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* manufacturer = nullptr;
+ const std::string* model = nullptr;
+ const std::string* sparePartNumber =
+ nullptr;
+
+ const bool success =
+ sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(),
+ propertiesList, "PartNumber",
+ partNumber, "SerialNumber",
+ serialNumber, "Manufacturer",
+ manufacturer, "Model", model,
+ "SparePartNumber", sparePartNumber);
+
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] =
+ *partNumber;
+ }
+
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res
+ .jsonValue["SerialNumber"] =
+ *serialNumber;
+ }
+
+ if (manufacturer != nullptr)
+ {
+ asyncResp->res
+ .jsonValue["Manufacturer"] =
+ *manufacturer;
+ }
+
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] =
+ *model;
+ }
+
+ if (sparePartNumber != nullptr)
+ {
+ asyncResp->res
+ .jsonValue["SparePartNumber"] =
+ *sparePartNumber;
+ }
+ });
}
-
- if (sparePartNumber != nullptr)
+ else if (
+ interfaceName ==
+ "xyz.openbmc_project.Inventory.Decorator.LocationCode")
{
- asyncResp->res.jsonValue["SparePartNumber"] =
- *sparePartNumber;
+ getLocation(asyncResp, connectionName, path);
}
- });
- }
- else if (interfaceName ==
- "xyz.openbmc_project.Inventory.Decorator.LocationCode")
- {
- getLocation(asyncResp, connectionName, path);
- }
- }
+ }
+ });
});
- });
BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/")
.privileges(redfish::privileges::patchManager)
@@ -2246,26 +2305,27 @@ inline void requestRoutesManager(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& managerId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "Manager", managerId);
- return;
- }
+ if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "Manager",
+ managerId);
+ return;
+ }
- std::optional<std::string> activeSoftwareImageOdataId;
- std::optional<std::string> datetime;
- std::optional<nlohmann::json::object_t> pidControllers;
- std::optional<nlohmann::json::object_t> fanControllers;
- std::optional<nlohmann::json::object_t> fanZones;
- std::optional<nlohmann::json::object_t> stepwiseControllers;
- std::optional<std::string> profile;
+ std::optional<std::string> activeSoftwareImageOdataId;
+ std::optional<std::string> datetime;
+ std::optional<nlohmann::json::object_t> pidControllers;
+ std::optional<nlohmann::json::object_t> fanControllers;
+ std::optional<nlohmann::json::object_t> fanZones;
+ std::optional<nlohmann::json::object_t> stepwiseControllers;
+ std::optional<std::string> profile;
- // clang-format off
+ // clang-format off
if (!json_util::readJsonPatch(req, asyncResp->res,
"DateTime", datetime,
"Links/ActiveSoftwareImage/@odata.id", activeSoftwareImageOdataId,
@@ -2278,56 +2338,60 @@ inline void requestRoutesManager(App& app)
{
return;
}
- // clang-format on
+ // clang-format on
- if (pidControllers || fanControllers || fanZones ||
- stepwiseControllers || profile)
- {
- if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA)
- {
- std::vector<std::pair<std::string,
- std::optional<nlohmann::json::object_t>>>
- configuration;
- if (pidControllers)
+ if (pidControllers || fanControllers || fanZones ||
+ stepwiseControllers || profile)
{
- configuration.emplace_back("PidControllers",
- std::move(pidControllers));
- }
- if (fanControllers)
- {
- configuration.emplace_back("FanControllers",
- std::move(fanControllers));
+ if constexpr (BMCWEB_REDFISH_OEM_MANAGER_FAN_DATA)
+ {
+ std::vector<
+ std::pair<std::string,
+ std::optional<nlohmann::json::object_t>>>
+ configuration;
+ if (pidControllers)
+ {
+ configuration.emplace_back(
+ "PidControllers", std::move(pidControllers));
+ }
+ if (fanControllers)
+ {
+ configuration.emplace_back(
+ "FanControllers", std::move(fanControllers));
+ }
+ if (fanZones)
+ {
+ configuration.emplace_back("FanZones",
+ std::move(fanZones));
+ }
+ if (stepwiseControllers)
+ {
+ configuration.emplace_back(
+ "StepwiseControllers",
+ std::move(stepwiseControllers));
+ }
+ auto pid = std::make_shared<SetPIDValues>(
+ asyncResp, std::move(configuration), profile);
+ pid->run();
+ }
+ else
+ {
+ messages::propertyUnknown(asyncResp->res, "Oem");
+ return;
+ }
}
- if (fanZones)
+
+ if (activeSoftwareImageOdataId)
{
- configuration.emplace_back("FanZones", std::move(fanZones));
+ setActiveFirmwareImage(asyncResp,
+ *activeSoftwareImageOdataId);
}
- if (stepwiseControllers)
+
+ if (datetime)
{
- configuration.emplace_back("StepwiseControllers",
- std::move(stepwiseControllers));
+ setDateTime(asyncResp, *datetime);
}
- auto pid = std::make_shared<SetPIDValues>(
- asyncResp, std::move(configuration), profile);
- pid->run();
- }
- else
- {
- messages::propertyUnknown(asyncResp->res, "Oem");
- return;
- }
- }
-
- if (activeSoftwareImageOdataId)
- {
- setActiveFirmwareImage(asyncResp, *activeSoftwareImageOdataId);
- }
-
- if (datetime)
- {
- setDateTime(asyncResp, *datetime);
- }
- });
+ });
}
inline void requestRoutesManagerCollection(App& app)
@@ -2337,22 +2401,22 @@ inline void requestRoutesManagerCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
- asyncResp->res.jsonValue["@odata.type"] =
- "#ManagerCollection.ManagerCollection";
- asyncResp->res.jsonValue["Name"] = "Manager Collection";
- asyncResp->res.jsonValue["Members@odata.count"] = 1;
- nlohmann::json::array_t members;
- nlohmann::json& bmc = members.emplace_back();
- bmc["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
- BMCWEB_REDFISH_MANAGER_URI_NAME);
- asyncResp->res.jsonValue["Members"] = std::move(members);
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ // Collections don't include the static data added by SubRoute
+ // because it has a duplicate entry for members
+ asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ManagerCollection.ManagerCollection";
+ asyncResp->res.jsonValue["Name"] = "Manager Collection";
+ asyncResp->res.jsonValue["Members@odata.count"] = 1;
+ nlohmann::json::array_t members;
+ nlohmann::json& bmc = members.emplace_back();
+ bmc["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME);
+ asyncResp->res.jsonValue["Members"] = std::move(members);
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/memory.hpp b/redfish-core/lib/memory.hpp
index c77a5346a6..eb5fb2312c 100644
--- a/redfish-core/lib/memory.hpp
+++ b/redfish-core/lib/memory.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -19,6 +19,8 @@
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/memory.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
@@ -368,39 +370,45 @@ inline void getPersistentMemoryProperties(
if (dataLockCapable != nullptr)
{
- asyncResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
- ["DataLockCapable"] = *dataLockCapable;
+ asyncResp->res
+ .jsonValue[jsonPtr]["SecurityCapabilities"]["DataLockCapable"] =
+ *dataLockCapable;
}
if (passphraseCapable != nullptr)
{
- asyncResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
- ["PassphraseCapable"] = *passphraseCapable;
+ asyncResp->res
+ .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseCapable"] =
+ *passphraseCapable;
}
if (maxPassphraseCount != nullptr)
{
- asyncResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
- ["MaxPassphraseCount"] = *maxPassphraseCount;
+ asyncResp->res
+ .jsonValue[jsonPtr]["SecurityCapabilities"]["MaxPassphraseCount"] =
+ *maxPassphraseCount;
}
if (passphraseLockLimit != nullptr)
{
- asyncResp->res.jsonValue[jsonPtr]["SecurityCapabilities"]
- ["PassphraseLockLimit"] = *passphraseLockLimit;
+ asyncResp->res
+ .jsonValue[jsonPtr]["SecurityCapabilities"]["PassphraseLockLimit"] =
+ *passphraseLockLimit;
}
}
-inline void
- assembleDimmProperties(std::string_view dimmId,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const dbus::utility::DBusPropertiesMap& properties,
- const nlohmann::json::json_pointer& jsonPtr)
+inline void assembleDimmProperties(
+ std::string_view dimmId,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const dbus::utility::DBusPropertiesMap& properties,
+ const nlohmann::json::json_pointer& jsonPtr)
{
asyncResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
asyncResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
- asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
+ resource::State::Enabled;
+ asyncResp->res.jsonValue[jsonPtr]["Status"]["Health"] =
+ resource::Health::OK;
const uint16_t* memoryDataWidth = nullptr;
const size_t* memorySizeInKB = nullptr;
@@ -477,7 +485,8 @@ inline void
if (present != nullptr && !*present)
{
- asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
+ asyncResp->res.jsonValue[jsonPtr]["Status"]["State"] =
+ resource::State::Absent;
}
if (memoryTotalWidth != nullptr)
@@ -552,11 +561,13 @@ inline void
}
if (memoryType->find("DDR") != std::string::npos)
{
- asyncResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
+ asyncResp->res.jsonValue[jsonPtr]["MemoryType"] =
+ memory::MemoryType::DRAM;
}
else if (memoryType->ends_with("Logical"))
{
- asyncResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
+ asyncResp->res.jsonValue[jsonPtr]["MemoryType"] =
+ memory::MemoryType::IntelOptane;
}
}
@@ -568,8 +579,9 @@ inline void
if (memoryController != nullptr)
{
- asyncResp->res.jsonValue[jsonPtr]["MemoryLocation"]
- ["MemoryController"] = *memoryController;
+ asyncResp->res
+ .jsonValue[jsonPtr]["MemoryLocation"]["MemoryController"] =
+ *memoryController;
}
if (slot != nullptr)
@@ -594,17 +606,17 @@ inline void
if (locationCode != nullptr)
{
- asyncResp->res.jsonValue[jsonPtr]["Location"]["PartLocation"]
- ["ServiceLabel"] = *locationCode;
+ asyncResp->res
+ .jsonValue[jsonPtr]["Location"]["PartLocation"]["ServiceLabel"] =
+ *locationCode;
}
getPersistentMemoryProperties(asyncResp, properties, jsonPtr);
}
-inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
- const std::string& dimmId,
- const std::string& service,
- const std::string& objPath)
+inline void getDimmDataByService(
+ std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& dimmId,
+ const std::string& service, const std::string& objPath)
{
BMCWEB_LOG_DEBUG("Get available system components.");
sdbusplus::asio::getAllProperties(
@@ -612,14 +624,15 @@ inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[dimmId, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
- assembleDimmProperties(dimmId, asyncResp, properties, ""_json_pointer);
- });
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ assembleDimmProperties(dimmId, asyncResp, properties,
+ ""_json_pointer);
+ });
}
inline void assembleDimmPartitionData(
@@ -685,16 +698,16 @@ inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
- return;
+ return;
+ }
+ nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
+ assembleDimmPartitionData(asyncResp, properties, regionPtr);
}
- nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
- assembleDimmPartitionData(asyncResp, properties, regionPtr);
- }
);
}
@@ -711,57 +724,57 @@ inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[dimmId, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
- return;
- }
- bool found = false;
- for (const auto& [rawPath, object] : subtree)
- {
- sdbusplus::message::object_path path(rawPath);
- for (const auto& [service, interfaces] : object)
+ return;
+ }
+ bool found = false;
+ for (const auto& [rawPath, object] : subtree)
{
- for (const auto& interface : interfaces)
+ sdbusplus::message::object_path path(rawPath);
+ for (const auto& [service, interfaces] : object)
{
- if (interface ==
- "xyz.openbmc_project.Inventory.Item.Dimm" &&
- path.filename() == dimmId)
- {
- getDimmDataByService(asyncResp, dimmId, service,
- rawPath);
- found = true;
- }
-
- // partitions are separate as there can be multiple
- // per
- // device, i.e.
- // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
- // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
- if (interface ==
- "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
- path.parent_path().filename() == dimmId)
+ for (const auto& interface : interfaces)
{
- getDimmPartitionData(asyncResp, service, rawPath);
+ if (interface ==
+ "xyz.openbmc_project.Inventory.Item.Dimm" &&
+ path.filename() == dimmId)
+ {
+ getDimmDataByService(asyncResp, dimmId, service,
+ rawPath);
+ found = true;
+ }
+
+ // partitions are separate as there can be multiple
+ // per
+ // device, i.e.
+ // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition1
+ // /xyz/openbmc_project/Inventory/Item/Dimm1/Partition2
+ if (interface ==
+ "xyz.openbmc_project.Inventory.Item.PersistentMemory.Partition" &&
+ path.parent_path().filename() == dimmId)
+ {
+ getDimmPartitionData(asyncResp, service, rawPath);
+ }
}
}
}
- }
- // Object not found
- if (!found)
- {
- messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
+ // Object not found
+ if (!found)
+ {
+ messages::resourceNotFound(asyncResp->res, "Memory", dimmId);
+ return;
+ }
+ // Set @odata only if object is found
+ asyncResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
+ asyncResp->res.jsonValue["@odata.id"] =
+ boost::urls::format("/redfish/v1/Systems/{}/Memory/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, dimmId);
return;
- }
- // Set @odata only if object is found
- asyncResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Systems/{}/Memory/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, dimmId);
- return;
- });
+ });
}
inline void requestRoutesMemoryCollection(App& app)
@@ -775,38 +788,39 @@ inline void requestRoutesMemoryCollection(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- asyncResp->res.jsonValue["@odata.type"] =
- "#MemoryCollection.MemoryCollection";
- asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/Memory", BMCWEB_REDFISH_SYSTEM_URI_NAME);
-
- constexpr std::array<std::string_view, 1> interfaces{
- "xyz.openbmc_project.Inventory.Item.Dimm"};
- collection_util::getCollectionMembers(
- asyncResp,
- boost::urls::format("/redfish/v1/Systems/{}/Memory",
- BMCWEB_REDFISH_SYSTEM_URI_NAME),
- interfaces, "/xyz/openbmc_project/inventory");
- });
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#MemoryCollection.MemoryCollection";
+ asyncResp->res.jsonValue["Name"] = "Memory Module Collection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ boost::urls::format("/redfish/v1/Systems/{}/Memory",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+
+ constexpr std::array<std::string_view, 1> interfaces{
+ "xyz.openbmc_project.Inventory.Item.Dimm"};
+ collection_util::getCollectionMembers(
+ asyncResp,
+ boost::urls::format("/redfish/v1/Systems/{}/Memory",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME),
+ interfaces, "/xyz/openbmc_project/inventory");
+ });
}
inline void requestRoutesMemory(App& app)
@@ -820,28 +834,28 @@ inline void requestRoutesMemory(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName, const std::string& dimmId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- getDimmData(asyncResp, dimmId);
- });
+ getDimmData(asyncResp, dimmId);
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp
index 94588ac1ca..c41b144023 100644
--- a/redfish-core/lib/message_registries.hpp
+++ b/redfish-core/lib/message_registries.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2019 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2019 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -56,8 +56,8 @@ inline void handleMessageRegistryFileCollectionGet(
{"Base", "TaskEvent", "ResourceEvent", "OpenBMC", "Telemetry"}))
{
nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format("/redfish/v1/Registries/{}",
- memberName);
+ member["@odata.id"] =
+ boost::urls::format("/redfish/v1/Registries/{}", memberName);
members.emplace_back(std::move(member));
}
}
@@ -123,8 +123,8 @@ inline void handleMessageRoutesMessageRegistryFileGet(
asyncResp->res.jsonValue["@odata.type"] =
"#MessageRegistryFile.v1_1_0.MessageRegistryFile";
asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
- asyncResp->res.jsonValue["Description"] = dmtf + registry +
- " Message Registry File Location";
+ asyncResp->res.jsonValue["Description"] =
+ dmtf + registry + " Message Registry File Location";
asyncResp->res.jsonValue["Id"] = header->registryPrefix;
asyncResp->res.jsonValue["Registry"] = header->id;
nlohmann::json::array_t languages;
diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
index 3eb692776c..c47ba13181 100644
--- a/redfish-core/lib/metric_report.hpp
+++ b/redfish-core/lib/metric_report.hpp
@@ -65,24 +65,25 @@ inline void requestRoutesMetricReportCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#MetricReportCollection.MetricReportCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/TelemetryService/MetricReports";
- asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
- constexpr std::array<std::string_view, 1> interfaces{
- telemetry::reportInterface};
- collection_util::getCollectionMembers(
- asyncResp,
- boost::urls::url("/redfish/v1/TelemetryService/MetricReports"),
- interfaces,
- "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#MetricReportCollection.MetricReportCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReports";
+ asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
+ constexpr std::array<std::string_view, 1> interfaces{
+ telemetry::reportInterface};
+ collection_util::getCollectionMembers(
+ asyncResp,
+ boost::urls::url(
+ "/redfish/v1/TelemetryService/MetricReports"),
+ interfaces,
+ "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
+ });
}
inline void requestRoutesMetricReport(App& app)
@@ -93,43 +94,49 @@ inline void requestRoutesMetricReport(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& id) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- const std::string reportPath = telemetry::getDbusReportPath(id);
- crow::connections::systemBus->async_method_call(
- [asyncResp, id, reportPath](const boost::system::error_code& ec) {
- if (ec.value() == EBADR ||
- ec == boost::system::errc::host_unreachable)
- {
- messages::resourceNotFound(asyncResp->res, "MetricReport", id);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- sdbusplus::asio::getProperty<telemetry::TimestampReadings>(
- *crow::connections::systemBus, telemetry::service, reportPath,
- telemetry::reportInterface, "Readings",
- [asyncResp, id](const boost::system::error_code& ec2,
- const telemetry::TimestampReadings& ret) {
- if (ec2)
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec2);
- messages::internalError(asyncResp->res);
return;
}
-
- telemetry::fillReport(asyncResp->res.jsonValue, id, ret);
+ const std::string reportPath = telemetry::getDbusReportPath(id);
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id,
+ reportPath](const boost::system::error_code& ec) {
+ if (ec.value() == EBADR ||
+ ec == boost::system::errc::host_unreachable)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "MetricReport", id);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ sdbusplus::asio::getProperty<
+ telemetry::TimestampReadings>(
+ *crow::connections::systemBus, telemetry::service,
+ reportPath, telemetry::reportInterface, "Readings",
+ [asyncResp,
+ id](const boost::system::error_code& ec2,
+ const telemetry::TimestampReadings& ret) {
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "respHandler DBus error {}", ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ telemetry::fillReport(asyncResp->res.jsonValue,
+ id, ret);
+ });
+ },
+ telemetry::service, reportPath, telemetry::reportInterface,
+ "Update");
});
- },
- telemetry::service, reportPath, telemetry::reportInterface,
- "Update");
- });
}
} // namespace redfish
diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
index 36f2334638..d92343d0fe 100644
--- a/redfish-core/lib/metric_report_definition.hpp
+++ b/redfish-core/lib/metric_report_definition.hpp
@@ -3,6 +3,7 @@
#include "app.hpp"
#include "dbus_utility.hpp"
#include "generated/enums/metric_report_definition.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "sensors.hpp"
@@ -245,10 +246,9 @@ inline std::optional<nlohmann::json::array_t> getLinkedTriggers(
return triggers;
}
-inline void
- fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& id,
- const dbus::utility::DBusPropertiesMap& properties)
+inline void fillReportDefinition(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
+ const dbus::utility::DBusPropertiesMap& properties)
{
std::vector<std::string> reportActions;
ReadingParameters readingParams;
@@ -356,11 +356,11 @@ inline void
if (enabled)
{
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
}
else
{
- asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Disabled;
}
metric_report_definition::ReportUpdatesEnum redfishReportUpdates =
@@ -641,22 +641,120 @@ inline bool getChassisSensorNodeFromMetrics(
getChassisSensorNode(metric.uris, matched);
if (error)
{
- messages::propertyValueIncorrect(asyncResp->res, error->uri,
- "MetricProperties/" +
- std::to_string(error->index));
+ messages::propertyValueIncorrect(
+ asyncResp->res, error->uri,
+ "MetricProperties/" + std::to_string(error->index));
+ return false;
+ }
+ }
+ return true;
+}
+
+inline std::string toRedfishProperty(std::string_view dbusMessage)
+{
+ if (dbusMessage == "Id")
+ {
+ return "Id";
+ }
+ if (dbusMessage == "Name")
+ {
+ return "Name";
+ }
+ if (dbusMessage == "ReportingType")
+ {
+ return "MetricReportDefinitionType";
+ }
+ if (dbusMessage == "AppendLimit")
+ {
+ return "AppendLimit";
+ }
+ if (dbusMessage == "ReportActions")
+ {
+ return "ReportActions";
+ }
+ if (dbusMessage == "Interval")
+ {
+ return "RecurrenceInterval";
+ }
+ if (dbusMessage == "ReportUpdates")
+ {
+ return "ReportUpdates";
+ }
+ if (dbusMessage == "ReadingParameters")
+ {
+ return "Metrics";
+ }
+ return "";
+}
+
+inline bool handleParamError(crow::Response& res, const char* errorMessage,
+ std::string_view key)
+{
+ if (errorMessage == nullptr)
+ {
+ BMCWEB_LOG_ERROR("errorMessage was null");
+ return true;
+ }
+ std::string_view errorMessageSv(errorMessage);
+ if (errorMessageSv.starts_with(key))
+ {
+ std::string redfishProperty = toRedfishProperty(key);
+ if (redfishProperty.empty())
+ {
+ // Getting here means most possibly that toRedfishProperty has
+ // incomplete implementation. Return internal error for now.
+ BMCWEB_LOG_ERROR("{} has no corresponding Redfish property", key);
+ messages::internalError(res);
return false;
}
+ messages::propertyValueError(res, redfishProperty);
+ return false;
}
+
return true;
}
+inline void afterAddReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const AddReportArgs& args,
+ const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg)
+{
+ if (!ec)
+ {
+ messages::created(asyncResp->res);
+ return;
+ }
+
+ if (ec == boost::system::errc::invalid_argument)
+ {
+ const sd_bus_error* errorMessage = msg.get_error();
+ if (errorMessage != nullptr)
+ {
+ for (const auto& arg :
+ {"Id", "Name", "ReportingType", "AppendLimit", "ReportActions",
+ "Interval", "ReportUpdates", "ReadingParameters"})
+ {
+ if (!handleParamError(asyncResp->res, errorMessage->message,
+ arg))
+ {
+ return;
+ }
+ }
+ }
+ }
+ if (!verifyCommonErrors(asyncResp->res, args.id, ec))
+ {
+ return;
+ }
+ messages::internalError(asyncResp->res);
+}
+
class AddReport
{
public:
AddReport(AddReportArgs&& argsIn,
const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
- asyncResp(asyncRespIn),
- args(std::move(argsIn))
+ asyncResp(asyncRespIn), args(std::move(argsIn))
{}
~AddReport()
@@ -695,9 +793,9 @@ class AddReport
BMCWEB_LOG_ERROR(
"Failed to find DBus sensor corresponding to URI {}",
uri);
- messages::propertyValueNotInList(asyncResp->res, uri,
- "MetricProperties/" +
- std::to_string(i));
+ messages::propertyValueNotInList(
+ asyncResp->res, uri,
+ "MetricProperties/" + std::to_string(i));
return;
}
@@ -709,41 +807,12 @@ class AddReport
std::move(sensorParams), metric.collectionFunction,
metric.collectionTimeScope, metric.collectionDuration);
}
-
crow::connections::systemBus->async_method_call(
- [asyncResp, id = args.id, uriToDbus](
- const boost::system::error_code& ec, const std::string&) {
- if (ec == boost::system::errc::file_exists)
- {
- messages::resourceAlreadyExists(
- asyncResp->res, "MetricReportDefinition", "Id", id);
- return;
- }
- if (ec == boost::system::errc::too_many_files_open)
- {
- messages::createLimitReachedForResource(asyncResp->res);
- return;
- }
- if (ec == boost::system::errc::argument_list_too_long)
- {
- nlohmann::json metricProperties = nlohmann::json::array();
- for (const auto& [uri, _] : uriToDbus)
- {
- metricProperties.emplace_back(uri);
- }
- messages::propertyValueIncorrect(
- asyncResp->res, "MetricProperties", metricProperties);
- return;
- }
- if (ec)
- {
- messages::internalError(asyncResp->res);
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
- return;
- }
-
- messages::created(asyncResp->res);
- },
+ [asyncResp, args](const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg,
+ const std::string& /*arg1*/) {
+ afterAddReport(asyncResp, args, ec, msg);
+ },
telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
"xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
"TelemetryService/" + args.id, args.name, args.reportingType,
@@ -762,36 +831,128 @@ class AddReport
}
private:
- std::shared_ptr<bmcweb::AsyncResp> asyncResp;
+ const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
AddReportArgs args;
boost::container::flat_map<std::string, std::string> uriToDbus;
};
-class UpdateMetrics
+inline std::optional<
+ std::vector<std::tuple<sdbusplus::message::object_path, std::string>>>
+ sensorPathToUri(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ std::span<const std::string> uris,
+ const std::map<std::string, std::string>& metricPropertyToDbusPaths)
{
- public:
- UpdateMetrics(std::string_view idIn,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
- id(idIn),
- asyncResp(asyncRespIn)
- {}
+ std::vector<std::tuple<sdbusplus::message::object_path, std::string>>
+ result;
- ~UpdateMetrics()
+ for (const std::string& uri : uris)
{
- try
+ auto it = metricPropertyToDbusPaths.find(uri);
+ if (it == metricPropertyToDbusPaths.end())
{
- setReadingParams();
+ messages::propertyValueNotInList(asyncResp->res, uri,
+ "MetricProperties");
+ return {};
}
- catch (const std::exception& e)
+ result.emplace_back(it->second, uri);
+ }
+
+ return result;
+}
+
+inline void afterSetReadingParams(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& reportId, const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg)
+{
+ if (!ec)
+ {
+ messages::success(asyncResp->res);
+ return;
+ }
+ if (ec == boost::system::errc::invalid_argument)
+ {
+ const sd_bus_error* errorMessage = msg.get_error();
+ if (errorMessage != nullptr)
{
- BMCWEB_LOG_ERROR("{}", e.what());
+ for (const auto& arg : {"Id", "ReadingParameters"})
+ {
+ if (!handleParamError(asyncResp->res, errorMessage->message,
+ arg))
+ {
+ return;
+ }
+ }
}
- catch (...)
+ }
+ if (!verifyCommonErrors(asyncResp->res, reportId, ec))
+ {
+ return;
+ }
+ messages::internalError(asyncResp->res);
+}
+
+inline void setReadingParams(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& reportId, ReadingParameters readingParams,
+ const std::vector<std::vector<std::string>>& readingParamsUris,
+ const std::map<std::string, std::string>& metricPropertyToDbusPaths)
+{
+ if (asyncResp->res.result() != boost::beast::http::status::ok)
+ {
+ return;
+ }
+
+ for (size_t index = 0; index < readingParamsUris.size(); ++index)
+ {
+ std::span<const std::string> newUris = readingParamsUris[index];
+
+ const std::optional<std::vector<
+ std::tuple<sdbusplus::message::object_path, std::string>>>
+ readingParam =
+ sensorPathToUri(asyncResp, newUris, metricPropertyToDbusPaths);
+
+ if (!readingParam)
+ {
+ return;
+ }
+
+ for (const std::tuple<sdbusplus::message::object_path, std::string>&
+ value : *readingParam)
{
- BMCWEB_LOG_ERROR("Unknown error");
+ std::get<0>(readingParams[index]).emplace_back(value);
}
}
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, reportId](const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg) {
+ afterSetReadingParams(asyncResp, reportId, ec, msg);
+ },
+ "xyz.openbmc_project.Telemetry", getDbusReportPath(reportId),
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Telemetry.Report", "ReadingParameters",
+ dbus::utility::DbusVariantType{readingParams});
+}
+
+class UpdateMetrics
+{
+ public:
+ UpdateMetrics(std::string_view idIn,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
+ id(idIn), asyncResp(asyncRespIn)
+ {}
+
+ ~UpdateMetrics()
+ {
+ boost::asio::post(
+ crow::connections::systemBus->get_io_context(),
+ std::bind_front(&setReadingParams, asyncResp, id,
+ std::move(readingParams), readingParamsUris,
+ metricPropertyToDbusPaths));
+ }
+
UpdateMetrics(const UpdateMetrics&) = delete;
UpdateMetrics(UpdateMetrics&&) = delete;
UpdateMetrics& operator=(const UpdateMetrics&) = delete;
@@ -808,10 +969,11 @@ class UpdateMetrics
additionalMetricPropertyToDbusPaths.end());
}
- void emplace(std::span<const std::tuple<sdbusplus::message::object_path,
- std::string>>
- pathAndUri,
- const AddReportArgs::MetricArgs& metricArgs)
+ void emplace(
+ std::span<
+ const std::tuple<sdbusplus::message::object_path, std::string>>
+ pathAndUri,
+ const AddReportArgs::MetricArgs& metricArgs)
{
readingParamsUris.emplace_back(metricArgs.uris);
readingParams.emplace_back(
@@ -820,66 +982,7 @@ class UpdateMetrics
metricArgs.collectionDuration);
}
- void setReadingParams()
- {
- if (asyncResp->res.result() != boost::beast::http::status::ok)
- {
- return;
- }
-
- for (size_t index = 0; index < readingParamsUris.size(); ++index)
- {
- std::span<const std::string> newUris = readingParamsUris[index];
-
- const std::optional<std::vector<
- std::tuple<sdbusplus::message::object_path, std::string>>>
- readingParam = sensorPathToUri(newUris);
-
- if (!readingParam)
- {
- return;
- }
-
- std::get<0>(readingParams[index]) = *readingParam;
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp(this->asyncResp),
- reportId = id](const boost::system::error_code& ec) {
- if (!verifyCommonErrors(asyncResp->res, reportId, ec))
- {
- return;
- }
- },
- "xyz.openbmc_project.Telemetry", getDbusReportPath(id),
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Telemetry.Report", "ReadingParameters",
- dbus::utility::DbusVariantType{readingParams});
- }
-
private:
- std::optional<
- std::vector<std::tuple<sdbusplus::message::object_path, std::string>>>
- sensorPathToUri(std::span<const std::string> uris) const
- {
- std::vector<std::tuple<sdbusplus::message::object_path, std::string>>
- result;
-
- for (const std::string& uri : uris)
- {
- auto it = metricPropertyToDbusPaths.find(uri);
- if (it == metricPropertyToDbusPaths.end())
- {
- messages::propertyValueNotInList(asyncResp->res, uri,
- "MetricProperties");
- return {};
- }
- result.emplace_back(it->second, uri);
- }
-
- return result;
- }
-
const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
std::vector<std::vector<std::string>> readingParamsUris;
ReadingParameters readingParams;
@@ -891,160 +994,282 @@ inline void
{
crow::connections::systemBus->async_method_call(
[asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
- if (!verifyCommonErrors(asyncResp->res, id, ec))
- {
- return;
- }
- },
+ if (!verifyCommonErrors(asyncResp->res, id, ec))
+ {
+ return;
+ }
+ },
"xyz.openbmc_project.Telemetry", getDbusReportPath(id),
"org.freedesktop.DBus.Properties", "Set",
"xyz.openbmc_project.Telemetry.Report", "Enabled",
dbus::utility::DbusVariantType{enabled});
}
+inline void afterSetReportingProperties(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
+ const boost::system::error_code& ec, const sdbusplus::message_t& msg)
+{
+ if (!ec)
+ {
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ return;
+ }
+
+ if (ec == boost::system::errc::invalid_argument)
+ {
+ const sd_bus_error* errorMessage = msg.get_error();
+ if (errorMessage != nullptr)
+ {
+ for (const auto& arg : {"Id", "ReportingType", "Interval"})
+ {
+ if (!handleParamError(asyncResp->res, errorMessage->message,
+ arg))
+ {
+ return;
+ }
+ }
+ }
+ }
+ if (!verifyCommonErrors(asyncResp->res, id, ec))
+ {
+ return;
+ }
+ messages::internalError(asyncResp->res);
+}
+
inline void setReportTypeAndInterval(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
- const std::string& reportingType, uint64_t recurrenceInterval)
+ const std::optional<std::string>& reportingType,
+ const std::optional<std::string>& recurrenceIntervalStr)
{
- crow::connections::systemBus->async_method_call(
- [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
- if (!verifyCommonErrors(asyncResp->res, id, ec))
+ std::string dbusReportingType;
+ if (reportingType)
+ {
+ dbusReportingType = toDbusReportingType(*reportingType);
+ if (dbusReportingType.empty())
{
+ messages::propertyValueNotInList(asyncResp->res, *reportingType,
+ "MetricReportDefinitionType");
return;
}
- },
+ }
+
+ uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max();
+ if (recurrenceIntervalStr)
+ {
+ std::optional<std::chrono::milliseconds> durationNum =
+ time_utils::fromDurationString(*recurrenceIntervalStr);
+ if (!durationNum || durationNum->count() < 0)
+ {
+ messages::propertyValueIncorrect(
+ asyncResp->res, "RecurrenceInterval", *recurrenceIntervalStr);
+ return;
+ }
+
+ recurrenceInterval = static_cast<uint64_t>(durationNum->count());
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id = std::string(id)](const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg) {
+ afterSetReportingProperties(asyncResp, id, ec, msg);
+ },
"xyz.openbmc_project.Telemetry", getDbusReportPath(id),
"xyz.openbmc_project.Telemetry.Report", "SetReportingProperties",
- reportingType, recurrenceInterval);
+ dbusReportingType, recurrenceInterval);
+}
+
+inline void afterSetReportUpdates(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
+ const boost::system::error_code& ec, const sdbusplus::message_t& msg)
+{
+ if (!ec)
+ {
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ return;
+ }
+ if (ec == boost::system::errc::invalid_argument)
+ {
+ const sd_bus_error* errorMessage = msg.get_error();
+ if (errorMessage != nullptr)
+ {
+ for (const auto& arg : {"Id", "ReportUpdates"})
+ {
+ if (!handleParamError(asyncResp->res, errorMessage->message,
+ arg))
+ {
+ return;
+ }
+ }
+ }
+ }
+ if (!verifyCommonErrors(asyncResp->res, id, ec))
+ {
+ return;
+ }
}
inline void
setReportUpdates(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
std::string_view id, const std::string& reportUpdates)
{
+ std::string dbusReportUpdates = toDbusReportUpdates(reportUpdates);
+ if (dbusReportUpdates.empty())
+ {
+ messages::propertyValueNotInList(asyncResp->res, reportUpdates,
+ "ReportUpdates");
+ return;
+ }
crow::connections::systemBus->async_method_call(
- [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
- if (!verifyCommonErrors(asyncResp->res, id, ec))
- {
- return;
- }
- },
+ [asyncResp, id = std::string(id)](const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg) {
+ afterSetReportUpdates(asyncResp, id, ec, msg);
+ },
"xyz.openbmc_project.Telemetry", getDbusReportPath(id),
"org.freedesktop.DBus.Properties", "Set",
"xyz.openbmc_project.Telemetry.Report", "ReportUpdates",
- dbus::utility::DbusVariantType{reportUpdates});
+ dbus::utility::DbusVariantType{dbusReportUpdates});
}
-inline void
- setReportActions(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- std::string_view id,
- const std::vector<std::string>& dbusReportActions)
+inline void afterSetReportActions(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
+ const boost::system::error_code& ec, const sdbusplus::message_t& msg)
{
- crow::connections::systemBus->async_method_call(
- [asyncResp, id = std::string(id)](const boost::system::error_code& ec) {
- if (!verifyCommonErrors(asyncResp->res, id, ec))
+ if (ec == boost::system::errc::invalid_argument)
+ {
+ const sd_bus_error* errorMessage = msg.get_error();
+ if (errorMessage != nullptr)
{
- return;
+ for (const auto& arg : {"Id", "ReportActions"})
+ {
+ if (!handleParamError(asyncResp->res, errorMessage->message,
+ arg))
+ {
+ return;
+ }
+ }
}
- },
+ }
+
+ if (!verifyCommonErrors(asyncResp->res, id, ec))
+ {
+ return;
+ }
+
+ messages::internalError(asyncResp->res);
+}
+
+inline void setReportActions(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
+ const std::vector<std::string>& reportActions)
+{
+ std::vector<std::string> dbusReportActions;
+ if (!toDbusReportActions(asyncResp->res, reportActions, dbusReportActions))
+ {
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id = std::string(id)](const boost::system::error_code& ec,
+ const sdbusplus::message_t& msg) {
+ afterSetReportActions(asyncResp, id, ec, msg);
+ },
"xyz.openbmc_project.Telemetry", getDbusReportPath(id),
"org.freedesktop.DBus.Properties", "Set",
"xyz.openbmc_project.Telemetry.Report", "ReportActions",
dbus::utility::DbusVariantType{dbusReportActions});
}
-inline void
- setReportMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- std::string_view id,
- std::span<nlohmann::json::object_t> metrics)
+inline void setReportMetrics(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id,
+ std::vector<nlohmann::json::object_t>&& metrics)
{
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, telemetry::service,
telemetry::getDbusReportPath(id), telemetry::reportInterface,
- [asyncResp, id = std::string(id),
- redfishMetrics = std::vector<nlohmann::json::object_t>(metrics.begin(),
- metrics.end())](
+ [asyncResp, id = std::string(id), redfishMetrics = std::move(metrics)](
boost::system::error_code ec,
const dbus::utility::DBusPropertiesMap& properties) mutable {
- if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec))
- {
- return;
- }
-
- ReadingParameters readingParams;
+ if (!verifyCommonErrors(asyncResp->res, id, ec))
+ {
+ return;
+ }
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "ReadingParameters",
- readingParams);
+ ReadingParameters readingParams;
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties,
+ "ReadingParameters", readingParams);
- auto updateMetricsReq = std::make_shared<UpdateMetrics>(id, asyncResp);
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- boost::container::flat_set<std::pair<std::string, std::string>>
- chassisSensors;
+ auto updateMetricsReq =
+ std::make_shared<UpdateMetrics>(id, asyncResp);
- size_t index = 0;
- for (nlohmann::json::object_t& metric : redfishMetrics)
- {
- AddReportArgs::MetricArgs metricArgs;
- std::vector<
- std::tuple<sdbusplus::message::object_path, std::string>>
- pathAndUri;
+ boost::container::flat_set<std::pair<std::string, std::string>>
+ chassisSensors;
- if (index < readingParams.size())
+ size_t index = 0;
+ for (nlohmann::json::object_t& metric : redfishMetrics)
{
- const ReadingParameters::value_type& existing =
- readingParams[index];
-
- pathAndUri = std::get<0>(existing);
- metricArgs.collectionFunction = std::get<1>(existing);
- metricArgs.collectionTimeScope = std::get<2>(existing);
- metricArgs.collectionDuration = std::get<3>(existing);
- }
+ AddReportArgs::MetricArgs metricArgs;
+ std::vector<
+ std::tuple<sdbusplus::message::object_path, std::string>>
+ pathAndUri;
- if (!getUserMetric(asyncResp->res, metric, metricArgs))
- {
- return;
- }
+ if (index < readingParams.size())
+ {
+ const ReadingParameters::value_type& existing =
+ readingParams[index];
- std::optional<IncorrectMetricUri> error =
- getChassisSensorNode(metricArgs.uris, chassisSensors);
+ pathAndUri = std::get<0>(existing);
+ metricArgs.collectionFunction = std::get<1>(existing);
+ metricArgs.collectionTimeScope = std::get<2>(existing);
+ metricArgs.collectionDuration = std::get<3>(existing);
+ }
- if (error)
- {
- messages::propertyValueIncorrect(
- asyncResp->res, error->uri,
- "MetricProperties/" + std::to_string(error->index));
- return;
- }
+ if (!getUserMetric(asyncResp->res, metric, metricArgs))
+ {
+ return;
+ }
- updateMetricsReq->emplace(pathAndUri, metricArgs);
- index++;
- }
+ std::optional<IncorrectMetricUri> error =
+ getChassisSensorNode(metricArgs.uris, chassisSensors);
- for (const auto& [chassis, sensorType] : chassisSensors)
- {
- retrieveUriToDbusMap(
- chassis, sensorType,
- [asyncResp, updateMetricsReq](
- const boost::beast::http::status status,
- const std::map<std::string, std::string>& uriToDbus) {
- if (status != boost::beast::http::status::ok)
+ if (error)
{
- BMCWEB_LOG_ERROR(
- "Failed to retrieve URI to dbus sensors map with err {}",
- static_cast<unsigned>(status));
+ messages::propertyValueIncorrect(
+ asyncResp->res, error->uri,
+ "MetricProperties/" + std::to_string(error->index));
return;
}
- updateMetricsReq->insert(uriToDbus);
- });
- }
- });
+
+ updateMetricsReq->emplace(pathAndUri, metricArgs);
+ index++;
+ }
+
+ for (const auto& [chassis, sensorType] : chassisSensors)
+ {
+ retrieveUriToDbusMap(
+ chassis, sensorType,
+ [asyncResp, updateMetricsReq](
+ const boost::beast::http::status status,
+ const std::map<std::string, std::string>& uriToDbus) {
+ if (status != boost::beast::http::status::ok)
+ {
+ BMCWEB_LOG_ERROR(
+ "Failed to retrieve URI to dbus sensors map with err {}",
+ static_cast<unsigned>(status));
+ return;
+ }
+ updateMetricsReq->insert(uriToDbus);
+ });
+ }
+ });
}
inline void handleMetricReportDefinitionCollectionHead(
@@ -1087,10 +1312,9 @@ inline void handleMetricReportDefinitionCollectionGet(
interfaces, "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
}
-inline void
- handleReportPatch(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- std::string_view id)
+inline void handleReportPatch(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -1121,71 +1345,29 @@ inline void
if (reportUpdatesStr)
{
- std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr);
- if (dbusReportUpdates.empty())
- {
- messages::propertyValueNotInList(asyncResp->res, *reportUpdatesStr,
- "ReportUpdates");
- return;
- }
- setReportUpdates(asyncResp, id, dbusReportUpdates);
+ setReportUpdates(asyncResp, id, *reportUpdatesStr);
}
if (reportActionsStr)
{
- std::vector<std::string> dbusReportActions;
- if (!toDbusReportActions(asyncResp->res, *reportActionsStr,
- dbusReportActions))
- {
- return;
- }
- setReportActions(asyncResp, id, dbusReportActions);
+ setReportActions(asyncResp, id, *reportActionsStr);
}
if (reportingTypeStr || scheduleDurationStr)
{
- std::string dbusReportingType;
- if (reportingTypeStr)
- {
- dbusReportingType = toDbusReportingType(*reportingTypeStr);
- if (dbusReportingType.empty())
- {
- messages::propertyValueNotInList(asyncResp->res,
- *reportingTypeStr,
- "MetricReportDefinitionType");
- return;
- }
- }
-
- uint64_t recurrenceInterval = std::numeric_limits<uint64_t>::max();
- if (scheduleDurationStr)
- {
- std::optional<std::chrono::milliseconds> durationNum =
- time_utils::fromDurationString(*scheduleDurationStr);
- if (!durationNum || durationNum->count() < 0)
- {
- messages::propertyValueIncorrect(
- asyncResp->res, "RecurrenceInterval", *scheduleDurationStr);
- return;
- }
-
- recurrenceInterval = static_cast<uint64_t>(durationNum->count());
- }
-
- setReportTypeAndInterval(asyncResp, id, dbusReportingType,
- recurrenceInterval);
+ setReportTypeAndInterval(asyncResp, id, reportingTypeStr,
+ scheduleDurationStr);
}
if (metrics)
{
- setReportMetrics(asyncResp, id, *metrics);
+ setReportMetrics(asyncResp, id, std::move(*metrics));
}
}
-inline void
- handleReportDelete(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- std::string_view id)
+inline void handleReportDelete(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, std::string_view id)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -1197,12 +1379,12 @@ inline void
crow::connections::systemBus->async_method_call(
[asyncResp,
reportId = std::string(id)](const boost::system::error_code& ec) {
- if (!verifyCommonErrors(asyncResp->res, reportId, ec))
- {
- return;
- }
- asyncResp->res.result(boost::beast::http::status::no_content);
- },
+ if (!verifyCommonErrors(asyncResp->res, reportId, ec))
+ {
+ return;
+ }
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ },
service, reportPath, "xyz.openbmc_project.Object.Delete", "Delete");
}
} // namespace telemetry
@@ -1246,8 +1428,8 @@ inline void handleMetricReportDefinitionsPost(
return;
}
- auto addReportReq = std::make_shared<telemetry::AddReport>(std::move(args),
- asyncResp);
+ auto addReportReq =
+ std::make_shared<telemetry::AddReport>(std::move(args), asyncResp);
for (const auto& [chassis, sensorType] : chassisSensors)
{
retrieveUriToDbusMap(chassis, sensorType,
@@ -1270,10 +1452,9 @@ inline void
"</redfish/v1/JsonSchemas/MetricReport/MetricReport.json>; rel=describedby");
}
-inline void
- handleMetricReportGet(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& id)
+inline void handleMetricReportGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -1288,13 +1469,13 @@ inline void
telemetry::getDbusReportPath(id), telemetry::reportInterface,
[asyncResp, id](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec))
- {
- return;
- }
+ if (!redfish::telemetry::verifyCommonErrors(asyncResp->res, id, ec))
+ {
+ return;
+ }
- telemetry::fillReportDefinition(asyncResp, id, properties);
- });
+ telemetry::fillReportDefinition(asyncResp, id, properties);
+ });
}
inline void handleMetricReportDelete(
@@ -1311,26 +1492,26 @@ inline void handleMetricReportDelete(
crow::connections::systemBus->async_method_call(
[asyncResp, id](const boost::system::error_code& ec) {
- /*
- * boost::system::errc and std::errc are missing value
- * for EBADR error that is defined in Linux.
- */
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "MetricReportDefinition",
- id);
- return;
- }
+ /*
+ * boost::system::errc and std::errc are missing value
+ * for EBADR error that is defined in Linux.
+ */
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "MetricReportDefinition", id);
+ return;
+ }
- if (ec)
- {
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.result(boost::beast::http::status::no_content);
- },
+ asyncResp->res.result(boost::beast::http::status::no_content);
+ },
telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
"Delete");
}
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp
index 410c32cc4c..f5b64f8aa7 100644
--- a/redfish-core/lib/network_protocol.hpp
+++ b/redfish-core/lib/network_protocol.hpp
@@ -1,23 +1,24 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
#include "registries/privilege_registry.hpp"
@@ -32,6 +33,7 @@
#include <optional>
#include <string_view>
#include <variant>
+#include <vector>
namespace redfish
{
@@ -52,7 +54,8 @@ static constexpr std::array<std::pair<std::string_view, std::string_view>, 3>
inline void extractNTPServersAndDomainNamesData(
const dbus::utility::ManagedObjectType& dbusData,
- std::vector<std::string>& ntpData, std::vector<std::string>& dnData)
+ std::vector<std::string>& ntpData, std::vector<std::string>& dynamicNtpData,
+ std::vector<std::string>& dnData)
{
for (const auto& obj : dbusData)
{
@@ -77,6 +80,16 @@ inline void extractNTPServersAndDomainNamesData(
ntpServers->end());
}
}
+ else if (propertyPair.first == "NTPServers")
+ {
+ const std::vector<std::string>* dynamicNtpServers =
+ std::get_if<std::vector<std::string>>(
+ &propertyPair.second);
+ if (dynamicNtpServers != nullptr)
+ {
+ dynamicNtpData = *dynamicNtpServers;
+ }
+ }
else if (propertyPair.first == "DomainName")
{
const std::vector<std::string>* domainNames =
@@ -104,19 +117,21 @@ void getEthernetIfaceData(CallbackFunc&& callback)
[callback = std::forward<CallbackFunc>(callback)](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& dbusData) {
- std::vector<std::string> ntpServers;
- std::vector<std::string> domainNames;
+ std::vector<std::string> ntpServers;
+ std::vector<std::string> dynamicNtpServers;
+ std::vector<std::string> domainNames;
- if (ec)
- {
- callback(false, ntpServers, domainNames);
- return;
- }
+ if (ec)
+ {
+ callback(false, ntpServers, dynamicNtpServers, domainNames);
+ return;
+ }
- extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames);
+ extractNTPServersAndDomainNamesData(dbusData, ntpServers,
+ dynamicNtpServers, domainNames);
- callback(true, ntpServers, domainNames);
- });
+ callback(true, ntpServers, dynamicNtpServers, domainNames);
+ });
}
inline void afterNetworkPortRequest(
@@ -164,16 +179,16 @@ inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
boost::beast::http::field::link,
"</redfish/v1/JsonSchemas/ManagerNetworkProtocol/NetworkProtocol.json>; rel=describedby");
asyncResp->res.jsonValue["@odata.type"] =
- "#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
+ "#ManagerNetworkProtocol.v1_9_0.ManagerNetworkProtocol";
asyncResp->res.jsonValue["@odata.id"] =
boost::urls::format("/redfish/v1/Managers/{}/NetworkProtocol",
BMCWEB_REDFISH_MANAGER_URI_NAME);
asyncResp->res.jsonValue["Id"] = "NetworkProtocol";
asyncResp->res.jsonValue["Name"] = "Manager Network Protocol";
asyncResp->res.jsonValue["Description"] = "Manager Network Service";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
- asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
+ asyncResp->res.jsonValue["Status"]["HealthRollup"] = resource::Health::OK;
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
// HTTP is Mandatory attribute as per OCP Baseline Profile - v1.0.0,
// but from security perspective it is not recommended to use.
@@ -199,10 +214,11 @@ inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
getNTPProtocolEnabled(asyncResp);
- getEthernetIfaceData(
- [hostName, asyncResp](const bool& success,
- const std::vector<std::string>& ntpServers,
- const std::vector<std::string>& domainNames) {
+ getEthernetIfaceData([hostName, asyncResp](
+ const bool& success,
+ const std::vector<std::string>& ntpServers,
+ const std::vector<std::string>& dynamicNtpServers,
+ const std::vector<std::string>& domainNames) {
if (!success)
{
messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol",
@@ -210,6 +226,8 @@ inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
return;
}
asyncResp->res.jsonValue["NTP"]["NTPServers"] = ntpServers;
+ asyncResp->res.jsonValue["NTP"]["NetworkSuppliedServers"] =
+ dynamicNtpServers;
if (!hostName.empty())
{
std::string fqdn = hostName;
@@ -289,9 +307,9 @@ inline void
// Can't delete an item that doesn't exist
if (currentNtpServer == currentNtpServers.end())
{
- messages::propertyValueNotInList(asyncResp->res, "null",
- "NTP/NTPServers/" +
- std::to_string(index));
+ messages::propertyValueNotInList(
+ asyncResp->res, "null",
+ "NTP/NTPServers/" + std::to_string(index));
return;
}
@@ -350,32 +368,32 @@ inline void
[asyncResp, currentNtpServers](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
- for (const auto& [objectPath, serviceMap] : subtree)
- {
- for (const auto& [service, interfaces] : serviceMap)
+ for (const auto& [objectPath, serviceMap] : subtree)
{
- for (const auto& interface : interfaces)
+ for (const auto& [service, interfaces] : serviceMap)
{
- if (interface !=
- "xyz.openbmc_project.Network.EthernetInterface")
+ for (const auto& interface : interfaces)
{
- continue;
+ if (interface !=
+ "xyz.openbmc_project.Network.EthernetInterface")
+ {
+ continue;
+ }
+
+ setDbusProperty(asyncResp, "NTP/NTPServers/", service,
+ objectPath, interface,
+ "StaticNTPServers", currentNtpServers);
}
-
- setDbusProperty(asyncResp, "NTP/NTPServers/", service,
- objectPath, interface, "StaticNTPServers",
- currentNtpServers);
}
}
- }
- });
+ });
}
inline void
@@ -390,29 +408,29 @@ inline void
[protocolEnabled, asyncResp,
netBasePath](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- for (const auto& entry : subtree)
- {
- if (entry.first.starts_with(netBasePath))
+ for (const auto& entry : subtree)
{
- setDbusProperty(
- asyncResp, "IPMI/ProtocolEnabled",
- entry.second.begin()->first, entry.first,
- "xyz.openbmc_project.Control.Service.Attributes", "Running",
- protocolEnabled);
- setDbusProperty(
- asyncResp, "IPMI/ProtocolEnabled",
- entry.second.begin()->first, entry.first,
- "xyz.openbmc_project.Control.Service.Attributes", "Enabled",
- protocolEnabled);
+ if (entry.first.starts_with(netBasePath))
+ {
+ setDbusProperty(
+ asyncResp, "IPMI/ProtocolEnabled",
+ entry.second.begin()->first, entry.first,
+ "xyz.openbmc_project.Control.Service.Attributes",
+ "Running", protocolEnabled);
+ setDbusProperty(
+ asyncResp, "IPMI/ProtocolEnabled",
+ entry.second.begin()->first, entry.first,
+ "xyz.openbmc_project.Control.Service.Attributes",
+ "Enabled", protocolEnabled);
+ }
}
- }
- });
+ });
}
inline std::string getHostName()
@@ -434,15 +452,15 @@ inline void
*crow::connections::systemBus, "org.freedesktop.timedate1",
"/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP",
[asyncResp](const boost::system::error_code& ec, bool enabled) {
- if (ec)
- {
- BMCWEB_LOG_WARNING(
- "Failed to get NTP status, assuming not supported");
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING(
+ "Failed to get NTP status, assuming not supported");
+ return;
+ }
- asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = enabled;
- });
+ asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = enabled;
+ });
}
inline std::string encodeServiceObjectPath(std::string_view serviceName)
@@ -518,15 +536,16 @@ inline void handleManagersNetworkProtocolPatch(
getEthernetIfaceData(
[asyncResp, ntpServerObjects](
const bool success, std::vector<std::string>& currentNtpServers,
+ const std::vector<std::string>& /*dynamicNtpServers*/,
const std::vector<std::string>& /*domainNames*/) {
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- handleNTPServersPatch(asyncResp, *ntpServerObjects,
- std::move(currentNtpServers));
- });
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ handleNTPServersPatch(asyncResp, *ntpServerObjects,
+ std::move(currentNtpServers));
+ });
}
if (ipmiEnabled)
diff --git a/redfish-core/lib/odata.hpp b/redfish-core/lib/odata.hpp
new file mode 100644
index 0000000000..beb26477a5
--- /dev/null
+++ b/redfish-core/lib/odata.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "app.hpp"
+#include "error_messages.hpp"
+#include "http_request.hpp"
+#include "http_response.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utility.hpp"
+
+#include <boost/url/format.hpp>
+#include <nlohmann/json.hpp>
+
+#include <memory>
+#include <ranges>
+#include <string>
+#include <string_view>
+
+namespace redfish
+{
+
+inline void redfishOdataGet(const crow::Request& /*req*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ nlohmann::json::object_t obj;
+ obj["@odata.context"] = "/redfish/v1/$metadata";
+ nlohmann::json::array_t value;
+ for (std::string_view service :
+ {"$metadata", "odata", "JsonSchemas", "Service", "ServiceRoot",
+ "Systems", "Chassis", "Managers", "SessionService", "AccountService",
+ "UpdateService"})
+ {
+ nlohmann::json::object_t serviceObj;
+ serviceObj["kind"] = "Singleton";
+ serviceObj["name"] = "$metadata";
+ boost::urls::url url = boost::urls::format("/redfish/v1/{}", service);
+ if (service == "Service")
+ {
+ url = boost::urls::url("/redfish/v1");
+ }
+ serviceObj["url"] = url;
+ value.emplace_back(std::move(serviceObj));
+ }
+
+ obj["value"] = std::move(value);
+
+ asyncResp->res.jsonValue = std::move(obj);
+}
+
+inline void requestRoutesOdata(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/odata/")
+ .methods(boost::beast::http::verb::get)(redfishOdataGet);
+}
+
+} // namespace redfish
diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp
index 3cfed3a3ca..7ddbaa0177 100644
--- a/redfish-core/lib/pcie.hpp
+++ b/redfish-core/lib/pcie.hpp
@@ -1,23 +1,24 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
@@ -40,7 +41,7 @@ static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
static constexpr std::array<std::string_view, 1> pcieSlotInterface = {
"xyz.openbmc_project.Inventory.Item.PCIeSlot"};
-static inline void handlePCIeDevicePath(
+inline void handlePCIeDevicePath(
const std::string& pcieDeviceId,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths,
@@ -58,18 +59,18 @@ static inline void handlePCIeDevicePath(
}
dbus::utility::getDbusObject(
- pcieDevicePath, {},
+ pcieDevicePath, pcieDeviceInterface,
[pcieDevicePath, asyncResp,
callback](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& object) {
- if (ec || object.empty())
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- callback(pcieDevicePath, object.begin()->first);
- });
+ if (ec || object.empty())
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ callback(pcieDevicePath, object.begin()->first);
+ });
return;
}
@@ -77,7 +78,7 @@ static inline void handlePCIeDevicePath(
messages::resourceNotFound(asyncResp->res, "PCIeDevice", pcieDeviceId);
}
-static inline void getValidPCIeDevicePath(
+inline void getValidPCIeDevicePath(
const std::string& pcieDeviceId,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::function<void(const std::string& pcieDevicePath,
@@ -89,19 +90,19 @@ static inline void getValidPCIeDevicePath(
callback](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse&
pcieDevicePaths) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
- messages::internalError(asyncResp->res);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("D-Bus response error on GetSubTree {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
+ callback);
return;
- }
- handlePCIeDevicePath(pcieDeviceId, asyncResp, pcieDevicePaths,
- callback);
- return;
- });
+ });
}
-static inline void handlePCIeDeviceCollectionGet(
+inline void handlePCIeDeviceCollectionGet(
crow::App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName)
@@ -226,43 +227,42 @@ inline void getPCIeDeviceSlotPath(
[callback = std::move(callback), asyncResp, pcieDevicePath](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse& endpoints) {
- if (ec)
- {
- if (ec.value() == EBADR)
+ if (ec)
{
- // Missing association is not an error
+ if (ec.value() == EBADR)
+ {
+ // Missing association is not an error
+ return;
+ }
+ BMCWEB_LOG_ERROR(
+ "DBUS response error for getAssociatedSubTreePaths {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_ERROR(
- "DBUS response error for getAssociatedSubTreePaths {}",
- ec.value());
- messages::internalError(asyncResp->res);
- return;
- }
- if (endpoints.size() > 1)
- {
- BMCWEB_LOG_ERROR(
- "PCIeDevice is associated with more than one PCIeSlot: {}",
- endpoints.size());
- messages::internalError(asyncResp->res);
- return;
- }
- if (endpoints.empty())
- {
- // If the device doesn't have an association, return without PCIe
- // Slot properties
- BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
- return;
- }
- callback(endpoints[0]);
- });
+ if (endpoints.size() > 1)
+ {
+ BMCWEB_LOG_ERROR(
+ "PCIeDevice is associated with more than one PCIeSlot: {}",
+ endpoints.size());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (endpoints.empty())
+ {
+ // If the device doesn't have an association, return without
+ // PCIe Slot properties
+ BMCWEB_LOG_DEBUG("PCIeDevice is not associated with PCIeSlot");
+ return;
+ }
+ callback(endpoints[0]);
+ });
}
-inline void
- afterGetDbusObject(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& pcieDeviceSlot,
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetObject& object)
+inline void afterGetDbusObject(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& pcieDeviceSlot, const boost::system::error_code& ec,
+ const dbus::utility::MapperGetObject& object)
{
if (ec || object.empty())
{
@@ -277,8 +277,8 @@ inline void
[asyncResp](
const boost::system::error_code& ec2,
const dbus::utility::DBusPropertiesMap& pcieSlotProperties) {
- addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
- });
+ addPCIeSlotProperties(asyncResp->res, ec2, pcieSlotProperties);
+ });
}
inline void afterGetPCIeDeviceSlotPath(
@@ -290,67 +290,66 @@ inline void afterGetPCIeDeviceSlotPath(
[asyncResp,
pcieDeviceSlot](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& object) {
- afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
- });
+ afterGetDbusObject(asyncResp, pcieDeviceSlot, ec, object);
+ });
}
-inline void
- getPCIeDeviceHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& pcieDevicePath,
- const std::string& service)
+inline void getPCIeDeviceHealth(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& pcieDevicePath, const std::string& service)
{
sdbusplus::asio::getProperty<bool>(
*crow::connections::systemBus, service, pcieDevicePath,
"xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
[asyncResp](const boost::system::error_code& ec, const bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Health {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Health {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!value)
- {
- asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
- }
- });
+ if (!value)
+ {
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::Critical;
+ }
+ });
}
-inline void
- getPCIeDeviceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& pcieDevicePath,
- const std::string& service)
+inline void getPCIeDeviceState(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& pcieDevicePath, const std::string& service)
{
sdbusplus::asio::getProperty<bool>(
*crow::connections::systemBus, service, pcieDevicePath,
"xyz.openbmc_project.Inventory.Item", "Present",
[asyncResp](const boost::system::error_code& ec, bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for State");
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for State");
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!value)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ if (!value)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ }
+ });
}
-inline void
- getPCIeDeviceAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& pcieDevicePath,
- const std::string& service)
+inline void getPCIeDeviceAsset(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& pcieDevicePath, const std::string& service)
{
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, service, pcieDevicePath,
@@ -358,58 +357,59 @@ inline void
[pcieDevicePath, asyncResp{asyncResp}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& assetList) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Properties{}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- const std::string* manufacturer = nullptr;
- const std::string* model = nullptr;
- const std::string* partNumber = nullptr;
- const std::string* serialNumber = nullptr;
- const std::string* sparePartNumber = nullptr;
+ const std::string* manufacturer = nullptr;
+ const std::string* model = nullptr;
+ const std::string* partNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* sparePartNumber = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
- manufacturer, "Model", model, "PartNumber", partNumber,
- "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
+ manufacturer, "Model", model, "PartNumber", partNumber,
+ "SerialNumber", serialNumber, "SparePartNumber",
+ sparePartNumber);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (manufacturer != nullptr)
- {
- asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
- }
- if (model != nullptr)
- {
- asyncResp->res.jsonValue["Model"] = *model;
- }
+ if (manufacturer != nullptr)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+ }
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] = *model;
+ }
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] = *partNumber;
- }
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
- if (serialNumber != nullptr)
- {
- asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
- }
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
- if (sparePartNumber != nullptr && !sparePartNumber->empty())
- {
- asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
- }
- });
+ if (sparePartNumber != nullptr && !sparePartNumber->empty())
+ {
+ asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
+ }
+ });
}
inline void addPCIeDeviceProperties(
@@ -520,17 +520,17 @@ inline void getPCIeDeviceProperties(
[asyncResp,
callback](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Properties");
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Properties");
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- callback(pcieDevProperties);
- });
+ callback(pcieDevProperties);
+ });
}
inline void addPCIeDeviceCommonProperties(
@@ -546,8 +546,8 @@ inline void addPCIeDeviceCommonProperties(
BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
asyncResp->res.jsonValue["Name"] = "PCIe Device";
asyncResp->res.jsonValue["Id"] = pcieDeviceId;
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
}
inline void afterGetValidPcieDevicePath(
@@ -567,11 +567,10 @@ inline void afterGetValidPcieDevicePath(
std::bind_front(afterGetPCIeDeviceSlotPath, asyncResp));
}
-inline void
- handlePCIeDeviceGet(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& pcieDeviceId)
+inline void handlePCIeDeviceGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& pcieDeviceId)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -616,8 +615,8 @@ inline void addPCIeFunctionList(
{
// Check if this function exists by
// looking for a device ID
- std::string devIDProperty = "Function" + std::to_string(functionNum) +
- "DeviceId";
+ std::string devIDProperty =
+ "Function" + std::to_string(functionNum) + "DeviceId";
const std::string* property = nullptr;
for (const auto& propEntry : pcieDevProperties)
{
@@ -663,25 +662,25 @@ inline void handlePCIeFunctionCollectionGet(
pcieDeviceId, asyncResp,
[asyncResp, pcieDeviceId](const std::string& pcieDevicePath,
const std::string& service) {
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
- asyncResp->res.jsonValue["@odata.type"] =
- "#PCIeFunctionCollection.PCIeFunctionCollection";
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
- asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
- asyncResp->res.jsonValue["Description"] =
- "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
- getPCIeDeviceProperties(
- asyncResp, pcieDevicePath, service,
- [asyncResp, pcieDeviceId](
- const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
- addPCIeFunctionList(asyncResp->res, pcieDeviceId,
- pcieDevProperties);
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#PCIeFunctionCollection.PCIeFunctionCollection";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/PCIeDevices/{}/PCIeFunctions",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
+ asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
+ getPCIeDeviceProperties(
+ asyncResp, pcieDevicePath, service,
+ [asyncResp, pcieDeviceId](
+ const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
+ addPCIeFunctionList(asyncResp->res, pcieDeviceId,
+ pcieDevProperties);
+ });
});
- });
}
inline void requestRoutesSystemPCIeFunctionCollection(App& app)
@@ -726,7 +725,6 @@ inline void addPCIeFunctionProperties(
std::get_if<std::string>(&property.second);
if (strProperty == nullptr)
{
- BMCWEB_LOG_ERROR("Function wasn't a string?");
continue;
}
if (property.first == functionName + "DeviceId")
@@ -793,12 +791,11 @@ inline void addPCIeFunctionCommonProperties(crow::Response& resp,
BMCWEB_REDFISH_SYSTEM_URI_NAME, pcieDeviceId);
}
-inline void
- handlePCIeFunctionGet(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& pcieDeviceId,
- const std::string& pcieFunctionIdStr)
+inline void handlePCIeFunctionGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& pcieDeviceId,
+ const std::string& pcieFunctionIdStr)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -829,20 +826,20 @@ inline void
return;
}
- getValidPCIeDevicePath(pcieDeviceId, asyncResp,
- [asyncResp, pcieDeviceId,
- pcieFunctionId](const std::string& pcieDevicePath,
- const std::string& service) {
- getPCIeDeviceProperties(
- asyncResp, pcieDevicePath, service,
- [asyncResp, pcieDeviceId, pcieFunctionId](
- const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
- addPCIeFunctionCommonProperties(asyncResp->res, pcieDeviceId,
- pcieFunctionId);
- addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
- pcieDevProperties);
+ getValidPCIeDevicePath(
+ pcieDeviceId, asyncResp,
+ [asyncResp, pcieDeviceId, pcieFunctionId](
+ const std::string& pcieDevicePath, const std::string& service) {
+ getPCIeDeviceProperties(
+ asyncResp, pcieDevicePath, service,
+ [asyncResp, pcieDeviceId, pcieFunctionId](
+ const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
+ addPCIeFunctionCommonProperties(
+ asyncResp->res, pcieDeviceId, pcieFunctionId);
+ addPCIeFunctionProperties(asyncResp->res, pcieFunctionId,
+ pcieDevProperties);
+ });
});
- });
}
inline void requestRoutesSystemPCIeFunction(App& app)
diff --git a/redfish-core/lib/pcie_slots.hpp b/redfish-core/lib/pcie_slots.hpp
index b8e6389275..a6796b9913 100644
--- a/redfish-core/lib/pcie_slots.hpp
+++ b/redfish-core/lib/pcie_slots.hpp
@@ -153,15 +153,14 @@ inline void onMapperAssociationDone(
"xyz.openbmc_project.Inventory.Item.PCIeSlot",
[asyncResp](const boost::system::error_code& ec2,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- onPcieSlotGetAllDone(asyncResp, ec2, propertiesList);
- });
+ onPcieSlotGetAllDone(asyncResp, ec2, propertiesList);
+ });
}
-inline void
- onMapperSubtreeDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisID,
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree)
+inline void onMapperSubtreeDone(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisID, const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree)
{
if (ec)
{
@@ -202,9 +201,9 @@ inline void
[asyncResp, chassisID, pcieSlotPath, connectionName](
const boost::system::error_code& ec2,
const dbus::utility::MapperEndPoints& endpoints) {
- onMapperAssociationDone(asyncResp, chassisID, pcieSlotPath,
- connectionName, ec2, endpoints);
- });
+ onMapperAssociationDone(asyncResp, chassisID, pcieSlotPath,
+ connectionName, ec2, endpoints);
+ });
}
}
}
@@ -226,8 +225,8 @@ inline void handlePCIeSlotCollectionGet(
[asyncResp,
chassisID](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- onMapperSubtreeDone(asyncResp, chassisID, ec, subtree);
- });
+ onMapperSubtreeDone(asyncResp, chassisID, ec, subtree);
+ });
}
inline void requestRoutesPCIeSlots(App& app)
diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp
index cd7fa0f08a..d2843615e0 100644
--- a/redfish-core/lib/power.hpp
+++ b/redfish-core/lib/power.hpp
@@ -1,28 +1,30 @@
/*
-// Copyright (c) 2018 Intel Corporation
-// Copyright (c) 2018 Ampere Computing LLC
-/
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+Copyright (c) 2018 Ampere Computing LLC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/power.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "sensors.hpp"
#include "utils/chassis_utils.hpp"
#include "utils/json_utils.hpp"
+#include "utils/sensor_utils.hpp"
#include <sdbusplus/asio/property.hpp>
@@ -125,9 +127,9 @@ inline void afterPowerCapSettingGet(
// A warning without a odata.type
nlohmann::json::object_t powerControl;
powerControl["@odata.type"] = "#Power.v1_0_0.PowerControl";
- powerControl["@odata.id"] = "/redfish/v1/Chassis/" +
- sensorAsyncResp->chassisId +
- "/Power#/PowerControl/0";
+ powerControl["@odata.id"] =
+ "/redfish/v1/Chassis/" + sensorAsyncResp->chassisId +
+ "/Power#/PowerControl/0";
powerControl["Name"] = "Chassis Power Control";
powerControl["MemberId"] = "0";
tempArray.emplace_back(std::move(powerControl));
@@ -181,24 +183,24 @@ inline void afterPowerCapSettingGet(
}
// LimitException is Mandatory attribute as per OCP
- // Baseline Profile – v1.0.0, so currently making it
+ // Baseline Profile - v1.0.0, so currently making it
// "NoAction" as default value to make it OCP Compliant.
- sensorJson["PowerLimit"]["LimitException"] = "NoAction";
+ sensorJson["PowerLimit"]["LimitException"] =
+ power::PowerLimitException::NoAction;
if (enabled)
{
// Redfish specification indicates PowerLimit should
// be null if the limit is not enabled.
- sensorJson["PowerLimit"]["LimitInWatts"] = powerCap *
- std::pow(10, scale);
+ sensorJson["PowerLimit"]["LimitInWatts"] =
+ powerCap * std::pow(10, scale);
}
}
using Mapper = dbus::utility::MapperGetSubTreePathsResponse;
-inline void
- afterGetChassis(const std::shared_ptr<SensorsAsyncResp>& sensorAsyncResp,
- const boost::system::error_code& ec2,
- const Mapper& chassisPaths)
+inline void afterGetChassis(
+ const std::shared_ptr<SensorsAsyncResp>& sensorAsyncResp,
+ const boost::system::error_code& ec2, const Mapper& chassisPaths)
{
if (ec2)
{
@@ -267,7 +269,8 @@ inline void
auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
asyncResp, chassisName, sensors::dbus::powerPaths,
- sensors::node::power);
+ sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::powerNode));
getChassisData(sensorAsyncResp);
@@ -296,7 +299,8 @@ inline void
}
auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
asyncResp, chassisName, sensors::dbus::powerPaths,
- sensors::node::power);
+ sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::powerNode));
std::optional<std::vector<nlohmann::json::object_t>> voltageCollections;
std::optional<std::vector<nlohmann::json::object_t>> powerCtlCollections;
diff --git a/redfish-core/lib/power_subsystem.hpp b/redfish-core/lib/power_subsystem.hpp
index d54fd18389..ff7d52cd22 100644
--- a/redfish-core/lib/power_subsystem.hpp
+++ b/redfish-core/lib/power_subsystem.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "app.hpp"
+#include "generated/enums/resource.hpp"
#include "logging.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
@@ -35,8 +36,8 @@ inline void doPowerSubsystemCollection(
asyncResp->res.jsonValue["Id"] = "PowerSubsystem";
asyncResp->res.jsonValue["@odata.id"] =
boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem", chassisId);
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
asyncResp->res.jsonValue["PowerSupplies"]["@odata.id"] =
boost::urls::format(
"/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
diff --git a/redfish-core/lib/power_supply.hpp b/redfish-core/lib/power_supply.hpp
index f59ed57d5f..26ea26c93c 100644
--- a/redfish-core/lib/power_supply.hpp
+++ b/redfish-core/lib/power_supply.hpp
@@ -2,6 +2,7 @@
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/chassis_utils.hpp"
@@ -46,17 +47,20 @@ inline void updatePowerSupplyList(
asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size();
}
-inline void
- doPowerSupplyCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::optional<std::string>& validChassisPath)
+inline void doPowerSupplyCollection(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths)
{
- if (!validChassisPath)
+ if (ec)
{
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
+ messages::internalError(asyncResp->res);
+ }
return;
}
-
asyncResp->res.addHeader(
boost::beast::http::field::link,
"</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
@@ -70,26 +74,7 @@ inline void
asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
asyncResp->res.jsonValue["Members@odata.count"] = 0;
- std::string powerPath = *validChassisPath + "/powered_by";
- dbus::utility::getAssociatedSubTreePaths(
- powerPath,
- sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
- powerSupplyInterface,
- [asyncResp, chassisId](
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
- if (ec)
- {
- if (ec.value() != EBADR)
- {
- BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
- messages::internalError(asyncResp->res);
- }
- return;
- }
-
- updatePowerSupplyList(asyncResp, chassisId, subtreePaths);
- });
+ updatePowerSupplyList(asyncResp, chassisId, subtreePaths);
}
inline void handlePowerSupplyCollectionHead(
@@ -106,15 +91,16 @@ inline void handlePowerSupplyCollectionHead(
asyncResp, chassisId,
[asyncResp,
chassisId](const std::optional<std::string>& validChassisPath) {
- if (!validChassisPath)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- return;
- }
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
- });
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis",
+ chassisId);
+ return;
+ }
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
+ });
}
inline void handlePowerSupplyCollectionGet(
@@ -127,9 +113,19 @@ inline void handlePowerSupplyCollectionGet(
return;
}
- redfish::chassis_utils::getValidChassisPath(
- asyncResp, chassisId,
- std::bind_front(doPowerSupplyCollection, asyncResp, chassisId));
+ constexpr std::array<std::string_view, 2> chasisInterfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+ const std::string reqpath = "/xyz/openbmc_project/inventory";
+
+ dbus::utility::getAssociatedSubTreePathsById(
+ chassisId, reqpath, chasisInterfaces, "powered_by",
+ powerSupplyInterface,
+ [asyncResp, chassisId](
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
+ doPowerSupplyCollection(asyncResp, chassisId, ec, subtreePaths);
+ });
}
inline void requestRoutesPowerSupplyCollection(App& app)
@@ -145,60 +141,56 @@ inline void requestRoutesPowerSupplyCollection(App& app)
std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
}
-inline bool checkPowerSupplyId(const std::string& powerSupplyPath,
- const std::string& powerSupplyId)
+inline void afterGetValidPowerSupplyPath(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& powerSupplyId, const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree,
+ const std::function<void(const std::string& powerSupplyPath,
+ const std::string& service)>& callback)
{
- std::string powerSupplyName =
- sdbusplus::message::object_path(powerSupplyPath).filename();
+ if (ec)
+ {
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+ for (const auto& [objectPath, service] : subtree)
+ {
+ sdbusplus::message::object_path path(objectPath);
+ if (path == powerSupplyId)
+ {
+ callback(path, service.begin()->first);
+ return;
+ }
+ }
- return !(powerSupplyName.empty() || powerSupplyName != powerSupplyId);
+ BMCWEB_LOG_WARNING("Power supply not found: {}", powerSupplyId);
+ messages::resourceNotFound(asyncResp->res, "PowerSupplies", powerSupplyId);
}
inline void getValidPowerSupplyPath(
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& validChassisPath, const std::string& powerSupplyId,
- std::function<void(const std::string& powerSupplyPath)>&& callback)
+ const std::string& chassisId, const std::string& powerSupplyId,
+ std::function<void(const std::string& powerSupplyPath,
+ const std::string& service)>&& callback)
{
- std::string powerPath = validChassisPath + "/powered_by";
- dbus::utility::getAssociatedSubTreePaths(
- powerPath,
- sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
+ constexpr std::array<std::string_view, 2> chasisInterfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis"};
+ const std::string reqpath = "/xyz/openbmc_project/inventory";
+
+ dbus::utility::getAssociatedSubTreeById(
+ chassisId, reqpath, chasisInterfaces, "powered_by",
powerSupplyInterface,
- [asyncResp, powerSupplyId, callback{std::move(callback)}](
+ [asyncResp, chassisId, powerSupplyId, callback{std::move(callback)}](
const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
- if (ec)
- {
- if (ec.value() != EBADR)
- {
- BMCWEB_LOG_ERROR(
- "DBUS response error for getAssociatedSubTreePaths{}",
- ec.value());
- messages::internalError(asyncResp->res);
- return;
- }
- messages::resourceNotFound(asyncResp->res, "PowerSupplies",
- powerSupplyId);
- return;
- }
-
- for (const std::string& path : subtreePaths)
- {
- if (checkPowerSupplyId(path, powerSupplyId))
- {
- callback(path);
- return;
- }
- }
-
- if (!subtreePaths.empty())
- {
- BMCWEB_LOG_WARNING("Power supply not found: {}", powerSupplyId);
- messages::resourceNotFound(asyncResp->res, "PowerSupplies",
- powerSupplyId);
- return;
- }
- });
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ afterGetValidPowerSupplyPath(asyncResp, powerSupplyId, ec, subtree,
+ callback);
+ });
}
inline void
@@ -209,22 +201,23 @@ inline void
*crow::connections::systemBus, service, path,
"xyz.openbmc_project.Inventory.Item", "Present",
[asyncResp](const boost::system::error_code& ec, const bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for State {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for State {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!value)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ if (!value)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ }
+ });
}
inline void
@@ -235,22 +228,23 @@ inline void
*crow::connections::systemBus, service, path,
"xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
[asyncResp](const boost::system::error_code& ec, const bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Health {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Health {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (!value)
- {
- asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
- }
- });
+ if (!value)
+ {
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::Critical;
+ }
+ });
}
inline void
@@ -262,60 +256,61 @@ inline void
"xyz.openbmc_project.Inventory.Decorator.Asset",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Asset {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Asset {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- const std::string* partNumber = nullptr;
- const std::string* serialNumber = nullptr;
- const std::string* manufacturer = nullptr;
- const std::string* model = nullptr;
- const std::string* sparePartNumber = nullptr;
+ const std::string* partNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* manufacturer = nullptr;
+ const std::string* model = nullptr;
+ const std::string* sparePartNumber = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
- partNumber, "SerialNumber", serialNumber, "Manufacturer",
- manufacturer, "Model", model, "SparePartNumber", sparePartNumber);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
+ partNumber, "SerialNumber", serialNumber, "Manufacturer",
+ manufacturer, "Model", model, "SparePartNumber",
+ sparePartNumber);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] = *partNumber;
- }
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
- if (serialNumber != nullptr)
- {
- asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
- }
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
- if (manufacturer != nullptr)
- {
- asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
- }
+ if (manufacturer != nullptr)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+ }
- if (model != nullptr)
- {
- asyncResp->res.jsonValue["Model"] = *model;
- }
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] = *model;
+ }
- // SparePartNumber is optional on D-Bus so skip if it is empty
- if (sparePartNumber != nullptr && !sparePartNumber->empty())
- {
- asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
- }
- });
+ // SparePartNumber is optional on D-Bus so skip if it is empty
+ if (sparePartNumber != nullptr && !sparePartNumber->empty())
+ {
+ asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
+ }
+ });
}
inline void getPowerSupplyFirmwareVersion(
@@ -327,18 +322,19 @@ inline void getPowerSupplyFirmwareVersion(
"xyz.openbmc_project.Software.Version", "Version",
[asyncResp](const boost::system::error_code& ec,
const std::string& value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for FirmwareVersion {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBUS response error for FirmwareVersion {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- asyncResp->res.jsonValue["FirmwareVersion"] = value;
- });
+ asyncResp->res.jsonValue["FirmwareVersion"] = value;
+ });
}
inline void
@@ -350,19 +346,19 @@ inline void
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
[asyncResp](const boost::system::error_code& ec,
const std::string& value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error for Location {}",
- ec.value());
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error for Location {}",
+ ec.value());
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- value;
- });
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = value;
+ });
}
inline void handleGetEfficiencyResponse(
@@ -430,8 +426,8 @@ inline void handlePowerSupplyAttributesSubTreeResponse(
*crow::connections::systemBus, service, path,
"xyz.openbmc_project.Control.PowerSupplyAttributes", "DeratingFactor",
[asyncResp](const boost::system::error_code& ec1, uint32_t value) {
- handleGetEfficiencyResponse(asyncResp, ec1, value);
- });
+ handleGetEfficiencyResponse(asyncResp, ec1, value);
+ });
}
inline void
@@ -444,111 +440,67 @@ inline void
"/xyz/openbmc_project", 0, efficiencyIntf,
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- handlePowerSupplyAttributesSubTreeResponse(asyncResp, ec, subtree);
- });
+ handlePowerSupplyAttributesSubTreeResponse(asyncResp, ec, subtree);
+ });
}
-inline void
- doPowerSupplyGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::string& powerSupplyId,
- const std::optional<std::string>& validChassisPath)
+inline void doPowerSupplyGet(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const std::string& powerSupplyId,
+ const std::string& powerSupplyPath, const std::string& service)
{
- if (!validChassisPath)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- return;
- }
-
- // Get the correct Path and Service that match the input parameters
- getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
- [asyncResp, chassisId, powerSupplyId](
- const std::string& powerSupplyPath) {
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
- asyncResp->res.jsonValue["@odata.type"] =
- "#PowerSupply.v1_5_0.PowerSupply";
- asyncResp->res.jsonValue["Name"] = "Power Supply";
- asyncResp->res.jsonValue["Id"] = powerSupplyId;
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
- powerSupplyId);
-
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
-
- dbus::utility::getDbusObject(
- powerSupplyPath, powerSupplyInterface,
- [asyncResp,
- powerSupplyPath](const boost::system::error_code& ec,
- const dbus::utility::MapperGetObject& object) {
- if (ec || object.empty())
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- getPowerSupplyState(asyncResp, object.begin()->first,
- powerSupplyPath);
- getPowerSupplyHealth(asyncResp, object.begin()->first,
- powerSupplyPath);
- getPowerSupplyAsset(asyncResp, object.begin()->first,
- powerSupplyPath);
- getPowerSupplyFirmwareVersion(asyncResp, object.begin()->first,
- powerSupplyPath);
- getPowerSupplyLocation(asyncResp, object.begin()->first,
- powerSupplyPath);
- });
-
- getEfficiencyPercent(asyncResp);
- });
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
+ asyncResp->res.jsonValue["@odata.type"] = "#PowerSupply.v1_5_0.PowerSupply";
+ asyncResp->res.jsonValue["Name"] = "Power Supply";
+ asyncResp->res.jsonValue["Id"] = powerSupplyId;
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
+ powerSupplyId);
+
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
+
+ getPowerSupplyState(asyncResp, service, powerSupplyPath);
+ getPowerSupplyHealth(asyncResp, service, powerSupplyPath);
+ getPowerSupplyAsset(asyncResp, service, powerSupplyPath);
+ getPowerSupplyFirmwareVersion(asyncResp, service, powerSupplyPath);
+ getPowerSupplyLocation(asyncResp, service, powerSupplyPath);
+ getEfficiencyPercent(asyncResp);
}
-inline void
- handlePowerSupplyHead(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::string& powerSupplyId)
+inline void handlePowerSupplyHead(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const std::string& powerSupplyId)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
return;
}
- redfish::chassis_utils::getValidChassisPath(
- asyncResp, chassisId,
- [asyncResp, chassisId,
- powerSupplyId](const std::optional<std::string>& validChassisPath) {
- if (!validChassisPath)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- return;
- }
-
- // Get the correct Path and Service that match the input parameters
- getValidPowerSupplyPath(asyncResp, *validChassisPath, powerSupplyId,
- [asyncResp](const std::string&) {
+ // Get the correct Path and Service that match the input parameters
+ getValidPowerSupplyPath(
+ asyncResp, chassisId, powerSupplyId,
+ [asyncResp](const std::string&, const std::string&) {
asyncResp->res.addHeader(
boost::beast::http::field::link,
"</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
});
- });
}
-inline void
- handlePowerSupplyGet(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::string& powerSupplyId)
+inline void handlePowerSupplyGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const std::string& powerSupplyId)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
return;
}
-
- redfish::chassis_utils::getValidChassisPath(
- asyncResp, chassisId,
+ getValidPowerSupplyPath(
+ asyncResp, chassisId, powerSupplyId,
std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
}
diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp
index 8015369dbf..82781d3bd9 100644
--- a/redfish-core/lib/processor.hpp
+++ b/redfish-core/lib/processor.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -20,6 +20,7 @@
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "generated/enums/processor.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
@@ -66,14 +67,14 @@ inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
"xyz.openbmc_project.Common.UUID", "UUID",
[objPath, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec, const std::string& property) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["UUID"] = property;
- });
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["UUID"] = property;
+ });
}
inline void getCpuDataByInterface(
@@ -83,8 +84,8 @@ inline void getCpuDataByInterface(
BMCWEB_LOG_DEBUG("Get CPU resources by interface.");
// Set the default value of state
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
for (const auto& interface : cpuInterfacesProperties)
{
@@ -102,7 +103,8 @@ inline void getCpuDataByInterface(
if (!*cpuPresent)
{
// Slot is not populated
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
}
}
else if (property.first == "Functional")
@@ -115,7 +117,8 @@ inline void getCpuDataByInterface(
}
if (!*cpuFunctional)
{
- asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
+ asyncResp->res.jsonValue["Status"]["Health"] =
+ resource::Health::Critical;
}
}
else if (property.first == "CoreCount")
@@ -219,10 +222,9 @@ inline void getCpuDataByInterface(
}
}
-inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
- const std::string& cpuId,
- const std::string& service,
- const std::string& objPath)
+inline void getCpuDataByService(
+ std::shared_ptr<bmcweb::AsyncResp> asyncResp, const std::string& cpuId,
+ const std::string& service, const std::string& objPath)
{
BMCWEB_LOG_DEBUG("Get available system cpu resources by service.");
@@ -232,43 +234,46 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[cpuId, service, objPath, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& dbusData) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["Id"] = cpuId;
- asyncResp->res.jsonValue["Name"] = "Processor";
- asyncResp->res.jsonValue["ProcessorType"] = "CPU";
-
- bool slotPresent = false;
- std::string corePath = objPath + "/core";
- size_t totalCores = 0;
- for (const auto& object : dbusData)
- {
- if (object.first.str == objPath)
+ if (ec)
{
- getCpuDataByInterface(asyncResp, object.second);
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
}
- else if (object.first.str.starts_with(corePath))
+ asyncResp->res.jsonValue["Id"] = cpuId;
+ asyncResp->res.jsonValue["Name"] = "Processor";
+ asyncResp->res.jsonValue["ProcessorType"] =
+ processor::ProcessorType::CPU;
+
+ bool slotPresent = false;
+ std::string corePath = objPath + "/core";
+ size_t totalCores = 0;
+ for (const auto& object : dbusData)
{
- for (const auto& interface : object.second)
+ if (object.first.str == objPath)
{
- if (interface.first == "xyz.openbmc_project.Inventory.Item")
+ getCpuDataByInterface(asyncResp, object.second);
+ }
+ else if (object.first.str.starts_with(corePath))
+ {
+ for (const auto& interface : object.second)
{
- for (const auto& property : interface.second)
+ if (interface.first ==
+ "xyz.openbmc_project.Inventory.Item")
{
- if (property.first == "Present")
+ for (const auto& property : interface.second)
{
- const bool* present =
- std::get_if<bool>(&property.second);
- if (present != nullptr)
+ if (property.first == "Present")
{
- if (*present)
+ const bool* present =
+ std::get_if<bool>(&property.second);
+ if (present != nullptr)
{
- slotPresent = true;
- totalCores++;
+ if (*present)
+ {
+ slotPresent = true;
+ totalCores++;
+ }
}
}
}
@@ -276,16 +281,15 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
}
}
}
- }
- // In getCpuDataByInterface(), state and health are set
- // based on the present and functional status. If core
- // count is zero, then it has a higher precedence.
- if (slotPresent)
- {
- asyncResp->res.jsonValue["TotalCores"] = totalCores;
- }
- return;
- });
+ // In getCpuDataByInterface(), state and health are set
+ // based on the present and functional status. If core
+ // count is zero, then it has a higher precedence.
+ if (slotPresent)
+ {
+ asyncResp->res.jsonValue["TotalCores"] = totalCores;
+ }
+ return;
+ });
}
/**
@@ -366,10 +370,9 @@ inline void
asyncResp->res.jsonValue["ThrottleCauses"] = std::move(rCauses);
}
-inline void
- getThrottleProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& service,
- const std::string& objectPath)
+inline void getThrottleProperties(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& service, const std::string& objectPath)
{
BMCWEB_LOG_DEBUG("Get processor throttle resources");
@@ -378,8 +381,8 @@ inline void
"xyz.openbmc_project.Control.Power.Throttle",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- readThrottleProperties(asyncResp, ec, properties);
- });
+ readThrottleProperties(asyncResp, ec, properties);
+ });
}
inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
@@ -393,67 +396,67 @@ inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[objPath, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string* serialNumber = nullptr;
- const std::string* model = nullptr;
- const std::string* manufacturer = nullptr;
- const std::string* partNumber = nullptr;
- const std::string* sparePartNumber = nullptr;
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
- serialNumber, "Model", model, "Manufacturer", manufacturer,
- "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
+ const std::string* serialNumber = nullptr;
+ const std::string* model = nullptr;
+ const std::string* manufacturer = nullptr;
+ const std::string* partNumber = nullptr;
+ const std::string* sparePartNumber = nullptr;
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties, "SerialNumber",
+ serialNumber, "Model", model, "Manufacturer", manufacturer,
+ "PartNumber", partNumber, "SparePartNumber", sparePartNumber);
- if (serialNumber != nullptr && !serialNumber->empty())
- {
- asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
- }
-
- if ((model != nullptr) && !model->empty())
- {
- asyncResp->res.jsonValue["Model"] = *model;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (manufacturer != nullptr)
- {
- asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+ if (serialNumber != nullptr && !serialNumber->empty())
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
- // Otherwise would be unexpected.
- if (manufacturer->find("Intel") != std::string::npos)
+ if ((model != nullptr) && !model->empty())
{
- asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
- asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
+ asyncResp->res.jsonValue["Model"] = *model;
}
- else if (manufacturer->find("IBM") != std::string::npos)
+
+ if (manufacturer != nullptr)
{
- asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
- asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
+ asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+
+ // Otherwise would be unexpected.
+ if (manufacturer->find("Intel") != std::string::npos)
+ {
+ asyncResp->res.jsonValue["ProcessorArchitecture"] = "x86";
+ asyncResp->res.jsonValue["InstructionSet"] = "x86-64";
+ }
+ else if (manufacturer->find("IBM") != std::string::npos)
+ {
+ asyncResp->res.jsonValue["ProcessorArchitecture"] = "Power";
+ asyncResp->res.jsonValue["InstructionSet"] = "PowerISA";
+ }
}
- }
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] = *partNumber;
- }
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
- if (sparePartNumber != nullptr && !sparePartNumber->empty())
- {
- asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
- }
- });
+ if (sparePartNumber != nullptr && !sparePartNumber->empty())
+ {
+ asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
+ }
+ });
}
inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
@@ -467,29 +470,30 @@ inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[objPath, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const std::string* version = nullptr;
+ const std::string* version = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "Version", version);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties, "Version",
+ version);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (version != nullptr)
- {
- asyncResp->res.jsonValue["Version"] = *version;
- }
- });
+ if (version != nullptr)
+ {
+ asyncResp->res.jsonValue["Version"] = *version;
+ }
+ });
}
inline void getAcceleratorDataByService(
@@ -502,48 +506,49 @@ inline void getAcceleratorDataByService(
[acclrtrId, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const bool* functional = nullptr;
- const bool* present = nullptr;
+ const bool* functional = nullptr;
+ const bool* present = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "Functional",
- functional, "Present", present);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties, "Functional",
+ functional, "Present", present);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- std::string state = "Enabled";
- std::string health = "OK";
+ std::string state = "Enabled";
+ std::string health = "OK";
- if (present != nullptr && !*present)
- {
- state = "Absent";
- }
+ if (present != nullptr && !*present)
+ {
+ state = "Absent";
+ }
- if (functional != nullptr && !*functional)
- {
- if (state == "Enabled")
+ if (functional != nullptr && !*functional)
{
- health = "Critical";
+ if (state == "Enabled")
+ {
+ health = "Critical";
+ }
}
- }
- asyncResp->res.jsonValue["Id"] = acclrtrId;
- asyncResp->res.jsonValue["Name"] = "Processor";
- asyncResp->res.jsonValue["Status"]["State"] = state;
- asyncResp->res.jsonValue["Status"]["Health"] = health;
- asyncResp->res.jsonValue["ProcessorType"] = "Accelerator";
- });
+ asyncResp->res.jsonValue["Id"] = acclrtrId;
+ asyncResp->res.jsonValue["Name"] = "Processor";
+ asyncResp->res.jsonValue["Status"]["State"] = state;
+ asyncResp->res.jsonValue["Status"]["Health"] = health;
+ asyncResp->res.jsonValue["ProcessorType"] =
+ processor::ProcessorType::Accelerator;
+ });
}
// OperatingConfig D-Bus Types
@@ -616,85 +621,87 @@ inline void
[asyncResp, cpuId,
service](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
-
- nlohmann::json& json = asyncResp->res.jsonValue;
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const sdbusplus::message::object_path* appliedConfig = nullptr;
- const bool* baseSpeedPriorityEnabled = nullptr;
+ nlohmann::json& json = asyncResp->res.jsonValue;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
- appliedConfig, "BaseSpeedPriorityEnabled",
- baseSpeedPriorityEnabled);
+ const sdbusplus::message::object_path* appliedConfig = nullptr;
+ const bool* baseSpeedPriorityEnabled = nullptr;
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties, "AppliedConfig",
+ appliedConfig, "BaseSpeedPriorityEnabled",
+ baseSpeedPriorityEnabled);
- if (appliedConfig != nullptr)
- {
- const std::string& dbusPath = appliedConfig->str;
- nlohmann::json::object_t operatingConfig;
- operatingConfig["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId);
- json["OperatingConfigs"] = std::move(operatingConfig);
-
- // Reuse the D-Bus config object name for the Redfish
- // URI
- size_t baseNamePos = dbusPath.rfind('/');
- if (baseNamePos == std::string::npos ||
- baseNamePos == (dbusPath.size() - 1))
- {
- // If the AppliedConfig was somehow not a valid path,
- // skip adding any more properties, since everything
- // else is tied to this applied config.
+ if (!success)
+ {
messages::internalError(asyncResp->res);
return;
}
- nlohmann::json::object_t appliedOperatingConfig;
- appliedOperatingConfig["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId,
- dbusPath.substr(baseNamePos + 1));
- json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig);
-
- // Once we found the current applied config, queue another
- // request to read the base freq core ids out of that
- // config.
- sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
- *crow::connections::systemBus, service, dbusPath,
- "xyz.openbmc_project.Inventory.Item.Cpu."
- "OperatingConfig",
- "BaseSpeedPrioritySettings",
- [asyncResp](
- const boost::system::error_code& ec2,
- const BaseSpeedPrioritySettingsProperty& baseSpeedList) {
- if (ec2)
+
+ if (appliedConfig != nullptr)
+ {
+ const std::string& dbusPath = appliedConfig->str;
+ nlohmann::json::object_t operatingConfig;
+ operatingConfig["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId);
+ json["OperatingConfigs"] = std::move(operatingConfig);
+
+ // Reuse the D-Bus config object name for the Redfish
+ // URI
+ size_t baseNamePos = dbusPath.rfind('/');
+ if (baseNamePos == std::string::npos ||
+ baseNamePos == (dbusPath.size() - 1))
{
- BMCWEB_LOG_WARNING("D-Bus Property Get error: {}", ec2);
+ // If the AppliedConfig was somehow not a valid path,
+ // skip adding any more properties, since everything
+ // else is tied to this applied config.
messages::internalError(asyncResp->res);
return;
}
+ nlohmann::json::object_t appliedOperatingConfig;
+ appliedOperatingConfig["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuId,
+ dbusPath.substr(baseNamePos + 1));
+ json["AppliedOperatingConfig"] =
+ std::move(appliedOperatingConfig);
+
+ // Once we found the current applied config, queue another
+ // request to read the base freq core ids out of that
+ // config.
+ sdbusplus::asio::getProperty<BaseSpeedPrioritySettingsProperty>(
+ *crow::connections::systemBus, service, dbusPath,
+ "xyz.openbmc_project.Inventory.Item.Cpu."
+ "OperatingConfig",
+ "BaseSpeedPrioritySettings",
+ [asyncResp](const boost::system::error_code& ec2,
+ const BaseSpeedPrioritySettingsProperty&
+ baseSpeedList) {
+ if (ec2)
+ {
+ BMCWEB_LOG_WARNING("D-Bus Property Get error: {}",
+ ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
- });
- }
+ highSpeedCoreIdsHandler(asyncResp, baseSpeedList);
+ });
+ }
- if (baseSpeedPriorityEnabled != nullptr)
- {
- json["BaseSpeedPriorityState"] =
- *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
- }
- });
+ if (baseSpeedPriorityEnabled != nullptr)
+ {
+ json["BaseSpeedPriorityState"] =
+ *baseSpeedPriorityEnabled ? "Enabled" : "Disabled";
+ }
+ });
}
/**
@@ -715,16 +722,17 @@ inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
[objPath, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec, const std::string& property) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- property;
- });
+ asyncResp->res
+ .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+ property;
+ });
}
/**
@@ -746,15 +754,15 @@ inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"UniqueIdentifier",
[asyncResp](const boost::system::error_code& ec,
const std::string& id) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res
- .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
- });
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Failed to read cpu unique id: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res
+ .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id;
+ });
}
/**
@@ -790,57 +798,56 @@ inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
[resp, processorId, handler = std::forward<Handler>(handler)](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
- messages::internalError(resp->res);
- return;
- }
- for (const auto& [objectPath, serviceMap] : subtree)
- {
- // Ignore any objects which don't end with our desired cpu name
- if (!objectPath.ends_with(processorId))
+ if (ec)
{
- continue;
+ BMCWEB_LOG_DEBUG("DBUS response error: {}", ec);
+ messages::internalError(resp->res);
+ return;
}
-
- bool found = false;
- // Filter out objects that don't have the CPU-specific
- // interfaces to make sure we can return 404 on non-CPUs
- // (e.g. /redfish/../Processors/dimm0)
- for (const auto& [serviceName, interfaceList] : serviceMap)
+ for (const auto& [objectPath, serviceMap] : subtree)
{
- if (std::ranges::find_first_of(interfaceList,
- processorInterfaces) !=
- std::end(interfaceList))
+ // Ignore any objects which don't end with our desired cpu name
+ if (!objectPath.ends_with(processorId))
{
- found = true;
- break;
+ continue;
}
- }
- if (!found)
- {
- continue;
- }
+ bool found = false;
+ // Filter out objects that don't have the CPU-specific
+ // interfaces to make sure we can return 404 on non-CPUs
+ // (e.g. /redfish/../Processors/dimm0)
+ for (const auto& [serviceName, interfaceList] : serviceMap)
+ {
+ if (std::ranges::find_first_of(interfaceList,
+ processorInterfaces) !=
+ std::end(interfaceList))
+ {
+ found = true;
+ break;
+ }
+ }
- // Process the first object which does match our cpu name and
- // required interfaces, and potentially ignore any other
- // matching objects. Assume all interfaces we want to process
- // must be on the same object path.
+ if (!found)
+ {
+ continue;
+ }
- handler(objectPath, serviceMap);
- return;
- }
- messages::resourceNotFound(resp->res, "Processor", processorId);
- });
+ // Process the first object which does match our cpu name and
+ // required interfaces, and potentially ignore any other
+ // matching objects. Assume all interfaces we want to process
+ // must be on the same object path.
+
+ handler(objectPath, serviceMap);
+ return;
+ }
+ messages::resourceNotFound(resp->res, "Processor", processorId);
+ });
}
-inline void
- getProcessorData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& processorId,
- const std::string& objectPath,
- const dbus::utility::MapperServiceMap& serviceMap)
+inline void getProcessorData(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& processorId, const std::string& objectPath,
+ const dbus::utility::MapperServiceMap& serviceMap)
{
for (const auto& [serviceName, interfaceList] : serviceMap)
{
@@ -903,100 +910,101 @@ inline void
* @param[in] service D-Bus service name to query.
* @param[in] objPath D-Bus object to query.
*/
-inline void
- getOperatingConfigData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& service,
- const std::string& objPath)
+inline void getOperatingConfigData(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& service, const std::string& objPath)
{
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, service, objPath,
"xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const size_t* availableCoreCount = nullptr;
- const uint32_t* baseSpeed = nullptr;
- const uint32_t* maxJunctionTemperature = nullptr;
- const uint32_t* maxSpeed = nullptr;
- const uint32_t* powerLimit = nullptr;
- const TurboProfileProperty* turboProfile = nullptr;
- const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
- nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "AvailableCoreCount",
- availableCoreCount, "BaseSpeed", baseSpeed,
- "MaxJunctionTemperature", maxJunctionTemperature, "MaxSpeed",
- maxSpeed, "PowerLimit", powerLimit, "TurboProfile", turboProfile,
- "BaseSpeedPrioritySettings", baseSpeedPrioritySettings);
-
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ const size_t* availableCoreCount = nullptr;
+ const uint32_t* baseSpeed = nullptr;
+ const uint32_t* maxJunctionTemperature = nullptr;
+ const uint32_t* maxSpeed = nullptr;
+ const uint32_t* powerLimit = nullptr;
+ const TurboProfileProperty* turboProfile = nullptr;
+ const BaseSpeedPrioritySettingsProperty* baseSpeedPrioritySettings =
+ nullptr;
+
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties,
+ "AvailableCoreCount", availableCoreCount, "BaseSpeed",
+ baseSpeed, "MaxJunctionTemperature", maxJunctionTemperature,
+ "MaxSpeed", maxSpeed, "PowerLimit", powerLimit, "TurboProfile",
+ turboProfile, "BaseSpeedPrioritySettings",
+ baseSpeedPrioritySettings);
+
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- nlohmann::json& json = asyncResp->res.jsonValue;
+ nlohmann::json& json = asyncResp->res.jsonValue;
- if (availableCoreCount != nullptr)
- {
- json["TotalAvailableCoreCount"] = *availableCoreCount;
- }
+ if (availableCoreCount != nullptr)
+ {
+ json["TotalAvailableCoreCount"] = *availableCoreCount;
+ }
- if (baseSpeed != nullptr)
- {
- json["BaseSpeedMHz"] = *baseSpeed;
- }
+ if (baseSpeed != nullptr)
+ {
+ json["BaseSpeedMHz"] = *baseSpeed;
+ }
- if (maxJunctionTemperature != nullptr)
- {
- json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
- }
+ if (maxJunctionTemperature != nullptr)
+ {
+ json["MaxJunctionTemperatureCelsius"] = *maxJunctionTemperature;
+ }
- if (maxSpeed != nullptr)
- {
- json["MaxSpeedMHz"] = *maxSpeed;
- }
+ if (maxSpeed != nullptr)
+ {
+ json["MaxSpeedMHz"] = *maxSpeed;
+ }
- if (powerLimit != nullptr)
- {
- json["TDPWatts"] = *powerLimit;
- }
+ if (powerLimit != nullptr)
+ {
+ json["TDPWatts"] = *powerLimit;
+ }
- if (turboProfile != nullptr)
- {
- nlohmann::json& turboArray = json["TurboProfile"];
- turboArray = nlohmann::json::array();
- for (const auto& [turboSpeed, coreCount] : *turboProfile)
+ if (turboProfile != nullptr)
{
- nlohmann::json::object_t turbo;
- turbo["ActiveCoreCount"] = coreCount;
- turbo["MaxSpeedMHz"] = turboSpeed;
- turboArray.emplace_back(std::move(turbo));
+ nlohmann::json& turboArray = json["TurboProfile"];
+ turboArray = nlohmann::json::array();
+ for (const auto& [turboSpeed, coreCount] : *turboProfile)
+ {
+ nlohmann::json::object_t turbo;
+ turbo["ActiveCoreCount"] = coreCount;
+ turbo["MaxSpeedMHz"] = turboSpeed;
+ turboArray.emplace_back(std::move(turbo));
+ }
}
- }
- if (baseSpeedPrioritySettings != nullptr)
- {
- nlohmann::json& baseSpeedArray = json["BaseSpeedPrioritySettings"];
- baseSpeedArray = nlohmann::json::array();
- for (const auto& [baseSpeedMhz, coreList] :
- *baseSpeedPrioritySettings)
+ if (baseSpeedPrioritySettings != nullptr)
{
- nlohmann::json::object_t speed;
- speed["CoreCount"] = coreList.size();
- speed["CoreIDs"] = coreList;
- speed["BaseSpeedMHz"] = baseSpeedMhz;
- baseSpeedArray.emplace_back(std::move(speed));
+ nlohmann::json& baseSpeedArray =
+ json["BaseSpeedPrioritySettings"];
+ baseSpeedArray = nlohmann::json::array();
+ for (const auto& [baseSpeedMhz, coreList] :
+ *baseSpeedPrioritySettings)
+ {
+ nlohmann::json::object_t speed;
+ speed["CoreCount"] = coreList.size();
+ speed["CoreIDs"] = coreList;
+ speed["BaseSpeedMHz"] = baseSpeedMhz;
+ baseSpeedArray.emplace_back(std::move(speed));
+ }
}
- }
- });
+ });
}
/**
@@ -1064,11 +1072,10 @@ inline void patchAppliedOperatingConfig(
"AppliedConfig", configPath);
}
-inline void
- handleProcessorHead(crow::App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& /* systemName */,
- const std::string& /* processorId */)
+inline void handleProcessorHead(
+ crow::App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& /* systemName */, const std::string& /* processorId */)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -1098,77 +1105,81 @@ inline void requestRoutesOperatingConfigCollection(App& app)
BMCWEB_ROUTE(app,
"/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/")
.privileges(redfish::privileges::getOperatingConfigCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& cpuName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#OperatingConfigCollection.OperatingConfigCollection";
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName);
- asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
-
- // First find the matching CPU object so we know how to
- // constrain our search for related Config objects.
- const std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
- dbus::utility::getSubTreePaths(
- "/xyz/openbmc_project/inventory", 0, interfaces,
- [asyncResp, cpuName](
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse& objects) {
- if (ec)
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName,
+ const std::string& cpuName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
- messages::internalError(asyncResp->res);
return;
}
- for (const std::string& object : objects)
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
{
- if (!object.ends_with(cpuName))
- {
- continue;
- }
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- // Not expected that there will be multiple matching
- // CPU objects, but if there are just use the first
- // one.
-
- // Use the common search routine to construct the
- // Collection of all Config objects under this CPU.
- constexpr std::array<std::string_view, 1> interface{
- "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
- collection_util::getCollectionMembers(
- asyncResp,
- boost::urls::format(
- "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName),
- interface, object);
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
return;
}
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#OperatingConfigCollection.OperatingConfigCollection";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName);
+ asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
+
+ // First find the matching CPU object so we know how to
+ // constrain our search for related Config objects.
+ const std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"};
+ dbus::utility::getSubTreePaths(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ [asyncResp,
+ cpuName](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse&
+ objects) {
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
+ ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ for (const std::string& object : objects)
+ {
+ if (!object.ends_with(cpuName))
+ {
+ continue;
+ }
+
+ // Not expected that there will be multiple matching
+ // CPU objects, but if there are just use the first
+ // one.
+
+ // Use the common search routine to construct the
+ // Collection of all Config objects under this CPU.
+ constexpr std::array<std::string_view, 1> interface{
+ "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
+ collection_util::getCollectionMembers(
+ asyncResp,
+ boost::urls::format(
+ "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName),
+ interface, object);
+ return;
+ }
+ });
});
- });
}
inline void requestRoutesOperatingConfig(App& app)
@@ -1177,72 +1188,79 @@ inline void requestRoutesOperatingConfig(App& app)
app,
"/redfish/v1/Systems/<str>/Processors/<str>/OperatingConfigs/<str>/")
.privileges(redfish::privileges::getOperatingConfig)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName, const std::string& cpuName,
- const std::string& configName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- // Ask for all objects implementing OperatingConfig so we can search
- // for one with a matching name
- constexpr std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
- dbus::utility::getSubTree(
- "/xyz/openbmc_project/inventory", 0, interfaces,
- [asyncResp, cpuName, configName](
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName,
+ const std::string& cpuName,
+ const std::string& configName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec, ec.message());
- messages::internalError(asyncResp->res);
return;
}
- const std::string expectedEnding = cpuName + '/' + configName;
- for (const auto& [objectPath, serviceMap] : subtree)
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
{
- // Ignore any configs without matching cpuX/configY
- if (!objectPath.ends_with(expectedEnding) || serviceMap.empty())
- {
- continue;
- }
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- nlohmann::json& json = asyncResp->res.jsonValue;
- json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
- json["@odata.id"] = boost::urls::format(
- "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName, configName);
- json["Name"] = "Processor Profile";
- json["Id"] = configName;
-
- // Just use the first implementation of the object - not
- // expected that there would be multiple matching
- // services
- getOperatingConfigData(asyncResp, serviceMap.begin()->first,
- objectPath);
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
return;
}
- messages::resourceNotFound(asyncResp->res, "OperatingConfig",
- configName);
+ // Ask for all objects implementing OperatingConfig so we can search
+ // for one with a matching name
+ constexpr std::array<std::string_view, 1> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"};
+ dbus::utility::getSubTree(
+ "/xyz/openbmc_project/inventory", 0, interfaces,
+ [asyncResp, cpuName, configName](
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree) {
+ if (ec)
+ {
+ BMCWEB_LOG_WARNING("D-Bus error: {}, {}", ec,
+ ec.message());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string expectedEnding =
+ cpuName + '/' + configName;
+ for (const auto& [objectPath, serviceMap] : subtree)
+ {
+ // Ignore any configs without matching cpuX/configY
+ if (!objectPath.ends_with(expectedEnding) ||
+ serviceMap.empty())
+ {
+ continue;
+ }
+
+ nlohmann::json& json = asyncResp->res.jsonValue;
+ json["@odata.type"] =
+ "#OperatingConfig.v1_0_0.OperatingConfig";
+ json["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/Processors/{}/OperatingConfigs/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, cpuName,
+ configName);
+ json["Name"] = "Processor Profile";
+ json["Id"] = configName;
+
+ // Just use the first implementation of the object - not
+ // expected that there would be multiple matching
+ // services
+ getOperatingConfigData(
+ asyncResp, serviceMap.begin()->first, objectPath);
+ return;
+ }
+ messages::resourceNotFound(asyncResp->res,
+ "OperatingConfig", configName);
+ });
});
- });
}
inline void requestRoutesProcessorCollection(App& app)
@@ -1257,47 +1275,48 @@ inline void requestRoutesProcessorCollection(App& app)
BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/")
.privileges(redfish::privileges::getProcessorCollection)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/ProcessorCollection/ProcessorCollection.json>; rel=describedby");
- asyncResp->res.jsonValue["@odata.type"] =
- "#ProcessorCollection.ProcessorCollection";
- asyncResp->res.jsonValue["Name"] = "Processor Collection";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#ProcessorCollection.ProcessorCollection";
+ asyncResp->res.jsonValue["Name"] = "Processor Collection";
- asyncResp->res.jsonValue["@odata.id"] =
- std::format("/redfish/v1/Systems/{}/Processors",
- BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/Processors",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
- collection_util::getCollectionMembers(
- asyncResp,
- boost::urls::format("/redfish/v1/Systems/{}/Processors",
- BMCWEB_REDFISH_SYSTEM_URI_NAME),
- processorInterfaces, "/xyz/openbmc_project/inventory");
- });
+ collection_util::getCollectionMembers(
+ asyncResp,
+ boost::urls::format("/redfish/v1/Systems/{}/Processors",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME),
+ processorInterfaces, "/xyz/openbmc_project/inventory");
+ });
}
inline void requestRoutesProcessor(App& app)
@@ -1313,42 +1332,43 @@ inline void requestRoutesProcessor(App& app)
BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
.privileges(redfish::privileges::getProcessor)
- .methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& processorId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
-
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
- asyncResp->res.jsonValue["@odata.type"] =
- "#Processor.v1_18_0.Processor";
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Systems/{}/Processors/{}",
- BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId);
+ .methods(
+ boost::beast::http::verb::
+ get)([&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName,
+ const std::string& processorId) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- getProcessorObject(
- asyncResp, processorId,
- std::bind_front(getProcessorData, asyncResp, processorId));
- });
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#Processor.v1_18_0.Processor";
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/Processors/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId);
+
+ getProcessorObject(
+ asyncResp, processorId,
+ std::bind_front(getProcessorData, asyncResp, processorId));
+ });
BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Processors/<str>/")
.privileges(redfish::privileges::patchProcessor)
@@ -1357,42 +1377,42 @@ inline void requestRoutesProcessor(App& app)
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& systemName,
const std::string& processorId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
- {
- // Option currently returns no systems. TBD
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
- if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
- {
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- systemName);
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
- std::optional<std::string> appliedConfigUri;
- if (!json_util::readJsonPatch(req, asyncResp->res,
- "AppliedOperatingConfig/@odata.id",
- appliedConfigUri))
- {
- return;
- }
+ std::optional<std::string> appliedConfigUri;
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res, "AppliedOperatingConfig/@odata.id",
+ appliedConfigUri))
+ {
+ return;
+ }
- if (appliedConfigUri)
- {
- // Check for 404 and find matching D-Bus object, then run
- // property patch handlers if that all succeeds.
- getProcessorObject(asyncResp, processorId,
- std::bind_front(patchAppliedOperatingConfig,
- asyncResp, processorId,
- *appliedConfigUri));
- }
- });
+ if (appliedConfigUri)
+ {
+ // Check for 404 and find matching D-Bus object, then run
+ // property patch handlers if that all succeeds.
+ getProcessorObject(
+ asyncResp, processorId,
+ std::bind_front(patchAppliedOperatingConfig, asyncResp,
+ processorId, *appliedConfigUri));
+ }
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index 555e7f32ac..48d53bfd94 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -1,22 +1,23 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "account_service.hpp"
#include "app.hpp"
+#include "cookies.hpp"
#include "error_messages.hpp"
#include "http/utility.hpp"
#include "persistent_data.hpp"
@@ -26,6 +27,9 @@
#include <boost/url/format.hpp>
+#include <string>
+#include <vector>
+
namespace redfish
{
@@ -125,21 +129,26 @@ inline void
}
}
+ if (req.session != nullptr && req.session->uniqueId == sessionId &&
+ session->cookieAuth)
+ {
+ bmcweb::clearSessionCookies(asyncResp->res);
+ }
+
persistent_data::SessionStore::getInstance().removeSession(session);
messages::success(asyncResp->res);
}
inline nlohmann::json getSessionCollectionMembers()
{
- std::vector<const std::string*> sessionIds =
- persistent_data::SessionStore::getInstance().getUniqueIds(
- false, persistent_data::PersistenceType::TIMEOUT);
+ std::vector<std::string> sessionIds =
+ persistent_data::SessionStore::getInstance().getAllUniqueIds();
nlohmann::json ret = nlohmann::json::array();
- for (const std::string* uid : sessionIds)
+ for (const std::string& uid : sessionIds)
{
nlohmann::json::object_t session;
session["@odata.id"] =
- boost::urls::format("/redfish/v1/SessionService/Sessions/{}", *uid);
+ boost::urls::format("/redfish/v1/SessionService/Sessions/{}", uid);
ret.emplace_back(std::move(session));
}
return ret;
@@ -203,12 +212,13 @@ inline void handleSessionCollectionPost(
std::string username;
std::string password;
std::optional<std::string> clientId;
+ std::optional<std::string> token;
if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", username,
- "Password", password, "Context", clientId))
+ "Password", password, "Token", token,
+ "Context", clientId))
{
return;
}
-
if (password.empty() || username.empty() ||
asyncResp->res.result() != boost::beast::http::status::ok)
{
@@ -225,7 +235,7 @@ inline void handleSessionCollectionPost(
return;
}
- int pamrc = pamAuthenticateUser(username, password);
+ int pamrc = pamAuthenticateUser(username, password, token);
bool isConfigureSelfOnly = pamrc == PAM_NEW_AUTHTOK_REQD;
if ((pamrc != PAM_SUCCESS) && !isConfigureSelfOnly)
{
@@ -238,14 +248,25 @@ inline void handleSessionCollectionPost(
std::shared_ptr<persistent_data::UserSession> session =
persistent_data::SessionStore::getInstance().generateUserSession(
username, req.ipAddress, clientId,
- persistent_data::PersistenceType::TIMEOUT, isConfigureSelfOnly);
+ persistent_data::SessionType::Session, isConfigureSelfOnly);
if (session == nullptr)
{
messages::internalError(asyncResp->res);
return;
}
- asyncResp->res.addHeader("X-Auth-Token", session->sessionToken);
+ // When session is created by webui-vue give it session cookies as a
+ // non-standard Redfish extension. This is needed for authentication for
+ // WebSockets-based functionality.
+ if (!req.getHeaderValue("X-Requested-With").empty())
+ {
+ bmcweb::setSessionCookies(asyncResp->res, *session);
+ }
+ else
+ {
+ asyncResp->res.addHeader("X-Auth-Token", session->sessionToken);
+ }
+
asyncResp->res.addHeader(
"Location", "/redfish/v1/SessionService/Sessions/" + session->uniqueId);
asyncResp->res.result(boost::beast::http::status::created);
diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp
index 8fe2bbc400..4164e10775 100644
--- a/redfish-core/lib/redfish_util.hpp
+++ b/redfish-core/lib/redfish_util.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2019 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2019 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -71,29 +71,29 @@ void getMainChassisId(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[callback = std::forward<CallbackFunc>(callback),
asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("{}", ec);
- return;
- }
- if (subtree.empty())
- {
- BMCWEB_LOG_DEBUG("Can't find chassis!");
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("{}", ec);
+ return;
+ }
+ if (subtree.empty())
+ {
+ BMCWEB_LOG_DEBUG("Can't find chassis!");
+ return;
+ }
- std::size_t idPos = subtree[0].first.rfind('/');
- if (idPos == std::string::npos ||
- (idPos + 1) >= subtree[0].first.size())
- {
- messages::internalError(asyncResp->res);
- BMCWEB_LOG_DEBUG("Can't parse chassis ID!");
- return;
- }
- std::string chassisId = subtree[0].first.substr(idPos + 1);
- BMCWEB_LOG_DEBUG("chassisId = {}", chassisId);
- callback(chassisId, asyncResp);
- });
+ std::size_t idPos = subtree[0].first.rfind('/');
+ if (idPos == std::string::npos ||
+ (idPos + 1) >= subtree[0].first.size())
+ {
+ messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG("Can't parse chassis ID!");
+ return;
+ }
+ std::string chassisId = subtree[0].first.substr(idPos + 1);
+ BMCWEB_LOG_DEBUG("chassisId = {}", chassisId);
+ callback(chassisId, asyncResp);
+ });
}
template <typename CallbackFunc>
@@ -106,99 +106,101 @@ void getPortStatusAndPath(
[protocolToDBus, callback = std::forward<CallbackFunc>(callback)](
const boost::system::error_code& ec,
const std::vector<UnitStruct>& r) {
- std::vector<std::tuple<std::string, std::string, bool>> socketData;
- if (ec)
- {
- BMCWEB_LOG_ERROR("{}", ec);
- // return error code
- callback(ec, socketData);
- return;
- }
-
- // save all service output into vector
- for (const UnitStruct& unit : r)
- {
- // Only traverse through <xyz>.socket units
- const std::string& unitName = std::get<NET_PROTO_UNIT_NAME>(unit);
-
- // find "." into unitsName
- size_t lastCharPos = unitName.rfind('.');
- if (lastCharPos == std::string::npos)
+ std::vector<std::tuple<std::string, std::string, bool>> socketData;
+ if (ec)
{
- continue;
+ BMCWEB_LOG_ERROR("{}", ec);
+ // return error code
+ callback(ec, socketData);
+ return;
}
- // is unitsName end with ".socket"
- std::string unitNameEnd = unitName.substr(lastCharPos);
- if (unitNameEnd != ".socket")
+ // save all service output into vector
+ for (const UnitStruct& unit : r)
{
- continue;
- }
+ // Only traverse through <xyz>.socket units
+ const std::string& unitName =
+ std::get<NET_PROTO_UNIT_NAME>(unit);
- // find "@" into unitsName
- if (size_t atCharPos = unitName.rfind('@');
- atCharPos != std::string::npos)
- {
- lastCharPos = atCharPos;
- }
-
- // unitsName without "@eth(x).socket", only <xyz>
- // unitsName without ".socket", only <xyz>
- std::string unitNameStr = unitName.substr(0, lastCharPos);
+ // find "." into unitsName
+ size_t lastCharPos = unitName.rfind('.');
+ if (lastCharPos == std::string::npos)
+ {
+ continue;
+ }
- for (const auto& kv : protocolToDBus)
- {
- // We are interested in services, which starts with
- // mapped service name
- if (unitNameStr != kv.second)
+ // is unitsName end with ".socket"
+ std::string unitNameEnd = unitName.substr(lastCharPos);
+ if (unitNameEnd != ".socket")
{
continue;
}
- const std::string& socketPath =
- std::get<NET_PROTO_UNIT_OBJ_PATH>(unit);
- const std::string& unitState =
- std::get<NET_PROTO_UNIT_SUB_STATE>(unit);
+ // find "@" into unitsName
+ if (size_t atCharPos = unitName.rfind('@');
+ atCharPos != std::string::npos)
+ {
+ lastCharPos = atCharPos;
+ }
- bool isProtocolEnabled = ((unitState == "running") ||
- (unitState == "listening"));
+ // unitsName without "@eth(x).socket", only <xyz>
+ // unitsName without ".socket", only <xyz>
+ std::string unitNameStr = unitName.substr(0, lastCharPos);
- // Some protocols may have multiple services associated with
- // them (for example IPMI). Look to see if we've already added
- // an entry for the current protocol.
- auto find = std::ranges::find_if(
- socketData,
- [&kv](const std::tuple<std::string, std::string, bool>& i) {
- return std::get<1>(i) == kv.first;
- });
- if (find != socketData.end())
+ for (const auto& kv : protocolToDBus)
{
- // It only takes one enabled systemd service to consider a
- // protocol enabled so if the current entry already has it
- // enabled (or the new one is disabled) then just continue,
- // otherwise remove the current one and add this new one.
- if (std::get<2>(*find) || !isProtocolEnabled)
+ // We are interested in services, which starts with
+ // mapped service name
+ if (unitNameStr != kv.second)
{
- // Already registered as enabled or current one is not
- // enabled, nothing to do
- BMCWEB_LOG_DEBUG(
- "protocolName: {}, already true or current one is false: {}",
- kv.first, isProtocolEnabled);
- break;
+ continue;
+ }
+
+ const std::string& socketPath =
+ std::get<NET_PROTO_UNIT_OBJ_PATH>(unit);
+ const std::string& unitState =
+ std::get<NET_PROTO_UNIT_SUB_STATE>(unit);
+
+ bool isProtocolEnabled = ((unitState == "running") ||
+ (unitState == "listening"));
+
+ // Some protocols may have multiple services associated with
+ // them (for example IPMI). Look to see if we've already
+ // added an entry for the current protocol.
+ auto find = std::ranges::find_if(
+ socketData,
+ [&kv](const std::tuple<std::string, std::string, bool>&
+ i) { return std::get<1>(i) == kv.first; });
+ if (find != socketData.end())
+ {
+ // It only takes one enabled systemd service to consider
+ // a protocol enabled so if the current entry already
+ // has it enabled (or the new one is disabled) then just
+ // continue, otherwise remove the current one and add
+ // this new one.
+ if (std::get<2>(*find) || !isProtocolEnabled)
+ {
+ // Already registered as enabled or current one is
+ // not enabled, nothing to do
+ BMCWEB_LOG_DEBUG(
+ "protocolName: {}, already true or current one is false: {}",
+ kv.first, isProtocolEnabled);
+ break;
+ }
+ // Remove existing entry and replace with new one
+ // (below)
+ socketData.erase(find);
}
- // Remove existing entry and replace with new one (below)
- socketData.erase(find);
- }
- socketData.emplace_back(socketPath, std::string(kv.first),
- isProtocolEnabled);
- // We found service, return from inner loop.
- break;
+ socketData.emplace_back(socketPath, std::string(kv.first),
+ isProtocolEnabled);
+ // We found service, return from inner loop.
+ break;
+ }
}
- }
- callback(ec, socketData);
- },
+ callback(ec, socketData);
+ },
"org.freedesktop.systemd1", "/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager", "ListUnits");
}
@@ -213,46 +215,46 @@ void getPortNumber(const std::string& socketPath, CallbackFunc&& callback)
[callback = std::forward<CallbackFunc>(callback)](
const boost::system::error_code& ec,
const std::vector<std::tuple<std::string, std::string>>& resp) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("{}", ec);
- callback(ec, 0);
- return;
- }
- if (resp.empty())
- {
- // Network Protocol Listen Response Elements is empty
- boost::system::error_code ec1 =
- boost::system::errc::make_error_code(
- boost::system::errc::bad_message);
- // return error code
- callback(ec1, 0);
- BMCWEB_LOG_ERROR("{}", ec1);
- return;
- }
- const std::string& listenStream =
- std::get<NET_PROTO_LISTEN_STREAM>(resp[0]);
- const char* pa = &listenStream[listenStream.rfind(':') + 1];
- int port{0};
- if (auto [p, ec2] = std::from_chars(pa, nullptr, port);
- ec2 != std::errc())
- {
- // there is only two possibility invalid_argument and
- // result_out_of_range
- boost::system::error_code ec3 =
- boost::system::errc::make_error_code(
- boost::system::errc::invalid_argument);
- if (ec2 == std::errc::result_out_of_range)
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("{}", ec);
+ callback(ec, 0);
+ return;
+ }
+ if (resp.empty())
{
- ec3 = boost::system::errc::make_error_code(
- boost::system::errc::result_out_of_range);
+ // Network Protocol Listen Response Elements is empty
+ boost::system::error_code ec1 =
+ boost::system::errc::make_error_code(
+ boost::system::errc::bad_message);
+ // return error code
+ callback(ec1, 0);
+ BMCWEB_LOG_ERROR("{}", ec1);
+ return;
+ }
+ const std::string& listenStream =
+ std::get<NET_PROTO_LISTEN_STREAM>(resp[0]);
+ const char* pa = &listenStream[listenStream.rfind(':') + 1];
+ int port{0};
+ if (auto [p, ec2] = std::from_chars(pa, nullptr, port);
+ ec2 != std::errc())
+ {
+ // there is only two possibility invalid_argument and
+ // result_out_of_range
+ boost::system::error_code ec3 =
+ boost::system::errc::make_error_code(
+ boost::system::errc::invalid_argument);
+ if (ec2 == std::errc::result_out_of_range)
+ {
+ ec3 = boost::system::errc::make_error_code(
+ boost::system::errc::result_out_of_range);
+ }
+ // return error code
+ callback(ec3, 0);
+ BMCWEB_LOG_ERROR("{}", ec3);
}
- // return error code
- callback(ec3, 0);
- BMCWEB_LOG_ERROR("{}", ec3);
- }
- callback(ec, port);
- });
+ callback(ec, port);
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/redfish_v1.hpp b/redfish-core/lib/redfish_v1.hpp
index bbda45bcdd..418f66c431 100644
--- a/redfish-core/lib/redfish_v1.hpp
+++ b/redfish-core/lib/redfish_v1.hpp
@@ -6,7 +6,6 @@
#include "http_response.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
-#include "schemas.hpp"
#include "utility.hpp"
#include <boost/url/format.hpp>
@@ -86,15 +85,32 @@ inline void
json["Name"] = "JsonSchemaFile Collection";
json["Description"] = "Collection of JsonSchemaFiles";
nlohmann::json::array_t members;
- for (std::string_view schema : schemas)
+
+ std::error_code ec;
+ std::filesystem::directory_iterator dirList(
+ "/usr/share/www/redfish/v1/JsonSchemas", ec);
+ if (ec)
{
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ for (const std::filesystem::path& file : dirList)
+ {
+ std::string filename = file.filename();
+ std::vector<std::string> split;
+ bmcweb::split(split, filename, '.');
+ if (split.empty())
+ {
+ continue;
+ }
nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format("/redfish/v1/JsonSchemas/{}",
- schema);
+ member["@odata.id"] =
+ boost::urls::format("/redfish/v1/JsonSchemas/{}", split[0]);
members.emplace_back(std::move(member));
}
+
+ json["Members@odata.count"] = members.size();
json["Members"] = std::move(members);
- json["Members@odata.count"] = schemas.size();
}
inline void jsonSchemaGet(App& app, const crow::Request& req,
@@ -106,40 +122,100 @@ inline void jsonSchemaGet(App& app, const crow::Request& req,
return;
}
- if (std::ranges::find(schemas, schema) == schemas.end())
+ std::error_code ec;
+ std::filesystem::directory_iterator dirList(
+ "/usr/share/www/redfish/v1/JsonSchemas", ec);
+ if (ec)
{
messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
return;
}
+ for (const std::filesystem::path& file : dirList)
+ {
+ std::string filename = file.filename();
+ std::vector<std::string> split;
+ bmcweb::split(split, filename, '.');
+ if (split.empty())
+ {
+ continue;
+ }
+ BMCWEB_LOG_DEBUG("Checking {}", split[0]);
+ if (split[0] != schema)
+ {
+ continue;
+ }
+
+ nlohmann::json& json = asyncResp->res.jsonValue;
+ json["@odata.id"] =
+ boost::urls::format("/redfish/v1/JsonSchemas/{}", schema);
+ json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile";
+ json["Name"] = schema + " Schema File";
+ json["Description"] = schema + " Schema File Location";
+ json["Id"] = schema;
+ std::string schemaName = std::format("#{}.{}", schema, schema);
+ json["Schema"] = std::move(schemaName);
+ constexpr std::array<std::string_view, 1> languages{"en"};
+ json["Languages"] = languages;
+ json["Languages@odata.count"] = languages.size();
+
+ nlohmann::json::array_t locationArray;
+ nlohmann::json::object_t locationEntry;
+ locationEntry["Language"] = "en";
+
+ locationEntry["PublicationUri"] = boost::urls::format(
+ "http://redfish.dmtf.org/schemas/v1/{}", filename);
+ locationEntry["Uri"] = boost::urls::format(
+ "/redfish/v1/JsonSchemas/{}/{}", schema, filename);
+
+ locationArray.emplace_back(locationEntry);
+
+ json["Location"] = std::move(locationArray);
+ json["Location@odata.count"] = 1;
+ return;
+ }
+ messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
+}
- nlohmann::json& json = asyncResp->res.jsonValue;
- json["@odata.id"] = boost::urls::format("/redfish/v1/JsonSchemas/{}",
- schema);
- json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile";
- json["Name"] = schema + " Schema File";
- json["Description"] = schema + " Schema File Location";
- json["Id"] = schema;
- std::string schemaName = "#";
- schemaName += schema;
- schemaName += ".";
- schemaName += schema;
- json["Schema"] = std::move(schemaName);
- constexpr std::array<std::string_view, 1> languages{"en"};
- json["Languages"] = languages;
- json["Languages@odata.count"] = languages.size();
-
- nlohmann::json::array_t locationArray;
- nlohmann::json::object_t locationEntry;
- locationEntry["Language"] = "en";
- locationEntry["PublicationUri"] = "http://redfish.dmtf.org/schemas/v1/" +
- schema + ".json";
- locationEntry["Uri"] = boost::urls::format(
- "/redfish/v1/JsonSchemas/{}/{}", schema, std::string(schema) + ".json");
-
- locationArray.emplace_back(locationEntry);
-
- json["Location"] = std::move(locationArray);
- json["Location@odata.count"] = 1;
+inline void
+ jsonSchemaGetFile(const crow::Request& /*req*/,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& schema, const std::string& schemaFile)
+{
+ // Sanity check the filename
+ if (schemaFile.find_first_not_of(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.") !=
+ std::string::npos)
+ {
+ messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
+ return;
+ }
+ // Schema path should look like /redfish/v1/JsonSchemas/Foo/Foo.x.json
+ // Make sure the two paths match.
+ if (!schemaFile.starts_with(schema))
+ {
+ messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
+ return;
+ }
+ std::filesystem::path filepath("/usr/share/www/redfish/v1/JsonSchemas");
+ filepath /= schemaFile;
+ if (filepath.is_relative())
+ {
+ messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
+ return;
+ }
+
+ crow::OpenCode ec = asyncResp->res.openFile(filepath);
+ if (ec == crow::OpenCode::FileDoesNotExist)
+ {
+ messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema);
+ return;
+ }
+ if (ec == crow::OpenCode::InternalError)
+ {
+ BMCWEB_LOG_DEBUG("failed to read file");
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
inline void requestRoutesRedfish(App& app)
@@ -148,6 +224,10 @@ inline void requestRoutesRedfish(App& app)
.methods(boost::beast::http::verb::get)(
std::bind_front(redfishGet, std::ref(app)));
+ BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/<str>")
+ .privileges(redfish::privileges::getJsonSchemaFile)
+ .methods(boost::beast::http::verb::get)(jsonSchemaGetFile);
+
BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/")
.privileges(redfish::privileges::getJsonSchemaFileCollection)
.methods(boost::beast::http::verb::get)(
diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp
index a0f4f34754..c17a2256be 100644
--- a/redfish-core/lib/roles.hpp
+++ b/redfish-core/lib/roles.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -85,31 +85,33 @@ inline void requestRoutesRoles(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& roleId) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- std::optional<nlohmann::json::array_t> privArray =
- getAssignedPrivFromRole(roleId);
- if (!privArray)
- {
- messages::resourceNotFound(asyncResp->res, "Role", roleId);
-
- return;
- }
-
- asyncResp->res.jsonValue["@odata.type"] = "#Role.v1_2_2.Role";
- asyncResp->res.jsonValue["Name"] = "User Role";
- asyncResp->res.jsonValue["Description"] = roleId + " User Role";
- asyncResp->res.jsonValue["OemPrivileges"] = nlohmann::json::array();
- asyncResp->res.jsonValue["IsPredefined"] = true;
- asyncResp->res.jsonValue["Id"] = roleId;
- asyncResp->res.jsonValue["RoleId"] = roleId;
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/AccountService/Roles/{}", roleId);
- asyncResp->res.jsonValue["AssignedPrivileges"] = std::move(*privArray);
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ std::optional<nlohmann::json::array_t> privArray =
+ getAssignedPrivFromRole(roleId);
+ if (!privArray)
+ {
+ messages::resourceNotFound(asyncResp->res, "Role", roleId);
+
+ return;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] = "#Role.v1_2_2.Role";
+ asyncResp->res.jsonValue["Name"] = "User Role";
+ asyncResp->res.jsonValue["Description"] = roleId + " User Role";
+ asyncResp->res.jsonValue["OemPrivileges"] =
+ nlohmann::json::array();
+ asyncResp->res.jsonValue["IsPredefined"] = true;
+ asyncResp->res.jsonValue["Id"] = roleId;
+ asyncResp->res.jsonValue["RoleId"] = roleId;
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/AccountService/Roles/{}", roleId);
+ asyncResp->res.jsonValue["AssignedPrivileges"] =
+ std::move(*privArray);
+ });
}
inline void requestRoutesRoleCollection(App& app)
@@ -119,46 +121,49 @@ inline void requestRoutesRoleCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
-
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/AccountService/Roles";
- asyncResp->res.jsonValue["@odata.type"] =
- "#RoleCollection.RoleCollection";
- asyncResp->res.jsonValue["Name"] = "Roles Collection";
- asyncResp->res.jsonValue["Description"] = "BMC User Roles";
-
- sdbusplus::asio::getProperty<std::vector<std::string>>(
- *crow::connections::systemBus, "xyz.openbmc_project.User.Manager",
- "/xyz/openbmc_project/user", "xyz.openbmc_project.User.Manager",
- "AllPrivileges",
- [asyncResp](const boost::system::error_code& ec,
- const std::vector<std::string>& privList) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"];
- memberArray = nlohmann::json::array();
- for (const std::string& priv : privList)
- {
- std::string role = getRoleFromPrivileges(priv);
- if (!role.empty())
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/AccountService/Roles/{}", role);
- memberArray.emplace_back(std::move(member));
+ return;
}
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- memberArray.size();
- });
- });
+
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/AccountService/Roles";
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#RoleCollection.RoleCollection";
+ asyncResp->res.jsonValue["Name"] = "Roles Collection";
+ asyncResp->res.jsonValue["Description"] = "BMC User Roles";
+
+ sdbusplus::asio::getProperty<std::vector<std::string>>(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.User.Manager",
+ "/xyz/openbmc_project/user",
+ "xyz.openbmc_project.User.Manager", "AllPrivileges",
+ [asyncResp](const boost::system::error_code& ec,
+ const std::vector<std::string>& privList) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ nlohmann::json& memberArray =
+ asyncResp->res.jsonValue["Members"];
+ memberArray = nlohmann::json::array();
+ for (const std::string& priv : privList)
+ {
+ std::string role = getRoleFromPrivileges(priv);
+ if (!role.empty())
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/AccountService/Roles/{}",
+ role);
+ memberArray.emplace_back(std::move(member));
+ }
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ memberArray.size();
+ });
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 8be861ba65..f344220b01 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -1,31 +1,32 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "dbus_singleton.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/redundancy.hpp"
#include "generated/enums/resource.hpp"
-#include "generated/enums/sensor.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "str_utility.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/query_param.hpp"
+#include "utils/sensor_utils.hpp"
#include <boost/system/error_code.hpp>
#include <boost/url/format.hpp>
@@ -49,12 +50,6 @@ namespace redfish
namespace sensors
{
-namespace node
-{
-static constexpr std::string_view power = "Power";
-static constexpr std::string_view sensors = "Sensors";
-static constexpr std::string_view thermal = "Thermal";
-} // namespace node
// clang-format off
namespace dbus
@@ -98,99 +93,22 @@ constexpr auto thermalPaths = std::to_array<std::string_view>({
} // namespace dbus
// clang-format on
+constexpr std::string_view powerNodeStr = sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::powerNode);
+constexpr std::string_view sensorsNodeStr =
+ sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::sensorsNode);
+constexpr std::string_view thermalNodeStr =
+ sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::thermalNode);
+
using sensorPair =
std::pair<std::string_view, std::span<const std::string_view>>;
static constexpr std::array<sensorPair, 3> paths = {
- {{node::power, dbus::powerPaths},
- {node::sensors, dbus::sensorPaths},
- {node::thermal, dbus::thermalPaths}}};
-
-inline sensor::ReadingType toReadingType(std::string_view sensorType)
-{
- if (sensorType == "voltage")
- {
- return sensor::ReadingType::Voltage;
- }
- if (sensorType == "power")
- {
- return sensor::ReadingType::Power;
- }
- if (sensorType == "current")
- {
- return sensor::ReadingType::Current;
- }
- if (sensorType == "fan_tach")
- {
- return sensor::ReadingType::Rotational;
- }
- if (sensorType == "temperature")
- {
- return sensor::ReadingType::Temperature;
- }
- if (sensorType == "fan_pwm" || sensorType == "utilization")
- {
- return sensor::ReadingType::Percent;
- }
- if (sensorType == "humidity")
- {
- return sensor::ReadingType::Humidity;
- }
- if (sensorType == "altitude")
- {
- return sensor::ReadingType::Altitude;
- }
- if (sensorType == "airflow")
- {
- return sensor::ReadingType::AirFlow;
- }
- if (sensorType == "energy")
- {
- return sensor::ReadingType::EnergyJoules;
- }
- return sensor::ReadingType::Invalid;
-}
+ {{sensors::powerNodeStr, dbus::powerPaths},
+ {sensors::sensorsNodeStr, dbus::sensorPaths},
+ {sensors::thermalNodeStr, dbus::thermalPaths}}};
-inline std::string_view toReadingUnits(std::string_view sensorType)
-{
- if (sensorType == "voltage")
- {
- return "V";
- }
- if (sensorType == "power")
- {
- return "W";
- }
- if (sensorType == "current")
- {
- return "A";
- }
- if (sensorType == "fan_tach")
- {
- return "RPM";
- }
- if (sensorType == "temperature")
- {
- return "Cel";
- }
- if (sensorType == "fan_pwm" || sensorType == "utilization" ||
- sensorType == "humidity")
- {
- return "%";
- }
- if (sensorType == "altitude")
- {
- return "m";
- }
- if (sensorType == "airflow")
- {
- return "cft_i/min";
- }
- if (sensorType == "energy")
- {
- return "J";
- }
- return "";
-}
} // namespace sensors
/**
@@ -206,18 +124,17 @@ class SensorsAsyncResp
struct SensorData
{
- const std::string name;
+ std::string name;
std::string uri;
- const std::string dbusPath;
+ std::string dbusPath;
};
SensorsAsyncResp(const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn,
const std::string& chassisIdIn,
std::span<const std::string_view> typesIn,
std::string_view subNode) :
- asyncResp(asyncRespIn),
- chassisId(chassisIdIn), types(typesIn), chassisSubNode(subNode),
- efficientExpand(false)
+ asyncResp(asyncRespIn), chassisId(chassisIdIn), types(typesIn),
+ chassisSubNode(subNode), efficientExpand(false)
{}
// Store extra data about sensor mapping and return it in callback
@@ -226,9 +143,9 @@ class SensorsAsyncResp
std::span<const std::string_view> typesIn,
std::string_view subNode,
DataCompleteCb&& creationComplete) :
- asyncResp(asyncRespIn),
- chassisId(chassisIdIn), types(typesIn), chassisSubNode(subNode),
- efficientExpand(false), metadata{std::vector<SensorData>()},
+ asyncResp(asyncRespIn), chassisId(chassisIdIn), types(typesIn),
+ chassisSubNode(subNode), efficientExpand(false),
+ metadata{std::vector<SensorData>()},
dataComplete{std::move(creationComplete)}
{}
@@ -237,9 +154,8 @@ class SensorsAsyncResp
const std::string& chassisIdIn,
std::span<const std::string_view> typesIn,
const std::string_view& subNode, bool efficientExpandIn) :
- asyncResp(asyncRespIn),
- chassisId(chassisIdIn), types(typesIn), chassisSubNode(subNode),
- efficientExpand(efficientExpandIn)
+ asyncResp(asyncRespIn), chassisId(chassisIdIn), types(typesIn),
+ chassisSubNode(subNode), efficientExpand(efficientExpandIn)
{}
~SensorsAsyncResp()
@@ -307,48 +223,7 @@ class SensorsAsyncResp
DataCompleteCb dataComplete;
};
-/**
- * Possible states for physical inventory leds
- */
-enum class LedState
-{
- OFF,
- ON,
- BLINK,
- UNKNOWN
-};
-
-/**
- * D-Bus inventory item associated with one or more sensors.
- */
-class InventoryItem
-{
- public:
- explicit InventoryItem(const std::string& objPath) : objectPath(objPath)
- {
- // Set inventory item name to last node of object path
- sdbusplus::message::object_path path(objectPath);
- name = path.filename();
- if (name.empty())
- {
- BMCWEB_LOG_ERROR("Failed to find '/' in {}", objectPath);
- }
- }
-
- std::string objectPath;
- std::string name;
- bool isPresent = true;
- bool isFunctional = true;
- bool isPowerSupply = false;
- int powerSupplyEfficiencyPercent = -1;
- std::string manufacturer;
- std::string model;
- std::string partNumber;
- std::string serialNumber;
- std::set<std::string> sensors;
- std::string ledObjectPath;
- LedState ledState = LedState::UNKNOWN;
-};
+using InventoryItem = sensor_utils::InventoryItem;
/**
* @brief Get objects with connection necessary for sensors
@@ -373,50 +248,51 @@ void getObjectsWithConnection(
[callback = std::forward<Callback>(callback), sensorsAsyncResp,
sensorNames](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- // Response handler for parsing objects subtree
- BMCWEB_LOG_DEBUG("getObjectsWithConnection resp_handler enter");
- if (ec)
- {
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- BMCWEB_LOG_ERROR(
- "getObjectsWithConnection resp_handler: Dbus error {}", ec);
- return;
- }
+ // Response handler for parsing objects subtree
+ BMCWEB_LOG_DEBUG("getObjectsWithConnection resp_handler enter");
+ if (ec)
+ {
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ BMCWEB_LOG_ERROR(
+ "getObjectsWithConnection resp_handler: Dbus error {}", ec);
+ return;
+ }
- BMCWEB_LOG_DEBUG("Found {} subtrees", subtree.size());
+ BMCWEB_LOG_DEBUG("Found {} subtrees", subtree.size());
- // Make unique list of connections only for requested sensor types and
- // found in the chassis
- std::set<std::string> connections;
- std::set<std::pair<std::string, std::string>> objectsWithConnection;
+ // Make unique list of connections only for requested sensor types
+ // and found in the chassis
+ std::set<std::string> connections;
+ std::set<std::pair<std::string, std::string>> objectsWithConnection;
- BMCWEB_LOG_DEBUG("sensorNames list count: {}", sensorNames->size());
- for (const std::string& tsensor : *sensorNames)
- {
- BMCWEB_LOG_DEBUG("Sensor to find: {}", tsensor);
- }
+ BMCWEB_LOG_DEBUG("sensorNames list count: {}", sensorNames->size());
+ for (const std::string& tsensor : *sensorNames)
+ {
+ BMCWEB_LOG_DEBUG("Sensor to find: {}", tsensor);
+ }
- for (const std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- if (sensorNames->find(object.first) != sensorNames->end())
+ for (const std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>&
+ object : subtree)
{
- for (const std::pair<std::string, std::vector<std::string>>&
- objData : object.second)
+ if (sensorNames->find(object.first) != sensorNames->end())
{
- BMCWEB_LOG_DEBUG("Adding connection: {}", objData.first);
- connections.insert(objData.first);
- objectsWithConnection.insert(
- std::make_pair(object.first, objData.first));
+ for (const std::pair<std::string, std::vector<std::string>>&
+ objData : object.second)
+ {
+ BMCWEB_LOG_DEBUG("Adding connection: {}",
+ objData.first);
+ connections.insert(objData.first);
+ objectsWithConnection.insert(
+ std::make_pair(object.first, objData.first));
+ }
}
}
- }
- BMCWEB_LOG_DEBUG("Found {} connections", connections.size());
- callback(std::move(connections), std::move(objectsWithConnection));
- BMCWEB_LOG_DEBUG("getObjectsWithConnection resp_handler exit");
- });
+ BMCWEB_LOG_DEBUG("Found {} connections", connections.size());
+ callback(std::move(connections), std::move(objectsWithConnection));
+ BMCWEB_LOG_DEBUG("getObjectsWithConnection resp_handler exit");
+ });
BMCWEB_LOG_DEBUG("getObjectsWithConnection exit");
}
@@ -458,7 +334,7 @@ inline void reduceSensorList(
if ((allSensors == nullptr) || (activeSensors == nullptr))
{
messages::resourceNotFound(res, chassisSubNode,
- chassisSubNode == sensors::node::thermal
+ chassisSubNode == sensors::thermalNodeStr
? "Temperatures"
: "Voltages");
@@ -490,17 +366,17 @@ inline void reduceSensorList(
inline void populateChassisNode(nlohmann::json& jsonValue,
std::string_view chassisSubNode)
{
- if (chassisSubNode == sensors::node::power)
+ if (chassisSubNode == sensors::powerNodeStr)
{
jsonValue["@odata.type"] = "#Power.v1_5_2.Power";
}
- else if (chassisSubNode == sensors::node::thermal)
+ else if (chassisSubNode == sensors::thermalNodeStr)
{
jsonValue["@odata.type"] = "#Thermal.v1_4_0.Thermal";
jsonValue["Fans"] = nlohmann::json::array();
jsonValue["Temperatures"] = nlohmann::json::array();
}
- else if (chassisSubNode == sensors::node::sensors)
+ else if (chassisSubNode == sensors::sensorsNodeStr)
{
jsonValue["@odata.type"] = "#SensorCollection.SensorCollection";
jsonValue["Description"] = "Collection of Sensors for this Chassis";
@@ -508,7 +384,7 @@ inline void populateChassisNode(nlohmann::json& jsonValue,
jsonValue["Members@odata.count"] = 0;
}
- if (chassisSubNode != sensors::node::sensors)
+ if (chassisSubNode != sensors::sensorsNodeStr)
{
jsonValue["Id"] = chassisSubNode;
}
@@ -536,456 +412,72 @@ void getChassis(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"/xyz/openbmc_project/inventory", 0, interfaces,
[callback = std::forward<Callback>(callback), asyncResp,
chassisIdStr{std::string(chassisId)},
- chassisSubNode{std::string(chassisSubNode)}, sensorTypes](
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse& chassisPaths) {
- BMCWEB_LOG_DEBUG("getChassis respHandler enter");
- if (ec)
- {
- BMCWEB_LOG_ERROR("getChassis respHandler DBUS error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string* chassisPath = nullptr;
- for (const std::string& chassis : chassisPaths)
- {
- sdbusplus::message::object_path path(chassis);
- std::string chassisName = path.filename();
- if (chassisName.empty())
- {
- BMCWEB_LOG_ERROR("Failed to find '/' in {}", chassis);
- continue;
- }
- if (chassisName == chassisIdStr)
+ chassisSubNode{std::string(chassisSubNode)},
+ sensorTypes](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreePathsResponse&
+ chassisPaths) mutable {
+ BMCWEB_LOG_DEBUG("getChassis respHandler enter");
+ if (ec)
{
- chassisPath = &chassis;
- break;
+ BMCWEB_LOG_ERROR("getChassis respHandler DBUS error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
}
- }
- if (chassisPath == nullptr)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisIdStr);
- return;
- }
- populateChassisNode(asyncResp->res.jsonValue, chassisSubNode);
-
- asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
- "/redfish/v1/Chassis/{}/{}", chassisIdStr, chassisSubNode);
-
- // Get the list of all sensors for this Chassis element
- std::string sensorPath = *chassisPath + "/all_sensors";
- dbus::utility::getAssociationEndPoints(
- sensorPath,
- [asyncResp, chassisSubNode, sensorTypes,
- callback = std::forward<const Callback>(callback)](
- const boost::system::error_code& ec2,
- const dbus::utility::MapperEndPoints& nodeSensorList) {
- if (ec2)
+ const std::string* chassisPath = nullptr;
+ for (const std::string& chassis : chassisPaths)
{
- if (ec2.value() != EBADR)
+ sdbusplus::message::object_path path(chassis);
+ std::string chassisName = path.filename();
+ if (chassisName.empty())
{
- messages::internalError(asyncResp->res);
- return;
+ BMCWEB_LOG_ERROR("Failed to find '/' in {}", chassis);
+ continue;
}
- }
- const std::shared_ptr<std::set<std::string>> culledSensorList =
- std::make_shared<std::set<std::string>>();
- reduceSensorList(asyncResp->res, chassisSubNode, sensorTypes,
- &nodeSensorList, culledSensorList);
- BMCWEB_LOG_DEBUG("Finishing with {}", culledSensorList->size());
- callback(culledSensorList);
- });
- });
- BMCWEB_LOG_DEBUG("getChassis exit");
-}
-
-/**
- * @brief Returns the Redfish State value for the specified inventory item.
- * @param inventoryItem D-Bus inventory item associated with a sensor.
- * @param sensorAvailable Boolean representing if D-Bus sensor is marked as
- * available.
- * @return State value for inventory item.
- */
-inline resource::State getState(const InventoryItem* inventoryItem,
- const bool sensorAvailable)
-{
- if ((inventoryItem != nullptr) && !(inventoryItem->isPresent))
- {
- return resource::State::Absent;
- }
-
- if (!sensorAvailable)
- {
- return resource::State::UnavailableOffline;
- }
-
- return resource::State::Enabled;
-}
-
-/**
- * @brief Returns the Redfish Health value for the specified sensor.
- * @param sensorJson Sensor JSON object.
- * @param valuesDict Map of all sensor DBus values.
- * @param inventoryItem D-Bus inventory item associated with the sensor. Will
- * be nullptr if no associated inventory item was found.
- * @return Health value for sensor.
- */
-inline std::string getHealth(nlohmann::json& sensorJson,
- const dbus::utility::DBusPropertiesMap& valuesDict,
- const InventoryItem* inventoryItem)
-{
- // Get current health value (if any) in the sensor JSON object. Some JSON
- // objects contain multiple sensors (such as PowerSupplies). We want to set
- // the overall health to be the most severe of any of the sensors.
- std::string currentHealth;
- auto statusIt = sensorJson.find("Status");
- if (statusIt != sensorJson.end())
- {
- auto healthIt = statusIt->find("Health");
- if (healthIt != statusIt->end())
- {
- std::string* health = healthIt->get_ptr<std::string*>();
- if (health != nullptr)
- {
- currentHealth = *health;
- }
- }
- }
-
- // If current health in JSON object is already Critical, return that. This
- // should override the sensor health, which might be less severe.
- if (currentHealth == "Critical")
- {
- return "Critical";
- }
-
- const bool* criticalAlarmHigh = nullptr;
- const bool* criticalAlarmLow = nullptr;
- const bool* warningAlarmHigh = nullptr;
- const bool* warningAlarmLow = nullptr;
-
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), valuesDict, "CriticalAlarmHigh",
- criticalAlarmHigh, "CriticalAlarmLow", criticalAlarmLow,
- "WarningAlarmHigh", warningAlarmHigh, "WarningAlarmLow",
- warningAlarmLow);
-
- if (success)
- {
- // Check if sensor has critical threshold alarm
- if ((criticalAlarmHigh != nullptr && *criticalAlarmHigh) ||
- (criticalAlarmLow != nullptr && *criticalAlarmLow))
- {
- return "Critical";
- }
- }
-
- // Check if associated inventory item is not functional
- if ((inventoryItem != nullptr) && !(inventoryItem->isFunctional))
- {
- return "Critical";
- }
-
- // If current health in JSON object is already Warning, return that. This
- // should override the sensor status, which might be less severe.
- if (currentHealth == "Warning")
- {
- return "Warning";
- }
-
- if (success)
- {
- // Check if sensor has warning threshold alarm
- if ((warningAlarmHigh != nullptr && *warningAlarmHigh) ||
- (warningAlarmLow != nullptr && *warningAlarmLow))
- {
- return "Warning";
- }
- }
-
- return "OK";
-}
-
-inline void setLedState(nlohmann::json& sensorJson,
- const InventoryItem* inventoryItem)
-{
- if (inventoryItem != nullptr && !inventoryItem->ledObjectPath.empty())
- {
- switch (inventoryItem->ledState)
- {
- case LedState::OFF:
- sensorJson["IndicatorLED"] = "Off";
- break;
- case LedState::ON:
- sensorJson["IndicatorLED"] = "Lit";
- break;
- case LedState::BLINK:
- sensorJson["IndicatorLED"] = "Blinking";
- break;
- default:
- break;
- }
- }
-}
-
-/**
- * @brief Builds a json sensor representation of a sensor.
- * @param sensorName The name of the sensor to be built
- * @param sensorType The type (temperature, fan_tach, etc) of the sensor to
- * build
- * @param chassisSubNode The subnode (thermal, sensor, etc) of the sensor
- * @param propertiesDict A dictionary of the properties to build the sensor
- * from.
- * @param sensorJson The json object to fill
- * @param inventoryItem D-Bus inventory item associated with the sensor. Will
- * be nullptr if no associated inventory item was found.
- */
-inline void objectPropertiesToJson(
- std::string_view sensorName, std::string_view sensorType,
- std::string_view chassisSubNode,
- const dbus::utility::DBusPropertiesMap& propertiesDict,
- nlohmann::json& sensorJson, InventoryItem* inventoryItem)
-{
- if (chassisSubNode == sensors::node::sensors)
- {
- std::string subNodeEscaped(sensorType);
- auto remove = std::ranges::remove(subNodeEscaped, '_');
- subNodeEscaped.erase(std::ranges::begin(remove), subNodeEscaped.end());
-
- // For sensors in SensorCollection we set Id instead of MemberId,
- // including power sensors.
- subNodeEscaped += '_';
- subNodeEscaped += sensorName;
- sensorJson["Id"] = std::move(subNodeEscaped);
-
- std::string sensorNameEs(sensorName);
- std::replace(sensorNameEs.begin(), sensorNameEs.end(), '_', ' ');
- sensorJson["Name"] = std::move(sensorNameEs);
- }
- else if (sensorType != "power")
- {
- // Set MemberId and Name for non-power sensors. For PowerSupplies and
- // PowerControl, those properties have more general values because
- // multiple sensors can be stored in the same JSON object.
- std::string sensorNameEs(sensorName);
- std::replace(sensorNameEs.begin(), sensorNameEs.end(), '_', ' ');
- sensorJson["Name"] = std::move(sensorNameEs);
- }
-
- const bool* checkAvailable = nullptr;
- bool available = true;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesDict, "Available",
- checkAvailable);
- if (!success)
- {
- messages::internalError();
- }
- if (checkAvailable != nullptr)
- {
- available = *checkAvailable;
- }
-
- sensorJson["Status"]["State"] = getState(inventoryItem, available);
- sensorJson["Status"]["Health"] = getHealth(sensorJson, propertiesDict,
- inventoryItem);
-
- // Parameter to set to override the type we get from dbus, and force it to
- // int, regardless of what is available. This is used for schemas like fan,
- // that require integers, not floats.
- bool forceToInt = false;
-
- nlohmann::json::json_pointer unit("/Reading");
- if (chassisSubNode == sensors::node::sensors)
- {
- sensorJson["@odata.type"] = "#Sensor.v1_2_0.Sensor";
-
- sensor::ReadingType readingType = sensors::toReadingType(sensorType);
- if (readingType == sensor::ReadingType::Invalid)
- {
- BMCWEB_LOG_ERROR("Redfish cannot map reading type for {}",
- sensorType);
- }
- else
- {
- sensorJson["ReadingType"] = readingType;
- }
-
- std::string_view readingUnits = sensors::toReadingUnits(sensorType);
- if (readingUnits.empty())
- {
- BMCWEB_LOG_ERROR("Redfish cannot map reading unit for {}",
- sensorType);
- }
- else
- {
- sensorJson["ReadingUnits"] = readingUnits;
- }
- }
- else if (sensorType == "temperature")
- {
- unit = "/ReadingCelsius"_json_pointer;
- sensorJson["@odata.type"] = "#Thermal.v1_3_0.Temperature";
- // TODO(ed) Documentation says that path should be type fan_tach,
- // implementation seems to implement fan
- }
- else if (sensorType == "fan" || sensorType == "fan_tach")
- {
- unit = "/Reading"_json_pointer;
- sensorJson["ReadingUnits"] = "RPM";
- sensorJson["@odata.type"] = "#Thermal.v1_3_0.Fan";
- setLedState(sensorJson, inventoryItem);
- forceToInt = true;
- }
- else if (sensorType == "fan_pwm")
- {
- unit = "/Reading"_json_pointer;
- sensorJson["ReadingUnits"] = "Percent";
- sensorJson["@odata.type"] = "#Thermal.v1_3_0.Fan";
- setLedState(sensorJson, inventoryItem);
- forceToInt = true;
- }
- else if (sensorType == "voltage")
- {
- unit = "/ReadingVolts"_json_pointer;
- sensorJson["@odata.type"] = "#Power.v1_0_0.Voltage";
- }
- else if (sensorType == "power")
- {
- std::string lower;
- std::ranges::transform(sensorName, std::back_inserter(lower),
- bmcweb::asciiToLower);
- if (lower == "total_power")
- {
- sensorJson["@odata.type"] = "#Power.v1_0_0.PowerControl";
- // Put multiple "sensors" into a single PowerControl, so have
- // generic names for MemberId and Name. Follows Redfish mockup.
- sensorJson["MemberId"] = "0";
- sensorJson["Name"] = "Chassis Power Control";
- unit = "/PowerConsumedWatts"_json_pointer;
- }
- else if (lower.find("input") != std::string::npos)
- {
- unit = "/PowerInputWatts"_json_pointer;
- }
- else
- {
- unit = "/PowerOutputWatts"_json_pointer;
- }
- }
- else
- {
- BMCWEB_LOG_ERROR("Redfish cannot map object type for {}", sensorName);
- return;
- }
- // Map of dbus interface name, dbus property name and redfish property_name
- std::vector<
- std::tuple<const char*, const char*, nlohmann::json::json_pointer>>
- properties;
- properties.reserve(7);
-
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);
-
- if (chassisSubNode == sensors::node::sensors)
- {
- properties.emplace_back(
- "xyz.openbmc_project.Sensor.Threshold.Warning", "WarningHigh",
- "/Thresholds/UpperCaution/Reading"_json_pointer);
- properties.emplace_back(
- "xyz.openbmc_project.Sensor.Threshold.Warning", "WarningLow",
- "/Thresholds/LowerCaution/Reading"_json_pointer);
- properties.emplace_back(
- "xyz.openbmc_project.Sensor.Threshold.Critical", "CriticalHigh",
- "/Thresholds/UpperCritical/Reading"_json_pointer);
- properties.emplace_back(
- "xyz.openbmc_project.Sensor.Threshold.Critical", "CriticalLow",
- "/Thresholds/LowerCritical/Reading"_json_pointer);
- }
- else if (sensorType != "power")
- {
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
- "WarningHigh",
- "/UpperThresholdNonCritical"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
- "WarningLow",
- "/LowerThresholdNonCritical"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
- "CriticalHigh",
- "/UpperThresholdCritical"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
- "CriticalLow",
- "/LowerThresholdCritical"_json_pointer);
- }
-
- // TODO Need to get UpperThresholdFatal and LowerThresholdFatal
-
- if (chassisSubNode == sensors::node::sensors)
- {
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
- "/ReadingRangeMin"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
- "/ReadingRangeMax"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Accuracy",
- "Accuracy", "/Accuracy"_json_pointer);
- }
- else if (sensorType == "temperature")
- {
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
- "/MinReadingRangeTemp"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
- "/MaxReadingRangeTemp"_json_pointer);
- }
- else if (sensorType != "power")
- {
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
- "/MinReadingRange"_json_pointer);
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
- "/MaxReadingRange"_json_pointer);
- }
-
- for (const std::tuple<const char*, const char*,
- nlohmann::json::json_pointer>& p : properties)
- {
- for (const auto& [valueName, valueVariant] : propertiesDict)
- {
- if (valueName != std::get<1>(p))
- {
- continue;
- }
-
- // The property we want to set may be nested json, so use
- // a json_pointer for easy indexing into the json structure.
- const nlohmann::json::json_pointer& key = std::get<2>(p);
-
- const double* doubleValue = std::get_if<double>(&valueVariant);
- if (doubleValue == nullptr)
- {
- BMCWEB_LOG_ERROR("Got value interface that wasn't double");
- continue;
- }
- if (!std::isfinite(*doubleValue))
- {
- if (valueName == "Value")
+ if (chassisName == chassisIdStr)
{
- // Readings are allowed to be NAN for unavailable; coerce
- // them to null in the json response.
- sensorJson[key] = nullptr;
- continue;
+ chassisPath = &chassis;
+ break;
}
- BMCWEB_LOG_WARNING("Sensor value for {} was unexpectedly {}",
- valueName, *doubleValue);
- continue;
- }
- if (forceToInt)
- {
- sensorJson[key] = static_cast<int64_t>(*doubleValue);
}
- else
+ if (chassisPath == nullptr)
{
- sensorJson[key] = *doubleValue;
+ messages::resourceNotFound(asyncResp->res, "Chassis",
+ chassisIdStr);
+ return;
}
- }
- }
+ populateChassisNode(asyncResp->res.jsonValue, chassisSubNode);
+
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/{}", chassisIdStr, chassisSubNode);
+
+ // Get the list of all sensors for this Chassis element
+ std::string sensorPath = *chassisPath + "/all_sensors";
+ dbus::utility::getAssociationEndPoints(
+ sensorPath, [asyncResp, chassisSubNode, sensorTypes,
+ callback = std::forward<Callback>(callback)](
+ const boost::system::error_code& ec2,
+ const dbus::utility::MapperEndPoints&
+ nodeSensorList) mutable {
+ if (ec2)
+ {
+ if (ec2.value() != EBADR)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ const std::shared_ptr<std::set<std::string>>
+ culledSensorList =
+ std::make_shared<std::set<std::string>>();
+ reduceSensorList(asyncResp->res, chassisSubNode,
+ sensorTypes, &nodeSensorList,
+ culledSensorList);
+ BMCWEB_LOG_DEBUG("Finishing with {}",
+ culledSensorList->size());
+ callback(culledSensorList);
+ });
+ });
+ BMCWEB_LOG_DEBUG("getChassis exit");
}
/**
@@ -1002,14 +494,15 @@ inline void objectPropertiesToJson(
*/
inline void objectInterfacesToJson(
const std::string& sensorName, const std::string& sensorType,
- const std::string& chassisSubNode,
+ const sensor_utils::ChassisSubNode chassisSubNode,
const dbus::utility::DBusInterfacesMap& interfacesDict,
nlohmann::json& sensorJson, InventoryItem* inventoryItem)
{
for (const auto& [interface, valuesDict] : interfacesDict)
{
- objectPropertiesToJson(sensorName, sensorType, chassisSubNode,
- valuesDict, sensorJson, inventoryItem);
+ sensor_utils::objectPropertiesToJson(
+ sensorName, sensorType, chassisSubNode, valuesDict, sensorJson,
+ inventoryItem);
}
BMCWEB_LOG_DEBUG("Added sensor {}", sensorName);
}
@@ -1024,167 +517,184 @@ inline void populateFanRedundancy(
[sensorsAsyncResp](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& resp) {
- if (ec)
- {
- return; // don't have to have this interface
- }
- for (const std::pair<std::string, dbus::utility::MapperServiceMap>&
- pathPair : resp)
- {
- const std::string& path = pathPair.first;
- const dbus::utility::MapperServiceMap& objDict = pathPair.second;
- if (objDict.empty())
+ if (ec)
{
- continue; // this should be impossible
+ return; // don't have to have this interface
}
-
- const std::string& owner = objDict.begin()->first;
- dbus::utility::getAssociationEndPoints(
- path + "/chassis",
- [path, owner, sensorsAsyncResp](
- const boost::system::error_code& ec2,
- const dbus::utility::MapperEndPoints& endpoints) {
- if (ec2)
+ for (const std::pair<std::string, dbus::utility::MapperServiceMap>&
+ pathPair : resp)
+ {
+ const std::string& path = pathPair.first;
+ const dbus::utility::MapperServiceMap& objDict =
+ pathPair.second;
+ if (objDict.empty())
{
- return; // if they don't have an association we
- // can't tell what chassis is
+ continue; // this should be impossible
}
- auto found = std::ranges::find_if(
- endpoints, [sensorsAsyncResp](const std::string& entry) {
- return entry.find(sensorsAsyncResp->chassisId) !=
- std::string::npos;
- });
- if (found == endpoints.end())
- {
- return;
- }
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, owner, path,
- "xyz.openbmc_project.Control.FanRedundancy",
- [path, sensorsAsyncResp](
- const boost::system::error_code& ec3,
- const dbus::utility::DBusPropertiesMap& ret) {
- if (ec3)
- {
- return; // don't have to have this
- // interface
- }
+ const std::string& owner = objDict.begin()->first;
+ dbus::utility::getAssociationEndPoints(
+ path + "/chassis",
+ [path, owner, sensorsAsyncResp](
+ const boost::system::error_code& ec2,
+ const dbus::utility::MapperEndPoints& endpoints) {
+ if (ec2)
+ {
+ return; // if they don't have an association we
+ // can't tell what chassis is
+ }
+ auto found = std::ranges::find_if(
+ endpoints,
+ [sensorsAsyncResp](const std::string& entry) {
+ return entry.find(
+ sensorsAsyncResp->chassisId) !=
+ std::string::npos;
+ });
+
+ if (found == endpoints.end())
+ {
+ return;
+ }
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, owner, path,
+ "xyz.openbmc_project.Control.FanRedundancy",
+ [path, sensorsAsyncResp](
+ const boost::system::error_code& ec3,
+ const dbus::utility::DBusPropertiesMap& ret) {
+ if (ec3)
+ {
+ return; // don't have to have this
+ // interface
+ }
- const uint8_t* allowedFailures = nullptr;
- const std::vector<std::string>* collection = nullptr;
- const std::string* status = nullptr;
+ const uint8_t* allowedFailures = nullptr;
+ const std::vector<std::string>* collection =
+ nullptr;
+ const std::string* status = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), ret,
- "AllowedFailures", allowedFailures, "Collection",
- collection, "Status", status);
+ const bool success =
+ sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), ret,
+ "AllowedFailures", allowedFailures,
+ "Collection", collection, "Status",
+ status);
- if (!success)
- {
- messages::internalError(
- sensorsAsyncResp->asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(
+ sensorsAsyncResp->asyncResp->res);
+ return;
+ }
- if (allowedFailures == nullptr || collection == nullptr ||
- status == nullptr)
- {
- BMCWEB_LOG_ERROR("Invalid redundancy interface");
- messages::internalError(
- sensorsAsyncResp->asyncResp->res);
- return;
- }
+ if (allowedFailures == nullptr ||
+ collection == nullptr || status == nullptr)
+ {
+ BMCWEB_LOG_ERROR(
+ "Invalid redundancy interface");
+ messages::internalError(
+ sensorsAsyncResp->asyncResp->res);
+ return;
+ }
- sdbusplus::message::object_path objectPath(path);
- std::string name = objectPath.filename();
- if (name.empty())
- {
- // this should be impossible
- messages::internalError(
- sensorsAsyncResp->asyncResp->res);
- return;
- }
- std::ranges::replace(name, '_', ' ');
+ sdbusplus::message::object_path objectPath(
+ path);
+ std::string name = objectPath.filename();
+ if (name.empty())
+ {
+ // this should be impossible
+ messages::internalError(
+ sensorsAsyncResp->asyncResp->res);
+ return;
+ }
+ std::ranges::replace(name, '_', ' ');
- std::string health;
+ std::string health;
- if (status->ends_with("Full"))
- {
- health = "OK";
- }
- else if (status->ends_with("Degraded"))
- {
- health = "Warning";
- }
- else
- {
- health = "Critical";
- }
- nlohmann::json::array_t redfishCollection;
- const auto& fanRedfish =
- sensorsAsyncResp->asyncResp->res.jsonValue["Fans"];
- for (const std::string& item : *collection)
- {
- sdbusplus::message::object_path itemPath(item);
- std::string itemName = itemPath.filename();
- if (itemName.empty())
- {
- continue;
- }
- /*
- todo(ed): merge patch that fixes the names
- std::replace(itemName.begin(),
- itemName.end(), '_', ' ');*/
- auto schemaItem = std::ranges::find_if(
- fanRedfish, [itemName](const nlohmann::json& fan) {
- return fan["Name"] == itemName;
- });
- if (schemaItem != fanRedfish.end())
- {
- nlohmann::json::object_t collectionId;
- collectionId["@odata.id"] =
- (*schemaItem)["@odata.id"];
- redfishCollection.emplace_back(
- std::move(collectionId));
- }
- else
- {
- BMCWEB_LOG_ERROR("failed to find fan in schema");
- messages::internalError(
- sensorsAsyncResp->asyncResp->res);
- return;
- }
- }
+ if (status->ends_with("Full"))
+ {
+ health = "OK";
+ }
+ else if (status->ends_with("Degraded"))
+ {
+ health = "Warning";
+ }
+ else
+ {
+ health = "Critical";
+ }
+ nlohmann::json::array_t redfishCollection;
+ const auto& fanRedfish =
+ sensorsAsyncResp->asyncResp->res
+ .jsonValue["Fans"];
+ for (const std::string& item : *collection)
+ {
+ sdbusplus::message::object_path itemPath(
+ item);
+ std::string itemName = itemPath.filename();
+ if (itemName.empty())
+ {
+ continue;
+ }
+ /*
+ todo(ed): merge patch that fixes the names
+ std::replace(itemName.begin(),
+ itemName.end(), '_', ' ');*/
+ auto schemaItem = std::ranges::find_if(
+ fanRedfish,
+ [itemName](const nlohmann::json& fan) {
+ return fan["Name"] == itemName;
+ });
+ if (schemaItem != fanRedfish.end())
+ {
+ nlohmann::json::object_t collectionId;
+ collectionId["@odata.id"] =
+ (*schemaItem)["@odata.id"];
+ redfishCollection.emplace_back(
+ std::move(collectionId));
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR(
+ "failed to find fan in schema");
+ messages::internalError(
+ sensorsAsyncResp->asyncResp->res);
+ return;
+ }
+ }
- size_t minNumNeeded = collection->empty()
- ? 0
- : collection->size() -
- *allowedFailures;
- nlohmann::json& jResp = sensorsAsyncResp->asyncResp->res
- .jsonValue["Redundancy"];
-
- nlohmann::json::object_t redundancy;
- boost::urls::url url =
- boost::urls::format("/redfish/v1/Chassis/{}/{}",
- sensorsAsyncResp->chassisId,
- sensorsAsyncResp->chassisSubNode);
- url.set_fragment(("/Redundancy"_json_pointer / jResp.size())
- .to_string());
- redundancy["@odata.id"] = std::move(url);
- redundancy["@odata.type"] = "#Redundancy.v1_3_2.Redundancy";
- redundancy["MinNumNeeded"] = minNumNeeded;
- redundancy["Mode"] = "N+m";
- redundancy["Name"] = name;
- redundancy["RedundancySet"] = redfishCollection;
- redundancy["Status"]["Health"] = health;
- redundancy["Status"]["State"] = "Enabled";
-
- jResp.emplace_back(std::move(redundancy));
- });
- });
- }
- });
+ size_t minNumNeeded =
+ collection->empty()
+ ? 0
+ : collection->size() - *allowedFailures;
+ nlohmann::json& jResp =
+ sensorsAsyncResp->asyncResp->res
+ .jsonValue["Redundancy"];
+
+ nlohmann::json::object_t redundancy;
+ boost::urls::url url = boost::urls::format(
+ "/redfish/v1/Chassis/{}/{}",
+ sensorsAsyncResp->chassisId,
+ sensorsAsyncResp->chassisSubNode);
+ url.set_fragment(
+ ("/Redundancy"_json_pointer / jResp.size())
+ .to_string());
+ redundancy["@odata.id"] = std::move(url);
+ redundancy["@odata.type"] =
+ "#Redundancy.v1_3_2.Redundancy";
+ redundancy["MinNumNeeded"] = minNumNeeded;
+ redundancy["Mode"] =
+ redundancy::RedundancyType::NPlusM;
+ redundancy["Name"] = name;
+ redundancy["RedundancySet"] = redfishCollection;
+ redundancy["Status"]["Health"] = health;
+ redundancy["Status"]["State"] =
+ resource::State::Enabled;
+
+ jResp.emplace_back(std::move(redundancy));
+ });
+ });
+ }
+ });
}
inline void
@@ -1192,37 +702,41 @@ inline void
{
nlohmann::json& response = sensorsAsyncResp->asyncResp->res.jsonValue;
std::array<std::string, 2> sensorHeaders{"Temperatures", "Fans"};
- if (sensorsAsyncResp->chassisSubNode == sensors::node::power)
+ if (sensorsAsyncResp->chassisSubNode == sensors::powerNodeStr)
{
sensorHeaders = {"Voltages", "PowerSupplies"};
}
for (const std::string& sensorGroup : sensorHeaders)
{
nlohmann::json::iterator entry = response.find(sensorGroup);
- if (entry != response.end())
+ if (entry == response.end())
{
- std::sort(entry->begin(), entry->end(),
- [](const nlohmann::json& c1, const nlohmann::json& c2) {
- return c1["Name"] < c2["Name"];
- });
+ continue;
+ }
+ nlohmann::json::array_t* arr =
+ entry->get_ptr<nlohmann::json::array_t*>();
+ if (arr == nullptr)
+ {
+ continue;
+ }
+ json_util::sortJsonArrayByKey(*arr, "Name");
- // add the index counts to the end of each entry
- size_t count = 0;
- for (nlohmann::json& sensorJson : *entry)
+ // add the index counts to the end of each entry
+ size_t count = 0;
+ for (nlohmann::json& sensorJson : *entry)
+ {
+ nlohmann::json::iterator odata = sensorJson.find("@odata.id");
+ if (odata == sensorJson.end())
{
- nlohmann::json::iterator odata = sensorJson.find("@odata.id");
- if (odata == sensorJson.end())
- {
- continue;
- }
- std::string* value = odata->get_ptr<std::string*>();
- if (value != nullptr)
- {
- *value += "/" + std::to_string(count);
- sensorJson["MemberId"] = std::to_string(count);
- count++;
- sensorsAsyncResp->updateUri(sensorJson["Name"], *value);
- }
+ continue;
+ }
+ std::string* value = odata->get_ptr<std::string*>();
+ if (value != nullptr)
+ {
+ *value += "/" + std::to_string(count);
+ sensorJson["MemberId"] = std::to_string(count);
+ count++;
+ sensorsAsyncResp->updateUri(sensorJson["Name"], *value);
}
}
}
@@ -1274,9 +788,8 @@ inline InventoryItem* findInventoryItemForSensor(
* @param ledObjPath D-Bus object path of led.
* @return Inventory item within vector, or nullptr if no match found.
*/
-inline InventoryItem*
- findInventoryItemForLed(std::vector<InventoryItem>& inventoryItems,
- const std::string& ledObjPath)
+inline InventoryItem* findInventoryItemForLed(
+ std::vector<InventoryItem>& inventoryItems, const std::string& ledObjPath)
{
for (InventoryItem& inventoryItem : inventoryItems)
{
@@ -1307,8 +820,8 @@ inline void addInventoryItem(
const std::string& invItemObjPath, const std::string& sensorObjPath)
{
// Look for inventory item in vector
- InventoryItem* inventoryItem = findInventoryItem(inventoryItems,
- invItemObjPath);
+ InventoryItem* inventoryItem =
+ findInventoryItem(inventoryItems, invItemObjPath);
// If inventory item doesn't exist in vector, add it
if (inventoryItem == nullptr)
@@ -1456,7 +969,7 @@ inline void storeInventoryItemData(
* in recursive calls to this function.
*/
template <typename Callback>
-static void getInventoryItemsData(
+void getInventoryItemsData(
std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp,
std::shared_ptr<std::vector<InventoryItem>> inventoryItems,
std::shared_ptr<std::set<std::string>> invConnections, Callback&& callback,
@@ -1486,39 +999,41 @@ static void getInventoryItemsData(
[sensorsAsyncResp, inventoryItems, invConnections,
callback = std::forward<Callback>(callback), invConnectionsIndex](
const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& resp) {
- BMCWEB_LOG_DEBUG("getInventoryItemsData respHandler enter");
- if (ec)
- {
- BMCWEB_LOG_ERROR(
- "getInventoryItemsData respHandler DBus error {}", ec);
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- return;
- }
-
- // Loop through returned object paths
- for (const auto& objDictEntry : resp)
- {
- const std::string& objPath =
- static_cast<const std::string&>(objDictEntry.first);
+ const dbus::utility::ManagedObjectType& resp) mutable {
+ BMCWEB_LOG_DEBUG("getInventoryItemsData respHandler enter");
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR(
+ "getInventoryItemsData respHandler DBus error {}", ec);
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ return;
+ }
- // If this object path is one of the specified inventory items
- InventoryItem* inventoryItem = findInventoryItem(inventoryItems,
- objPath);
- if (inventoryItem != nullptr)
+ // Loop through returned object paths
+ for (const auto& objDictEntry : resp)
{
- // Store inventory data in InventoryItem
- storeInventoryItemData(*inventoryItem, objDictEntry.second);
+ const std::string& objPath =
+ static_cast<const std::string&>(objDictEntry.first);
+
+ // If this object path is one of the specified inventory
+ // items
+ InventoryItem* inventoryItem =
+ findInventoryItem(inventoryItems, objPath);
+ if (inventoryItem != nullptr)
+ {
+ // Store inventory data in InventoryItem
+ storeInventoryItemData(*inventoryItem,
+ objDictEntry.second);
+ }
}
- }
- // Recurse to get inventory item data from next connection
- getInventoryItemsData(sensorsAsyncResp, inventoryItems,
- invConnections, std::move(callback),
- invConnectionsIndex + 1);
+ // Recurse to get inventory item data from next connection
+ getInventoryItemsData(sensorsAsyncResp, inventoryItems,
+ invConnections, std::move(callback),
+ invConnectionsIndex + 1);
- BMCWEB_LOG_DEBUG("getInventoryItemsData respHandler exit");
- });
+ BMCWEB_LOG_DEBUG("getInventoryItemsData respHandler exit");
+ });
}
BMCWEB_LOG_DEBUG("getInventoryItemsData exit");
@@ -1543,7 +1058,7 @@ static void getInventoryItemsData(
* @param callback Callback to invoke when connections have been obtained.
*/
template <typename Callback>
-static void getInventoryItemsConnections(
+void getInventoryItemsConnections(
const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp,
const std::shared_ptr<std::vector<InventoryItem>>& inventoryItems,
Callback&& callback)
@@ -1563,44 +1078,45 @@ static void getInventoryItemsConnections(
[callback = std::forward<Callback>(callback), sensorsAsyncResp,
inventoryItems](
const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- // Response handler for parsing output from GetSubTree
- BMCWEB_LOG_DEBUG("getInventoryItemsConnections respHandler enter");
- if (ec)
- {
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- BMCWEB_LOG_ERROR(
- "getInventoryItemsConnections respHandler DBus error {}", ec);
- return;
- }
+ const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
+ // Response handler for parsing output from GetSubTree
+ BMCWEB_LOG_DEBUG("getInventoryItemsConnections respHandler enter");
+ if (ec)
+ {
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ BMCWEB_LOG_ERROR(
+ "getInventoryItemsConnections respHandler DBus error {}",
+ ec);
+ return;
+ }
- // Make unique list of connections for desired inventory items
- std::shared_ptr<std::set<std::string>> invConnections =
- std::make_shared<std::set<std::string>>();
+ // Make unique list of connections for desired inventory items
+ std::shared_ptr<std::set<std::string>> invConnections =
+ std::make_shared<std::set<std::string>>();
- // Loop through objects from GetSubTree
- for (const std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- // Check if object path is one of the specified inventory items
- const std::string& objPath = object.first;
- if (findInventoryItem(inventoryItems, objPath) != nullptr)
+ // Loop through objects from GetSubTree
+ for (const std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>&
+ object : subtree)
{
- // Store all connections to inventory item
- for (const std::pair<std::string, std::vector<std::string>>&
- objData : object.second)
+ // Check if object path is one of the specified inventory items
+ const std::string& objPath = object.first;
+ if (findInventoryItem(inventoryItems, objPath) != nullptr)
{
- const std::string& invConnection = objData.first;
- invConnections->insert(invConnection);
+ // Store all connections to inventory item
+ for (const std::pair<std::string, std::vector<std::string>>&
+ objData : object.second)
+ {
+ const std::string& invConnection = objData.first;
+ invConnections->insert(invConnection);
+ }
}
}
- }
- callback(invConnections);
- BMCWEB_LOG_DEBUG("getInventoryItemsConnections respHandler exit");
- });
+ callback(invConnections);
+ BMCWEB_LOG_DEBUG("getInventoryItemsConnections respHandler exit");
+ });
BMCWEB_LOG_DEBUG("getInventoryItemsConnections exit");
}
@@ -1625,7 +1141,7 @@ static void getInventoryItemsConnections(
* @param callback Callback to invoke when inventory items have been obtained.
*/
template <typename Callback>
-static void getInventoryItemAssociations(
+void getInventoryItemAssociations(
const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp,
const std::shared_ptr<std::set<std::string>>& sensorNames,
Callback&& callback)
@@ -1638,113 +1154,120 @@ static void getInventoryItemAssociations(
"xyz.openbmc_project.ObjectMapper", path,
[callback = std::forward<Callback>(callback), sensorsAsyncResp,
sensorNames](const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& resp) {
- BMCWEB_LOG_DEBUG("getInventoryItemAssociations respHandler enter");
- if (ec)
- {
- BMCWEB_LOG_ERROR(
- "getInventoryItemAssociations respHandler DBus error {}", ec);
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- return;
- }
-
- // Create vector to hold list of inventory items
- std::shared_ptr<std::vector<InventoryItem>> inventoryItems =
- std::make_shared<std::vector<InventoryItem>>();
+ const dbus::utility::ManagedObjectType& resp) mutable {
+ BMCWEB_LOG_DEBUG("getInventoryItemAssociations respHandler enter");
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR(
+ "getInventoryItemAssociations respHandler DBus error {}",
+ ec);
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ return;
+ }
- // Loop through returned object paths
- std::string sensorAssocPath;
- sensorAssocPath.reserve(128); // avoid memory allocations
- for (const auto& objDictEntry : resp)
- {
- const std::string& objPath =
- static_cast<const std::string&>(objDictEntry.first);
+ // Create vector to hold list of inventory items
+ std::shared_ptr<std::vector<InventoryItem>> inventoryItems =
+ std::make_shared<std::vector<InventoryItem>>();
- // If path is inventory association for one of the specified sensors
- for (const std::string& sensorName : *sensorNames)
+ // Loop through returned object paths
+ std::string sensorAssocPath;
+ sensorAssocPath.reserve(128); // avoid memory allocations
+ for (const auto& objDictEntry : resp)
{
- sensorAssocPath = sensorName;
- sensorAssocPath += "/inventory";
- if (objPath == sensorAssocPath)
+ const std::string& objPath =
+ static_cast<const std::string&>(objDictEntry.first);
+
+ // If path is inventory association for one of the specified
+ // sensors
+ for (const std::string& sensorName : *sensorNames)
{
- // Get Association interface for object path
- for (const auto& [interface, values] : objDictEntry.second)
+ sensorAssocPath = sensorName;
+ sensorAssocPath += "/inventory";
+ if (objPath == sensorAssocPath)
{
- if (interface == "xyz.openbmc_project.Association")
+ // Get Association interface for object path
+ for (const auto& [interface, values] :
+ objDictEntry.second)
{
- for (const auto& [valueName, value] : values)
+ if (interface == "xyz.openbmc_project.Association")
{
- if (valueName == "endpoints")
+ for (const auto& [valueName, value] : values)
{
- const std::vector<std::string>* endpoints =
- std::get_if<std::vector<std::string>>(
- &value);
- if ((endpoints != nullptr) &&
- !endpoints->empty())
+ if (valueName == "endpoints")
{
- // Add inventory item to vector
- const std::string& invItemPath =
- endpoints->front();
- addInventoryItem(inventoryItems,
- invItemPath,
- sensorName);
+ const std::vector<std::string>*
+ endpoints = std::get_if<
+ std::vector<std::string>>(
+ &value);
+ if ((endpoints != nullptr) &&
+ !endpoints->empty())
+ {
+ // Add inventory item to vector
+ const std::string& invItemPath =
+ endpoints->front();
+ addInventoryItem(inventoryItems,
+ invItemPath,
+ sensorName);
+ }
}
}
}
}
+ break;
}
- break;
}
}
- }
-
- // Now loop through the returned object paths again, this time to
- // find the leds associated with the inventory items we just found
- std::string inventoryAssocPath;
- inventoryAssocPath.reserve(128); // avoid memory allocations
- for (const auto& objDictEntry : resp)
- {
- const std::string& objPath =
- static_cast<const std::string&>(objDictEntry.first);
- for (InventoryItem& inventoryItem : *inventoryItems)
+ // Now loop through the returned object paths again, this time to
+ // find the leds associated with the inventory items we just found
+ std::string inventoryAssocPath;
+ inventoryAssocPath.reserve(128); // avoid memory allocations
+ for (const auto& objDictEntry : resp)
{
- inventoryAssocPath = inventoryItem.objectPath;
- inventoryAssocPath += "/leds";
- if (objPath == inventoryAssocPath)
+ const std::string& objPath =
+ static_cast<const std::string&>(objDictEntry.first);
+
+ for (InventoryItem& inventoryItem : *inventoryItems)
{
- for (const auto& [interface, values] : objDictEntry.second)
+ inventoryAssocPath = inventoryItem.objectPath;
+ inventoryAssocPath += "/leds";
+ if (objPath == inventoryAssocPath)
{
- if (interface == "xyz.openbmc_project.Association")
+ for (const auto& [interface, values] :
+ objDictEntry.second)
{
- for (const auto& [valueName, value] : values)
+ if (interface == "xyz.openbmc_project.Association")
{
- if (valueName == "endpoints")
+ for (const auto& [valueName, value] : values)
{
- const std::vector<std::string>* endpoints =
- std::get_if<std::vector<std::string>>(
- &value);
- if ((endpoints != nullptr) &&
- !endpoints->empty())
+ if (valueName == "endpoints")
{
- // Add inventory item to vector
- // Store LED path in inventory item
- const std::string& ledPath =
- endpoints->front();
- inventoryItem.ledObjectPath = ledPath;
+ const std::vector<std::string>*
+ endpoints = std::get_if<
+ std::vector<std::string>>(
+ &value);
+ if ((endpoints != nullptr) &&
+ !endpoints->empty())
+ {
+ // Add inventory item to vector
+ // Store LED path in inventory item
+ const std::string& ledPath =
+ endpoints->front();
+ inventoryItem.ledObjectPath =
+ ledPath;
+ }
}
}
}
}
- }
- break;
+ break;
+ }
}
}
- }
- callback(inventoryItems);
- BMCWEB_LOG_DEBUG("getInventoryItemAssociations respHandler exit");
- });
+ callback(inventoryItems);
+ BMCWEB_LOG_DEBUG("getInventoryItemAssociations respHandler exit");
+ });
BMCWEB_LOG_DEBUG("getInventoryItemAssociations exit");
}
@@ -1805,49 +1328,51 @@ void getInventoryLedData(
// Response handler for Get State property
auto respHandler =
[sensorsAsyncResp, inventoryItems, ledConnections, ledPath,
- callback = std::forward<Callback>(callback), ledConnectionsIndex](
- const boost::system::error_code& ec, const std::string& state) {
- BMCWEB_LOG_DEBUG("getInventoryLedData respHandler enter");
- if (ec)
- {
- BMCWEB_LOG_ERROR(
- "getInventoryLedData respHandler DBus error {}", ec);
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- return;
- }
-
- BMCWEB_LOG_DEBUG("Led state: {}", state);
- // Find inventory item with this LED object path
- InventoryItem* inventoryItem =
- findInventoryItemForLed(*inventoryItems, ledPath);
- if (inventoryItem != nullptr)
- {
- // Store LED state in InventoryItem
- if (state.ends_with("On"))
- {
- inventoryItem->ledState = LedState::ON;
- }
- else if (state.ends_with("Blink"))
- {
- inventoryItem->ledState = LedState::BLINK;
- }
- else if (state.ends_with("Off"))
+ callback = std::forward<Callback>(callback),
+ ledConnectionsIndex](const boost::system::error_code& ec,
+ const std::string& state) mutable {
+ BMCWEB_LOG_DEBUG("getInventoryLedData respHandler enter");
+ if (ec)
{
- inventoryItem->ledState = LedState::OFF;
+ BMCWEB_LOG_ERROR(
+ "getInventoryLedData respHandler DBus error {}", ec);
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ return;
}
- else
+
+ BMCWEB_LOG_DEBUG("Led state: {}", state);
+ // Find inventory item with this LED object path
+ InventoryItem* inventoryItem =
+ findInventoryItemForLed(*inventoryItems, ledPath);
+ if (inventoryItem != nullptr)
{
- inventoryItem->ledState = LedState::UNKNOWN;
+ // Store LED state in InventoryItem
+ if (state.ends_with("On"))
+ {
+ inventoryItem->ledState = sensor_utils::LedState::ON;
+ }
+ else if (state.ends_with("Blink"))
+ {
+ inventoryItem->ledState = sensor_utils::LedState::BLINK;
+ }
+ else if (state.ends_with("Off"))
+ {
+ inventoryItem->ledState = sensor_utils::LedState::OFF;
+ }
+ else
+ {
+ inventoryItem->ledState =
+ sensor_utils::LedState::UNKNOWN;
+ }
}
- }
- // Recurse to get LED data from next connection
- getInventoryLedData(sensorsAsyncResp, inventoryItems,
- ledConnections, std::move(callback),
- ledConnectionsIndex + 1);
+ // Recurse to get LED data from next connection
+ getInventoryLedData(sensorsAsyncResp, inventoryItems,
+ ledConnections, std::move(callback),
+ ledConnectionsIndex + 1);
- BMCWEB_LOG_DEBUG("getInventoryLedData respHandler exit");
- };
+ BMCWEB_LOG_DEBUG("getInventoryLedData respHandler exit");
+ };
// Get the State property for the current LED
sdbusplus::asio::getProperty<std::string>(
@@ -1899,42 +1424,46 @@ void getInventoryLeds(
[callback = std::forward<Callback>(callback), sensorsAsyncResp,
inventoryItems](
const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- // Response handler for parsing output from GetSubTree
- BMCWEB_LOG_DEBUG("getInventoryLeds respHandler enter");
- if (ec)
- {
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- BMCWEB_LOG_ERROR("getInventoryLeds respHandler DBus error {}", ec);
- return;
- }
+ const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
+ // Response handler for parsing output from GetSubTree
+ BMCWEB_LOG_DEBUG("getInventoryLeds respHandler enter");
+ if (ec)
+ {
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ BMCWEB_LOG_ERROR("getInventoryLeds respHandler DBus error {}",
+ ec);
+ return;
+ }
- // Build map of LED object paths to connections
- std::shared_ptr<std::map<std::string, std::string>> ledConnections =
- std::make_shared<std::map<std::string, std::string>>();
+ // Build map of LED object paths to connections
+ std::shared_ptr<std::map<std::string, std::string>> ledConnections =
+ std::make_shared<std::map<std::string, std::string>>();
- // Loop through objects from GetSubTree
- for (const std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>&
- object : subtree)
- {
- // Check if object path is LED for one of the specified inventory
- // items
- const std::string& ledPath = object.first;
- if (findInventoryItemForLed(*inventoryItems, ledPath) != nullptr)
+ // Loop through objects from GetSubTree
+ for (const std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>&
+ object : subtree)
{
- // Add mapping from ledPath to connection
- const std::string& connection = object.second.begin()->first;
- (*ledConnections)[ledPath] = connection;
- BMCWEB_LOG_DEBUG("Added mapping {} -> {}", ledPath, connection);
+ // Check if object path is LED for one of the specified
+ // inventory items
+ const std::string& ledPath = object.first;
+ if (findInventoryItemForLed(*inventoryItems, ledPath) !=
+ nullptr)
+ {
+ // Add mapping from ledPath to connection
+ const std::string& connection =
+ object.second.begin()->first;
+ (*ledConnections)[ledPath] = connection;
+ BMCWEB_LOG_DEBUG("Added mapping {} -> {}", ledPath,
+ connection);
+ }
}
- }
- getInventoryLedData(sensorsAsyncResp, inventoryItems, ledConnections,
- std::move(callback));
- BMCWEB_LOG_DEBUG("getInventoryLeds respHandler exit");
- });
+ getInventoryLedData(sensorsAsyncResp, inventoryItems,
+ ledConnections, std::move(callback));
+ BMCWEB_LOG_DEBUG("getInventoryLeds respHandler exit");
+ });
BMCWEB_LOG_DEBUG("getInventoryLeds exit");
}
@@ -1988,7 +1517,7 @@ void getPowerSupplyAttributesData(
auto respHandler = [sensorsAsyncResp, inventoryItems,
callback = std::forward<Callback>(callback)](
const boost::system::error_code& ec,
- const uint32_t value) {
+ uint32_t value) mutable {
BMCWEB_LOG_DEBUG("getPowerSupplyAttributesData respHandler enter");
if (ec)
{
@@ -2055,7 +1584,7 @@ void getPowerSupplyAttributes(
BMCWEB_LOG_DEBUG("getPowerSupplyAttributes enter");
// Only need the power supply attributes when the Power Schema
- if (sensorsAsyncResp->chassisSubNode != sensors::node::power)
+ if (sensorsAsyncResp->chassisSubNode != sensors::powerNodeStr)
{
BMCWEB_LOG_DEBUG("getPowerSupplyAttributes exit since not Power");
callback(inventoryItems);
@@ -2071,54 +1600,54 @@ void getPowerSupplyAttributes(
[callback = std::forward<Callback>(callback), sensorsAsyncResp,
inventoryItems](
const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree) {
- // Response handler for parsing output from GetSubTree
- BMCWEB_LOG_DEBUG("getPowerSupplyAttributes respHandler enter");
- if (ec)
- {
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- BMCWEB_LOG_ERROR(
- "getPowerSupplyAttributes respHandler DBus error {}", ec);
- return;
- }
- if (subtree.empty())
- {
- BMCWEB_LOG_DEBUG("Can't find Power Supply Attributes!");
- callback(inventoryItems);
- return;
- }
+ const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
+ // Response handler for parsing output from GetSubTree
+ BMCWEB_LOG_DEBUG("getPowerSupplyAttributes respHandler enter");
+ if (ec)
+ {
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ BMCWEB_LOG_ERROR(
+ "getPowerSupplyAttributes respHandler DBus error {}", ec);
+ return;
+ }
+ if (subtree.empty())
+ {
+ BMCWEB_LOG_DEBUG("Can't find Power Supply Attributes!");
+ callback(inventoryItems);
+ return;
+ }
- // Currently we only support 1 power supply attribute, use this for
- // all the power supplies. Build map of object path to connection.
- // Assume just 1 connection and 1 path for now.
- std::map<std::string, std::string> psAttributesConnections;
+ // Currently we only support 1 power supply attribute, use this for
+ // all the power supplies. Build map of object path to connection.
+ // Assume just 1 connection and 1 path for now.
+ std::map<std::string, std::string> psAttributesConnections;
- if (subtree[0].first.empty() || subtree[0].second.empty())
- {
- BMCWEB_LOG_DEBUG("Power Supply Attributes mapper error!");
- callback(inventoryItems);
- return;
- }
+ if (subtree[0].first.empty() || subtree[0].second.empty())
+ {
+ BMCWEB_LOG_DEBUG("Power Supply Attributes mapper error!");
+ callback(inventoryItems);
+ return;
+ }
- const std::string& psAttributesPath = subtree[0].first;
- const std::string& connection = subtree[0].second.begin()->first;
+ const std::string& psAttributesPath = subtree[0].first;
+ const std::string& connection = subtree[0].second.begin()->first;
- if (connection.empty())
- {
- BMCWEB_LOG_DEBUG("Power Supply Attributes mapper error!");
- callback(inventoryItems);
- return;
- }
+ if (connection.empty())
+ {
+ BMCWEB_LOG_DEBUG("Power Supply Attributes mapper error!");
+ callback(inventoryItems);
+ return;
+ }
- psAttributesConnections[psAttributesPath] = connection;
- BMCWEB_LOG_DEBUG("Added mapping {} -> {}", psAttributesPath,
- connection);
+ psAttributesConnections[psAttributesPath] = connection;
+ BMCWEB_LOG_DEBUG("Added mapping {} -> {}", psAttributesPath,
+ connection);
- getPowerSupplyAttributesData(sensorsAsyncResp, inventoryItems,
- psAttributesConnections,
- std::move(callback));
- BMCWEB_LOG_DEBUG("getPowerSupplyAttributes respHandler exit");
- });
+ getPowerSupplyAttributesData(sensorsAsyncResp, inventoryItems,
+ psAttributesConnections,
+ std::move(callback));
+ BMCWEB_LOG_DEBUG("getPowerSupplyAttributes respHandler exit");
+ });
BMCWEB_LOG_DEBUG("getPowerSupplyAttributes exit");
}
@@ -2145,7 +1674,7 @@ void getPowerSupplyAttributes(
* @param callback Callback to invoke when inventory items have been obtained.
*/
template <typename Callback>
-static void
+inline void
getInventoryItems(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp,
const std::shared_ptr<std::set<std::string>> sensorNames,
Callback&& callback)
@@ -2153,45 +1682,55 @@ static void
BMCWEB_LOG_DEBUG("getInventoryItems enter");
auto getInventoryItemAssociationsCb =
[sensorsAsyncResp, callback = std::forward<Callback>(callback)](
- std::shared_ptr<std::vector<InventoryItem>> inventoryItems) {
- BMCWEB_LOG_DEBUG("getInventoryItemAssociationsCb enter");
- auto getInventoryItemsConnectionsCb =
- [sensorsAsyncResp, inventoryItems,
- callback = std::forward<const Callback>(callback)](
- std::shared_ptr<std::set<std::string>> invConnections) {
- BMCWEB_LOG_DEBUG("getInventoryItemsConnectionsCb enter");
- auto getInventoryItemsDataCb = [sensorsAsyncResp, inventoryItems,
- callback{std::move(callback)}]() {
- BMCWEB_LOG_DEBUG("getInventoryItemsDataCb enter");
-
- auto getInventoryLedsCb = [sensorsAsyncResp, inventoryItems,
- callback{std::move(callback)}]() {
- BMCWEB_LOG_DEBUG("getInventoryLedsCb enter");
- // Find Power Supply Attributes and get the data
- getPowerSupplyAttributes(sensorsAsyncResp, inventoryItems,
- std::move(callback));
- BMCWEB_LOG_DEBUG("getInventoryLedsCb exit");
+ std::shared_ptr<std::vector<InventoryItem>>
+ inventoryItems) mutable {
+ BMCWEB_LOG_DEBUG("getInventoryItemAssociationsCb enter");
+ auto getInventoryItemsConnectionsCb =
+ [sensorsAsyncResp, inventoryItems,
+ callback = std::forward<Callback>(callback)](
+ std::shared_ptr<std::set<std::string>>
+ invConnections) mutable {
+ BMCWEB_LOG_DEBUG("getInventoryItemsConnectionsCb enter");
+ auto getInventoryItemsDataCb =
+ [sensorsAsyncResp, inventoryItems,
+ callback =
+ std::forward<Callback>(callback)]() mutable {
+ BMCWEB_LOG_DEBUG("getInventoryItemsDataCb enter");
+
+ auto getInventoryLedsCb =
+ [sensorsAsyncResp, inventoryItems,
+ callback = std::forward<Callback>(
+ callback)]() mutable {
+ BMCWEB_LOG_DEBUG(
+ "getInventoryLedsCb enter");
+ // Find Power Supply Attributes and get the
+ // data
+ getPowerSupplyAttributes(
+ sensorsAsyncResp, inventoryItems,
+ std::move(callback));
+ BMCWEB_LOG_DEBUG("getInventoryLedsCb exit");
+ };
+
+ // Find led connections and get the data
+ getInventoryLeds(sensorsAsyncResp, inventoryItems,
+ std::move(getInventoryLedsCb));
+ BMCWEB_LOG_DEBUG("getInventoryItemsDataCb exit");
+ };
+
+ // Get inventory item data from connections
+ getInventoryItemsData(sensorsAsyncResp, inventoryItems,
+ invConnections,
+ std::move(getInventoryItemsDataCb));
+ BMCWEB_LOG_DEBUG("getInventoryItemsConnectionsCb exit");
};
- // Find led connections and get the data
- getInventoryLeds(sensorsAsyncResp, inventoryItems,
- std::move(getInventoryLedsCb));
- BMCWEB_LOG_DEBUG("getInventoryItemsDataCb exit");
- };
-
- // Get inventory item data from connections
- getInventoryItemsData(sensorsAsyncResp, inventoryItems,
- invConnections,
- std::move(getInventoryItemsDataCb));
- BMCWEB_LOG_DEBUG("getInventoryItemsConnectionsCb exit");
+ // Get connections that provide inventory item data
+ getInventoryItemsConnections(
+ sensorsAsyncResp, inventoryItems,
+ std::move(getInventoryItemsConnectionsCb));
+ BMCWEB_LOG_DEBUG("getInventoryItemAssociationsCb exit");
};
- // Get connections that provide inventory item data
- getInventoryItemsConnections(sensorsAsyncResp, inventoryItems,
- std::move(getInventoryItemsConnectionsCb));
- BMCWEB_LOG_DEBUG("getInventoryItemAssociationsCb exit");
- };
-
// Get associations from sensors to inventory items
getInventoryItemAssociations(sensorsAsyncResp, sensorNames,
std::move(getInventoryItemAssociationsCb));
@@ -2243,8 +1782,8 @@ inline nlohmann::json& getPowerSupply(nlohmann::json& powerSupplyArray,
// Add new PowerSupply object to JSON array
powerSupplyArray.push_back({});
nlohmann::json& powerSupply = powerSupplyArray.back();
- boost::urls::url url = boost::urls::format("/redfish/v1/Chassis/{}/Power",
- chassisId);
+ boost::urls::url url =
+ boost::urls::format("/redfish/v1/Chassis/{}/Power", chassisId);
url.set_fragment(("/PowerSupplies"_json_pointer).to_string());
powerSupply["@odata.id"] = std::move(url);
std::string escaped;
@@ -2255,7 +1794,7 @@ inline nlohmann::json& getPowerSupply(nlohmann::json& powerSupplyArray,
powerSupply["Model"] = inventoryItem.model;
powerSupply["PartNumber"] = inventoryItem.partNumber;
powerSupply["SerialNumber"] = inventoryItem.serialNumber;
- setLedState(powerSupply, &inventoryItem);
+ sensor_utils::setLedState(powerSupply, &inventoryItem);
if (inventoryItem.powerSupplyEfficiencyPercent >= 0)
{
@@ -2263,7 +1802,8 @@ inline nlohmann::json& getPowerSupply(nlohmann::json& powerSupplyArray,
inventoryItem.powerSupplyEfficiencyPercent;
}
- powerSupply["Status"]["State"] = getState(&inventoryItem, true);
+ powerSupply["Status"]["State"] =
+ sensor_utils::getState(&inventoryItem, true);
const char* health = inventoryItem.isFunctional ? "OK" : "Critical";
powerSupply["Status"]["Health"] = health;
@@ -2312,215 +1852,212 @@ inline void getSensorData(
[sensorsAsyncResp, sensorNames,
inventoryItems](const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& resp) {
- BMCWEB_LOG_DEBUG("getManagedObjectsCb enter");
- if (ec)
- {
- BMCWEB_LOG_ERROR("getManagedObjectsCb DBUS error: {}", ec);
- messages::internalError(sensorsAsyncResp->asyncResp->res);
- return;
- }
- // Go through all objects and update response with sensor data
- for (const auto& objDictEntry : resp)
- {
- const std::string& objPath =
- static_cast<const std::string&>(objDictEntry.first);
- BMCWEB_LOG_DEBUG("getManagedObjectsCb parsing object {}",
- objPath);
-
- std::vector<std::string> split;
- // Reserve space for
- // /xyz/openbmc_project/sensors/<name>/<subname>
- split.reserve(6);
- // NOLINTNEXTLINE
- bmcweb::split(split, objPath, '/');
- if (split.size() < 6)
+ BMCWEB_LOG_DEBUG("getManagedObjectsCb enter");
+ if (ec)
{
- BMCWEB_LOG_ERROR("Got path that isn't long enough {}",
- objPath);
- continue;
+ BMCWEB_LOG_ERROR("getManagedObjectsCb DBUS error: {}", ec);
+ messages::internalError(sensorsAsyncResp->asyncResp->res);
+ return;
}
- // These indexes aren't intuitive, as split puts an empty
- // string at the beginning
- const std::string& sensorType = split[4];
- const std::string& sensorName = split[5];
- BMCWEB_LOG_DEBUG("sensorName {} sensorType {}", sensorName,
- sensorType);
- if (sensorNames->find(objPath) == sensorNames->end())
+ auto chassisSubNode = sensor_utils::chassisSubNodeFromString(
+ sensorsAsyncResp->chassisSubNode);
+ // Go through all objects and update response with sensor data
+ for (const auto& objDictEntry : resp)
{
- BMCWEB_LOG_DEBUG("{} not in sensor list ", sensorName);
- continue;
- }
-
- // Find inventory item (if any) associated with sensor
- InventoryItem* inventoryItem =
- findInventoryItemForSensor(inventoryItems, objPath);
-
- const std::string& sensorSchema =
- sensorsAsyncResp->chassisSubNode;
-
- nlohmann::json* sensorJson = nullptr;
+ const std::string& objPath =
+ static_cast<const std::string&>(objDictEntry.first);
+ BMCWEB_LOG_DEBUG("getManagedObjectsCb parsing object {}",
+ objPath);
- if (sensorSchema == sensors::node::sensors &&
- !sensorsAsyncResp->efficientExpand)
- {
- std::string sensorTypeEscaped(sensorType);
- auto remove = std::ranges::remove(sensorTypeEscaped, '_');
-
- sensorTypeEscaped.erase(std::ranges::begin(remove),
- sensorTypeEscaped.end());
- std::string sensorId(sensorTypeEscaped);
- sensorId += "_";
- sensorId += sensorName;
-
- sensorsAsyncResp->asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/Chassis/{}/{}/{}",
- sensorsAsyncResp->chassisId,
- sensorsAsyncResp->chassisSubNode,
- sensorId);
- sensorJson = &(sensorsAsyncResp->asyncResp->res.jsonValue);
- }
- else
- {
- std::string fieldName;
- if (sensorsAsyncResp->efficientExpand)
+ std::vector<std::string> split;
+ // Reserve space for
+ // /xyz/openbmc_project/sensors/<name>/<subname>
+ split.reserve(6);
+ // NOLINTNEXTLINE
+ bmcweb::split(split, objPath, '/');
+ if (split.size() < 6)
{
- fieldName = "Members";
- }
- else if (sensorType == "temperature")
- {
- fieldName = "Temperatures";
+ BMCWEB_LOG_ERROR("Got path that isn't long enough {}",
+ objPath);
+ continue;
}
- else if (sensorType == "fan" || sensorType == "fan_tach" ||
- sensorType == "fan_pwm")
+ // These indexes aren't intuitive, as split puts an empty
+ // string at the beginning
+ const std::string& sensorType = split[4];
+ const std::string& sensorName = split[5];
+ BMCWEB_LOG_DEBUG("sensorName {} sensorType {}", sensorName,
+ sensorType);
+ if (sensorNames->find(objPath) == sensorNames->end())
{
- fieldName = "Fans";
+ BMCWEB_LOG_DEBUG("{} not in sensor list ", sensorName);
+ continue;
}
- else if (sensorType == "voltage")
+
+ // Find inventory item (if any) associated with sensor
+ InventoryItem* inventoryItem =
+ findInventoryItemForSensor(inventoryItems, objPath);
+
+ const std::string& sensorSchema =
+ sensorsAsyncResp->chassisSubNode;
+
+ nlohmann::json* sensorJson = nullptr;
+
+ if (sensorSchema == sensors::sensorsNodeStr &&
+ !sensorsAsyncResp->efficientExpand)
{
- fieldName = "Voltages";
+ std::string sensorId =
+ redfish::sensor_utils::getSensorId(sensorName,
+ sensorType);
+
+ sensorsAsyncResp->asyncResp->res
+ .jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/{}/{}",
+ sensorsAsyncResp->chassisId,
+ sensorsAsyncResp->chassisSubNode, sensorId);
+ sensorJson =
+ &(sensorsAsyncResp->asyncResp->res.jsonValue);
}
- else if (sensorType == "power")
+ else
{
- if (sensorName == "total_power")
+ std::string fieldName;
+ if (sensorsAsyncResp->efficientExpand)
+ {
+ fieldName = "Members";
+ }
+ else if (sensorType == "temperature")
{
- fieldName = "PowerControl";
+ fieldName = "Temperatures";
}
- else if ((inventoryItem != nullptr) &&
- (inventoryItem->isPowerSupply))
+ else if (sensorType == "fan" ||
+ sensorType == "fan_tach" ||
+ sensorType == "fan_pwm")
{
- fieldName = "PowerSupplies";
+ fieldName = "Fans";
+ }
+ else if (sensorType == "voltage")
+ {
+ fieldName = "Voltages";
+ }
+ else if (sensorType == "power")
+ {
+ if (sensorName == "total_power")
+ {
+ fieldName = "PowerControl";
+ }
+ else if ((inventoryItem != nullptr) &&
+ (inventoryItem->isPowerSupply))
+ {
+ fieldName = "PowerSupplies";
+ }
+ else
+ {
+ // Other power sensors are in SensorCollection
+ continue;
+ }
}
else
{
- // Other power sensors are in SensorCollection
+ BMCWEB_LOG_ERROR(
+ "Unsure how to handle sensorType {}",
+ sensorType);
continue;
}
- }
- else
- {
- BMCWEB_LOG_ERROR("Unsure how to handle sensorType {}",
- sensorType);
- continue;
- }
- nlohmann::json& tempArray =
- sensorsAsyncResp->asyncResp->res.jsonValue[fieldName];
- if (fieldName == "PowerControl")
- {
- if (tempArray.empty())
+ nlohmann::json& tempArray =
+ sensorsAsyncResp->asyncResp->res
+ .jsonValue[fieldName];
+ if (fieldName == "PowerControl")
+ {
+ if (tempArray.empty())
+ {
+ // Put multiple "sensors" into a single
+ // PowerControl. Follows MemberId naming and
+ // naming in power.hpp.
+ nlohmann::json::object_t power;
+ boost::urls::url url = boost::urls::format(
+ "/redfish/v1/Chassis/{}/{}",
+ sensorsAsyncResp->chassisId,
+ sensorsAsyncResp->chassisSubNode);
+ url.set_fragment(
+ (""_json_pointer / fieldName / "0")
+ .to_string());
+ power["@odata.id"] = std::move(url);
+ tempArray.emplace_back(std::move(power));
+ }
+ sensorJson = &(tempArray.back());
+ }
+ else if (fieldName == "PowerSupplies")
+ {
+ if (inventoryItem != nullptr)
+ {
+ sensorJson = &(getPowerSupply(
+ tempArray, *inventoryItem,
+ sensorsAsyncResp->chassisId));
+ }
+ }
+ else if (fieldName == "Members")
+ {
+ std::string sensorId =
+ redfish::sensor_utils::getSensorId(sensorName,
+ sensorType);
+
+ nlohmann::json::object_t member;
+ member["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Chassis/{}/{}/{}",
+ sensorsAsyncResp->chassisId,
+ sensorsAsyncResp->chassisSubNode, sensorId);
+ tempArray.emplace_back(std::move(member));
+ sensorJson = &(tempArray.back());
+ }
+ else
{
- // Put multiple "sensors" into a single
- // PowerControl. Follows MemberId naming and
- // naming in power.hpp.
- nlohmann::json::object_t power;
+ nlohmann::json::object_t member;
boost::urls::url url = boost::urls::format(
"/redfish/v1/Chassis/{}/{}",
sensorsAsyncResp->chassisId,
sensorsAsyncResp->chassisSubNode);
- url.set_fragment((""_json_pointer / fieldName / "0")
- .to_string());
- power["@odata.id"] = std::move(url);
- tempArray.emplace_back(std::move(power));
+ url.set_fragment(
+ (""_json_pointer / fieldName).to_string());
+ member["@odata.id"] = std::move(url);
+ tempArray.emplace_back(std::move(member));
+ sensorJson = &(tempArray.back());
}
- sensorJson = &(tempArray.back());
}
- else if (fieldName == "PowerSupplies")
+
+ if (sensorJson != nullptr)
{
- if (inventoryItem != nullptr)
- {
- sensorJson =
- &(getPowerSupply(tempArray, *inventoryItem,
- sensorsAsyncResp->chassisId));
- }
+ objectInterfacesToJson(
+ sensorName, sensorType, chassisSubNode,
+ objDictEntry.second, *sensorJson, inventoryItem);
+
+ std::string path = "/xyz/openbmc_project/sensors/";
+ path += sensorType;
+ path += "/";
+ path += sensorName;
+ sensorsAsyncResp->addMetadata(*sensorJson, path);
}
- else if (fieldName == "Members")
+ }
+ if (sensorsAsyncResp.use_count() == 1)
+ {
+ sortJSONResponse(sensorsAsyncResp);
+ if (chassisSubNode ==
+ sensor_utils::ChassisSubNode::sensorsNode &&
+ sensorsAsyncResp->efficientExpand)
{
- std::string sensorTypeEscaped(sensorType);
- auto remove = std::ranges::remove(sensorTypeEscaped,
- '_');
- sensorTypeEscaped.erase(std::ranges::begin(remove),
- sensorTypeEscaped.end());
- std::string sensorId(sensorTypeEscaped);
- sensorId += "_";
- sensorId += sensorName;
-
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/Chassis/{}/{}/{}",
- sensorsAsyncResp->chassisId,
- sensorsAsyncResp->chassisSubNode, sensorId);
- tempArray.emplace_back(std::move(member));
- sensorJson = &(tempArray.back());
+ sensorsAsyncResp->asyncResp->res
+ .jsonValue["Members@odata.count"] =
+ sensorsAsyncResp->asyncResp->res
+ .jsonValue["Members"]
+ .size();
}
- else
+ else if (chassisSubNode ==
+ sensor_utils::ChassisSubNode::thermalNode)
{
- nlohmann::json::object_t member;
- boost::urls::url url = boost::urls::format(
- "/redfish/v1/Chassis/{}/{}",
- sensorsAsyncResp->chassisId,
- sensorsAsyncResp->chassisSubNode);
- url.set_fragment(
- (""_json_pointer / fieldName).to_string());
- member["@odata.id"] = std::move(url);
- tempArray.emplace_back(std::move(member));
- sensorJson = &(tempArray.back());
+ populateFanRedundancy(sensorsAsyncResp);
}
}
-
- if (sensorJson != nullptr)
- {
- objectInterfacesToJson(sensorName, sensorType,
- sensorsAsyncResp->chassisSubNode,
- objDictEntry.second, *sensorJson,
- inventoryItem);
-
- std::string path = "/xyz/openbmc_project/sensors/";
- path += sensorType;
- path += "/";
- path += sensorName;
- sensorsAsyncResp->addMetadata(*sensorJson, path);
- }
- }
- if (sensorsAsyncResp.use_count() == 1)
- {
- sortJSONResponse(sensorsAsyncResp);
- if (sensorsAsyncResp->chassisSubNode ==
- sensors::node::sensors &&
- sensorsAsyncResp->efficientExpand)
- {
- sensorsAsyncResp->asyncResp->res
- .jsonValue["Members@odata.count"] =
- sensorsAsyncResp->asyncResp->res.jsonValue["Members"]
- .size();
- }
- else if (sensorsAsyncResp->chassisSubNode ==
- sensors::node::thermal)
- {
- populateFanRedundancy(sensorsAsyncResp);
- }
- }
- BMCWEB_LOG_DEBUG("getManagedObjectsCb exit");
- });
+ BMCWEB_LOG_DEBUG("getManagedObjectsCb exit");
+ });
}
BMCWEB_LOG_DEBUG("getSensorData exit");
}
@@ -2533,15 +2070,15 @@ inline void
const std::set<std::string>& connections) {
BMCWEB_LOG_DEBUG("getConnectionCb enter");
auto getInventoryItemsCb =
- [sensorsAsyncResp, sensorNames,
- connections](const std::shared_ptr<std::vector<InventoryItem>>&
- inventoryItems) {
- BMCWEB_LOG_DEBUG("getInventoryItemsCb enter");
- // Get sensor data and store results in JSON
- getSensorData(sensorsAsyncResp, sensorNames, connections,
- inventoryItems);
- BMCWEB_LOG_DEBUG("getInventoryItemsCb exit");
- };
+ [sensorsAsyncResp, sensorNames, connections](
+ const std::shared_ptr<std::vector<InventoryItem>>&
+ inventoryItems) mutable {
+ BMCWEB_LOG_DEBUG("getInventoryItemsCb enter");
+ // Get sensor data and store results in JSON
+ getSensorData(sensorsAsyncResp, sensorNames, connections,
+ inventoryItems);
+ BMCWEB_LOG_DEBUG("getInventoryItemsCb exit");
+ };
// Get inventory items associated with sensors
getInventoryItems(sensorsAsyncResp, sensorNames,
@@ -2566,12 +2103,12 @@ inline void
auto getChassisCb =
[sensorsAsyncResp](
const std::shared_ptr<std::set<std::string>>& sensorNames) {
- BMCWEB_LOG_DEBUG("getChassisCb enter");
- processSensorList(sensorsAsyncResp, sensorNames);
- BMCWEB_LOG_DEBUG("getChassisCb exit");
- };
+ BMCWEB_LOG_DEBUG("getChassisCb enter");
+ processSensorList(sensorsAsyncResp, sensorNames);
+ BMCWEB_LOG_DEBUG("getChassisCb exit");
+ };
// SensorCollection doesn't contain the Redundancy property
- if (sensorsAsyncResp->chassisSubNode != sensors::node::sensors)
+ if (sensorsAsyncResp->chassisSubNode != sensors::sensorsNodeStr)
{
sensorsAsyncResp->asyncResp->res.jsonValue["Redundancy"] =
nlohmann::json::array();
@@ -2592,10 +2129,9 @@ inline void
* @param sensorsModified The list of sensors that were found as a result of
* repeated calls to this function
*/
-inline bool
- findSensorNameUsingSensorPath(std::string_view sensorName,
- const std::set<std::string>& sensorsList,
- std::set<std::string>& sensorsModified)
+inline bool findSensorNameUsingSensorPath(
+ std::string_view sensorName, const std::set<std::string>& sensorsList,
+ std::set<std::string>& sensorsModified)
{
for (const auto& chassisSensor : sensorsList)
{
@@ -2614,24 +2150,6 @@ inline bool
return false;
}
-inline std::pair<std::string, std::string>
- splitSensorNameAndType(std::string_view sensorId)
-{
- size_t index = sensorId.find('_');
- if (index == std::string::npos)
- {
- return std::make_pair<std::string, std::string>("", "");
- }
- std::string sensorType{sensorId.substr(0, index)};
- std::string sensorName{sensorId.substr(index + 1)};
- // fan_pwm and fan_tach need special handling
- if (sensorType == "fantach" || sensorType == "fanpwm")
- {
- sensorType.insert(3, 1, '_');
- }
- return std::make_pair(sensorType, sensorName);
-}
-
/**
* @brief Entry point for overriding sensor values of given sensor
*
@@ -2678,10 +2196,11 @@ inline void setSensorsOverride(
}
}
- auto getChassisSensorListCb =
- [sensorAsyncResp, overrideMap,
- propertyValueNameStr = std::string(propertyValueName)](
- const std::shared_ptr<std::set<std::string>>& sensorsList) {
+ auto getChassisSensorListCb = [sensorAsyncResp, overrideMap,
+ propertyValueNameStr =
+ std::string(propertyValueName)](
+ const std::shared_ptr<
+ std::set<std::string>>& sensorsList) {
// Match sensor names in the PATCH request to those managed by the
// chassis node
const std::shared_ptr<std::set<std::string>> sensorNames =
@@ -2690,7 +2209,7 @@ inline void setSensorsOverride(
{
const auto& sensor = item.first;
std::pair<std::string, std::string> sensorNameType =
- splitSensorNameAndType(sensor);
+ redfish::sensor_utils::splitSensorNameAndType(sensor);
if (!findSensorNameUsingSensorPath(sensorNameType.second,
*sensorsList, *sensorNames))
{
@@ -2701,22 +2220,24 @@ inline void setSensorsOverride(
}
}
// Get the connection to which the memberId belongs
- auto getObjectsWithConnectionCb =
- [sensorAsyncResp, overrideMap, propertyValueNameStr](
- const std::set<std::string>& /*connections*/,
- const std::set<std::pair<std::string, std::string>>&
- objectsWithConnection) {
+ auto getObjectsWithConnectionCb = [sensorAsyncResp, overrideMap,
+ propertyValueNameStr](
+ const std::set<
+ std::string>& /*connections*/,
+ const std::set<std::pair<
+ std::string, std::string>>&
+ objectsWithConnection) {
if (objectsWithConnection.size() != overrideMap.size())
{
BMCWEB_LOG_INFO(
"Unable to find all objects with proper connection {} requested {}",
objectsWithConnection.size(), overrideMap.size());
- messages::resourceNotFound(sensorAsyncResp->asyncResp->res,
- sensorAsyncResp->chassisSubNode ==
- sensors::node::thermal
- ? "Temperatures"
- : "Voltages",
- "Count");
+ messages::resourceNotFound(
+ sensorAsyncResp->asyncResp->res,
+ sensorAsyncResp->chassisSubNode == sensors::thermalNodeStr
+ ? "Temperatures"
+ : "Voltages",
+ "Count");
return;
}
for (const auto& item : objectsWithConnection)
@@ -2728,11 +2249,8 @@ inline void setSensorsOverride(
messages::internalError(sensorAsyncResp->asyncResp->res);
return;
}
- std::string id = path.parent_path().filename();
- auto remove = std::ranges::remove(id, '_');
- id.erase(std::ranges::begin(remove), id.end());
- id += "_";
- id += sensorName;
+ std::string id = redfish::sensor_utils::getSensorId(
+ sensorName, path.parent_path().filename());
const auto& iterator = overrideMap.find(id);
if (iterator == overrideMap.end())
@@ -2767,13 +2285,13 @@ inline void setSensorsOverride(
* it to caller in a callback.
*
* @param chassis Chassis for which retrieval should be performed
- * @param node Node (group) of sensors. See sensors::node for supported values
+ * @param node Node (group) of sensors. See sensor_utils::node for supported
+ * values
* @param mapComplete Callback to be called with retrieval result
*/
template <typename Callback>
-inline void retrieveUriToDbusMap(const std::string& chassis,
- const std::string& node,
- Callback&& mapComplete)
+inline void retrieveUriToDbusMap(
+ const std::string& chassis, const std::string& node, Callback&& mapComplete)
{
decltype(sensors::paths)::const_iterator pathIt =
std::find_if(sensors::paths.cbegin(), sensors::paths.cend(),
@@ -2787,12 +2305,12 @@ inline void retrieveUriToDbusMap(const std::string& chassis,
}
auto asyncResp = std::make_shared<bmcweb::AsyncResp>();
- auto callback = [asyncResp,
- mapCompleteCb = std::forward<Callback>(mapComplete)](
- const boost::beast::http::status status,
- const std::map<std::string, std::string>& uriToDbus) {
- mapCompleteCb(status, uriToDbus);
- };
+ auto callback =
+ [asyncResp, mapCompleteCb = std::forward<Callback>(mapComplete)](
+ const boost::beast::http::status status,
+ const std::map<std::string, std::string>& uriToDbus) {
+ mapCompleteCb(status, uriToDbus);
+ };
auto resp = std::make_shared<SensorsAsyncResp>(
asyncResp, chassis, pathIt->second, node, std::move(callback));
@@ -2823,15 +2341,9 @@ inline void getChassisCallback(
return;
}
std::string type = path.parent_path().filename();
- // fan_tach has an underscore in it, so remove it to "normalize" the
- // type in the URI
- auto remove = std::ranges::remove(type, '_');
- type.erase(std::ranges::begin(remove), type.end());
+ std::string id = redfish::sensor_utils::getSensorId(sensorName, type);
nlohmann::json::object_t member;
- std::string id = type;
- id += "_";
- id += sensorName;
member["@odata.id"] = boost::urls::format(
"/redfish/v1/Chassis/{}/{}/{}", chassisId, chassisSubNode, id);
@@ -2862,7 +2374,7 @@ inline void handleSensorCollectionGet(
// we perform efficient expand.
auto sensorsAsyncResp = std::make_shared<SensorsAsyncResp>(
asyncResp, chassisId, sensors::dbus::sensorPaths,
- sensors::node::sensors,
+ sensors::sensorsNodeStr,
/*efficientExpand=*/true);
getChassisData(sensorsAsyncResp);
@@ -2873,9 +2385,9 @@ inline void handleSensorCollectionGet(
// We get all sensors as hyperlinkes in the chassis (this
// implies we reply on the default query parameters handler)
- getChassis(asyncResp, chassisId, sensors::node::sensors, dbus::sensorPaths,
+ getChassis(asyncResp, chassisId, sensors::sensorsNodeStr, dbus::sensorPaths,
std::bind_front(sensors::getChassisCallback, asyncResp,
- chassisId, sensors::node::sensors));
+ chassisId, sensors::sensorsNodeStr));
}
inline void
@@ -2898,18 +2410,19 @@ inline void
[asyncResp,
sensorPath](const boost::system::error_code& ec,
const ::dbus::utility::DBusPropertiesMap& valuesDict) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- sdbusplus::message::object_path path(sensorPath);
- std::string name = path.filename();
- path = path.parent_path();
- std::string type = path.filename();
- objectPropertiesToJson(name, type, sensors::node::sensors, valuesDict,
- asyncResp->res.jsonValue, nullptr);
- });
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ sdbusplus::message::object_path path(sensorPath);
+ std::string name = path.filename();
+ path = path.parent_path();
+ std::string type = path.filename();
+ sensor_utils::objectPropertiesToJson(
+ name, type, sensor_utils::ChassisSubNode::sensorsNode,
+ valuesDict, asyncResp->res.jsonValue, nullptr);
+ });
}
inline void handleSensorGet(App& app, const crow::Request& req,
@@ -2922,7 +2435,7 @@ inline void handleSensorGet(App& app, const crow::Request& req,
return;
}
std::pair<std::string, std::string> nameType =
- splitSensorNameAndType(sensorId);
+ redfish::sensor_utils::splitSensorNameAndType(sensorId);
if (nameType.first.empty() || nameType.second.empty())
{
messages::resourceNotFound(asyncResp->res, sensorId, "Sensor");
@@ -2945,23 +2458,23 @@ inline void handleSensorGet(App& app, const crow::Request& req,
[asyncResp, sensorId,
sensorPath](const boost::system::error_code& ec,
const ::dbus::utility::MapperGetObject& subtree) {
- BMCWEB_LOG_DEBUG("respHandler1 enter");
- if (ec == boost::system::errc::io_error)
- {
- BMCWEB_LOG_WARNING("Sensor not found from getSensorPaths");
- messages::resourceNotFound(asyncResp->res, sensorId, "Sensor");
- return;
- }
- if (ec)
- {
- messages::internalError(asyncResp->res);
- BMCWEB_LOG_ERROR(
- "Sensor getSensorPaths resp_handler: Dbus error {}", ec);
- return;
- }
- getSensorFromDbus(asyncResp, sensorPath, subtree);
- BMCWEB_LOG_DEBUG("respHandler1 exit");
- });
+ BMCWEB_LOG_DEBUG("respHandler1 enter");
+ if (ec == boost::system::errc::io_error)
+ {
+ BMCWEB_LOG_WARNING("Sensor not found from getSensorPaths");
+ messages::resourceNotFound(asyncResp->res, sensorId, "Sensor");
+ return;
+ }
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ BMCWEB_LOG_ERROR(
+ "Sensor getSensorPaths resp_handler: Dbus error {}", ec);
+ return;
+ }
+ getSensorFromDbus(asyncResp, sensorPath, subtree);
+ BMCWEB_LOG_DEBUG("respHandler1 exit");
+ });
}
} // namespace sensors
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 57b967c427..ca640749ed 100644
--- a/redfish-core/lib/service_root.hpp
+++ b/redfish-core/lib/service_root.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index e0ad737752..e670de72e3 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2019 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2019 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -21,6 +21,7 @@
#include "dbus_utility.hpp"
#include "generated/enums/drive.hpp"
#include "generated/enums/protocol.hpp"
+#include "generated/enums/resource.hpp"
#include "human_sort.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
@@ -162,9 +163,9 @@ inline void afterSystemsStorageGetSubtree(
subtree,
[&storageId](const std::pair<std::string,
dbus::utility::MapperServiceMap>& object) {
- return sdbusplus::message::object_path(object.first).filename() ==
- storageId;
- });
+ return sdbusplus::message::object_path(object.first).filename() ==
+ storageId;
+ });
if (storage == subtree.end())
{
messages::resourceNotFound(asyncResp->res, "#Storage.v1_13_0.Storage",
@@ -178,7 +179,7 @@ inline void afterSystemsStorageGetSubtree(
BMCWEB_REDFISH_SYSTEM_URI_NAME, storageId);
asyncResp->res.jsonValue["Name"] = "Storage";
asyncResp->res.jsonValue["Id"] = storageId;
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
getDrives(asyncResp);
asyncResp->res.jsonValue["Controllers"]["@odata.id"] =
@@ -186,11 +187,10 @@ inline void afterSystemsStorageGetSubtree(
BMCWEB_REDFISH_SYSTEM_URI_NAME, storageId);
}
-inline void
- handleSystemsStorageGet(App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& systemName,
- const std::string& storageId)
+inline void handleSystemsStorageGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& storageId)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -227,9 +227,9 @@ inline void afterSubtree(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
subtree,
[&storageId](const std::pair<std::string,
dbus::utility::MapperServiceMap>& object) {
- return sdbusplus::message::object_path(object.first).filename() ==
- storageId;
- });
+ return sdbusplus::message::object_path(object.first).filename() ==
+ storageId;
+ });
if (storage == subtree.end())
{
messages::resourceNotFound(asyncResp->res, "#Storage.v1_13_0.Storage",
@@ -242,7 +242,7 @@ inline void afterSubtree(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
boost::urls::format("/redfish/v1/Storage/{}", storageId);
asyncResp->res.jsonValue["Name"] = "Storage";
asyncResp->res.jsonValue["Id"] = storageId;
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
// Storage subsystem to Storage link.
nlohmann::json::array_t storageServices;
@@ -298,48 +298,48 @@ inline void getDriveAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::vector<
std::pair<std::string, dbus::utility::DbusVariantType>>&
propertiesList) {
- if (ec)
- {
- // this interface isn't necessary
- return;
- }
+ if (ec)
+ {
+ // this interface isn't necessary
+ return;
+ }
- const std::string* partNumber = nullptr;
- const std::string* serialNumber = nullptr;
- const std::string* manufacturer = nullptr;
- const std::string* model = nullptr;
+ const std::string* partNumber = nullptr;
+ const std::string* serialNumber = nullptr;
+ const std::string* manufacturer = nullptr;
+ const std::string* model = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
- partNumber, "SerialNumber", serialNumber, "Manufacturer",
- manufacturer, "Model", model);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
+ partNumber, "SerialNumber", serialNumber, "Manufacturer",
+ manufacturer, "Model", model);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (partNumber != nullptr)
- {
- asyncResp->res.jsonValue["PartNumber"] = *partNumber;
- }
+ if (partNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["PartNumber"] = *partNumber;
+ }
- if (serialNumber != nullptr)
- {
- asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
- }
+ if (serialNumber != nullptr)
+ {
+ asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
+ }
- if (manufacturer != nullptr)
- {
- asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
- }
+ if (manufacturer != nullptr)
+ {
+ asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
+ }
- if (model != nullptr)
- {
- asyncResp->res.jsonValue["Model"] = *model;
- }
- });
+ if (model != nullptr)
+ {
+ asyncResp->res.jsonValue["Model"] = *model;
+ }
+ });
}
inline void getDrivePresent(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -349,20 +349,21 @@ inline void getDrivePresent(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
sdbusplus::asio::getProperty<bool>(
*crow::connections::systemBus, connectionName, path,
"xyz.openbmc_project.Inventory.Item", "Present",
- [asyncResp, path](const boost::system::error_code& ec,
- const bool isPresent) {
- // this interface isn't necessary, only check it if
- // we get a good return
- if (ec)
- {
- return;
- }
+ [asyncResp,
+ path](const boost::system::error_code& ec, const bool isPresent) {
+ // this interface isn't necessary, only check it if
+ // we get a good return
+ if (ec)
+ {
+ return;
+ }
- if (!isPresent)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ if (!isPresent)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ }
+ });
}
inline void getDriveState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -373,22 +374,23 @@ inline void getDriveState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
*crow::connections::systemBus, connectionName, path,
"xyz.openbmc_project.State.Drive", "Rebuilding",
[asyncResp](const boost::system::error_code& ec, const bool updating) {
- // this interface isn't necessary, only check it
- // if we get a good return
- if (ec)
- {
- return;
- }
+ // this interface isn't necessary, only check it
+ // if we get a good return
+ if (ec)
+ {
+ return;
+ }
- // updating and disabled in the backend shouldn't be
- // able to be set at the same time, so we don't need
- // to check for the race condition of these two
- // calls
- if (updating)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Updating";
- }
- });
+ // updating and disabled in the backend shouldn't be
+ // able to be set at the same time, so we don't need
+ // to check for the race condition of these two
+ // calls
+ if (updating)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Updating;
+ }
+ });
}
inline std::optional<drive::MediaType> convertDriveType(std::string_view type)
@@ -437,10 +439,9 @@ inline std::optional<protocol::Protocol>
return protocol::Protocol::Invalid;
}
-inline void
- getDriveItemProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& connectionName,
- const std::string& path)
+inline void getDriveItemProperties(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& connectionName, const std::string& path)
{
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, connectionName, path,
@@ -449,160 +450,162 @@ inline void
const std::vector<
std::pair<std::string, dbus::utility::DbusVariantType>>&
propertiesList) {
- if (ec)
- {
- // this interface isn't required
- return;
- }
- const std::string* encryptionStatus = nullptr;
- const bool* isLocked = nullptr;
- for (const std::pair<std::string, dbus::utility::DbusVariantType>&
- property : propertiesList)
- {
- const std::string& propertyName = property.first;
- if (propertyName == "Type")
+ if (ec)
{
- const std::string* value =
- std::get_if<std::string>(&property.second);
- if (value == nullptr)
- {
- // illegal property
- BMCWEB_LOG_ERROR("Illegal property: Type");
- messages::internalError(asyncResp->res);
- return;
- }
-
- std::optional<drive::MediaType> mediaType =
- convertDriveType(*value);
- if (!mediaType)
- {
- BMCWEB_LOG_WARNING("UnknownDriveType Interface: {}",
- *value);
- continue;
- }
- if (*mediaType == drive::MediaType::Invalid)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- asyncResp->res.jsonValue["MediaType"] = *mediaType;
+ // this interface isn't required
+ return;
}
- else if (propertyName == "Capacity")
+ const std::string* encryptionStatus = nullptr;
+ const bool* isLocked = nullptr;
+ for (const std::pair<std::string, dbus::utility::DbusVariantType>&
+ property : propertiesList)
{
- const uint64_t* capacity =
- std::get_if<uint64_t>(&property.second);
- if (capacity == nullptr)
+ const std::string& propertyName = property.first;
+ if (propertyName == "Type")
{
- BMCWEB_LOG_ERROR("Illegal property: Capacity");
- messages::internalError(asyncResp->res);
- return;
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+ if (value == nullptr)
+ {
+ // illegal property
+ BMCWEB_LOG_ERROR("Illegal property: Type");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::optional<drive::MediaType> mediaType =
+ convertDriveType(*value);
+ if (!mediaType)
+ {
+ BMCWEB_LOG_WARNING("UnknownDriveType Interface: {}",
+ *value);
+ continue;
+ }
+ if (*mediaType == drive::MediaType::Invalid)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ asyncResp->res.jsonValue["MediaType"] = *mediaType;
}
- if (*capacity == 0)
+ else if (propertyName == "Capacity")
{
- // drive capacity not known
- continue;
+ const uint64_t* capacity =
+ std::get_if<uint64_t>(&property.second);
+ if (capacity == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Illegal property: Capacity");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (*capacity == 0)
+ {
+ // drive capacity not known
+ continue;
+ }
+
+ asyncResp->res.jsonValue["CapacityBytes"] = *capacity;
}
-
- asyncResp->res.jsonValue["CapacityBytes"] = *capacity;
- }
- else if (propertyName == "Protocol")
- {
- const std::string* value =
- std::get_if<std::string>(&property.second);
- if (value == nullptr)
+ else if (propertyName == "Protocol")
{
- BMCWEB_LOG_ERROR("Illegal property: Protocol");
- messages::internalError(asyncResp->res);
- return;
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+ if (value == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Illegal property: Protocol");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ std::optional<protocol::Protocol> proto =
+ convertDriveProtocol(*value);
+ if (!proto)
+ {
+ BMCWEB_LOG_WARNING(
+ "Unknown DrivePrototype Interface: {}", *value);
+ continue;
+ }
+ if (*proto == protocol::Protocol::Invalid)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ asyncResp->res.jsonValue["Protocol"] = *proto;
}
-
- std::optional<protocol::Protocol> proto =
- convertDriveProtocol(*value);
- if (!proto)
+ else if (propertyName == "PredictedMediaLifeLeftPercent")
{
- BMCWEB_LOG_WARNING("Unknown DrivePrototype Interface: {}",
- *value);
- continue;
- }
- if (*proto == protocol::Protocol::Invalid)
- {
- messages::internalError(asyncResp->res);
- return;
+ const uint8_t* lifeLeft =
+ std::get_if<uint8_t>(&property.second);
+ if (lifeLeft == nullptr)
+ {
+ BMCWEB_LOG_ERROR(
+ "Illegal property: PredictedMediaLifeLeftPercent");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // 255 means reading the value is not supported
+ if (*lifeLeft != 255)
+ {
+ asyncResp->res
+ .jsonValue["PredictedMediaLifeLeftPercent"] =
+ *lifeLeft;
+ }
}
- asyncResp->res.jsonValue["Protocol"] = *proto;
- }
- else if (propertyName == "PredictedMediaLifeLeftPercent")
- {
- const uint8_t* lifeLeft =
- std::get_if<uint8_t>(&property.second);
- if (lifeLeft == nullptr)
+ else if (propertyName == "EncryptionStatus")
{
- BMCWEB_LOG_ERROR(
- "Illegal property: PredictedMediaLifeLeftPercent");
- messages::internalError(asyncResp->res);
- return;
+ encryptionStatus =
+ std::get_if<std::string>(&property.second);
+ if (encryptionStatus == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Illegal property: EncryptionStatus");
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
- // 255 means reading the value is not supported
- if (*lifeLeft != 255)
+ else if (propertyName == "Locked")
{
- asyncResp->res.jsonValue["PredictedMediaLifeLeftPercent"] =
- *lifeLeft;
+ isLocked = std::get_if<bool>(&property.second);
+ if (isLocked == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Illegal property: Locked");
+ messages::internalError(asyncResp->res);
+ return;
+ }
}
}
- else if (propertyName == "EncryptionStatus")
+
+ if (encryptionStatus == nullptr || isLocked == nullptr ||
+ *encryptionStatus ==
+ "xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Unknown")
{
- encryptionStatus = std::get_if<std::string>(&property.second);
- if (encryptionStatus == nullptr)
- {
- BMCWEB_LOG_ERROR("Illegal property: EncryptionStatus");
- messages::internalError(asyncResp->res);
- return;
- }
+ return;
}
- else if (propertyName == "Locked")
+ if (*encryptionStatus !=
+ "xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Encrypted")
{
- isLocked = std::get_if<bool>(&property.second);
- if (isLocked == nullptr)
- {
- BMCWEB_LOG_ERROR("Illegal property: Locked");
- messages::internalError(asyncResp->res);
- return;
- }
+ //"The drive is not currently encrypted."
+ asyncResp->res.jsonValue["EncryptionStatus"] =
+ drive::EncryptionStatus::Unencrypted;
+ return;
}
- }
-
- if (encryptionStatus == nullptr || isLocked == nullptr ||
- *encryptionStatus ==
- "xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Unknown")
- {
- return;
- }
- if (*encryptionStatus !=
- "xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Encrypted")
- {
- //"The drive is not currently encrypted."
- asyncResp->res.jsonValue["EncryptionStatus"] =
- drive::EncryptionStatus::Unencrypted;
- return;
- }
- if (*isLocked)
- {
- //"The drive is currently encrypted and the data is not
- // accessible to the user."
+ if (*isLocked)
+ {
+ //"The drive is currently encrypted and the data is not
+ // accessible to the user."
+ asyncResp->res.jsonValue["EncryptionStatus"] =
+ drive::EncryptionStatus::Locked;
+ return;
+ }
+ // if not locked
+ // "The drive is currently encrypted but the data is accessible
+ // to the user in unencrypted form."
asyncResp->res.jsonValue["EncryptionStatus"] =
- drive::EncryptionStatus::Locked;
- return;
- }
- // if not locked
- // "The drive is currently encrypted but the data is accessible
- // to the user in unencrypted form."
- asyncResp->res.jsonValue["EncryptionStatus"] =
- drive::EncryptionStatus::Unlocked;
- });
+ drive::EncryptionStatus::Unlocked;
+ });
}
-static void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+inline void addAllDriveInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& connectionName,
const std::string& path,
const std::vector<std::string>& interfaces)
@@ -644,9 +647,9 @@ inline void afterGetSubtreeSystemsStorageDrive(
subtree,
[&driveId](const std::pair<std::string,
dbus::utility::MapperServiceMap>& object) {
- return sdbusplus::message::object_path(object.first).filename() ==
- driveId;
- });
+ return sdbusplus::message::object_path(object.first).filename() ==
+ driveId;
+ });
if (drive == subtree.end())
{
@@ -672,15 +675,15 @@ inline void afterGetSubtreeSystemsStorageDrive(
return;
}
- getMainChassisId(asyncResp,
- [](const std::string& chassisId,
- const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
- aRsp->res.jsonValue["Links"]["Chassis"]["@odata.id"] =
- boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
- });
+ getMainChassisId(
+ asyncResp, [](const std::string& chassisId,
+ const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
+ aRsp->res.jsonValue["Links"]["Chassis"]["@odata.id"] =
+ boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
+ });
// default it to Enabled
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
addAllDriveInfo(asyncResp, connectionNames[0].first, path,
connectionNames[0].second);
@@ -768,35 +771,36 @@ inline void afterChassisDriveCollectionSubtreeGet(
path + "/drive",
[asyncResp, chassisId](const boost::system::error_code& ec3,
const dbus::utility::MapperEndPoints& resp) {
- if (ec3)
- {
- BMCWEB_LOG_ERROR("Error in chassis Drive association ");
- }
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- // important if array is empty
- members = nlohmann::json::array();
+ if (ec3)
+ {
+ BMCWEB_LOG_ERROR("Error in chassis Drive association ");
+ }
+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
+ // important if array is empty
+ members = nlohmann::json::array();
- std::vector<std::string> leafNames;
- for (const auto& drive : resp)
- {
- sdbusplus::message::object_path drivePath(drive);
- leafNames.push_back(drivePath.filename());
- }
+ std::vector<std::string> leafNames;
+ for (const auto& drive : resp)
+ {
+ sdbusplus::message::object_path drivePath(drive);
+ leafNames.push_back(drivePath.filename());
+ }
- std::ranges::sort(leafNames, AlphanumLess<std::string>());
+ std::ranges::sort(leafNames, AlphanumLess<std::string>());
- for (const auto& leafName : leafNames)
- {
- nlohmann::json::object_t member;
- member["@odata.id"] = boost::urls::format(
- "/redfish/v1/Chassis/{}/Drives/{}", chassisId, leafName);
- members.emplace_back(std::move(member));
- // navigation links will be registered in next patch set
- }
- asyncResp->res.jsonValue["Members@odata.count"] = resp.size();
- }); // end association lambda
+ for (const auto& leafName : leafNames)
+ {
+ nlohmann::json::object_t member;
+ member["@odata.id"] =
+ boost::urls::format("/redfish/v1/Chassis/{}/Drives/{}",
+ chassisId, leafName);
+ members.emplace_back(std::move(member));
+ // navigation links will be registered in next patch set
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = resp.size();
+ }); // end association lambda
- } // end Iterate over all retrieved ObjectPaths
+ } // end Iterate over all retrieved ObjectPaths
}
/**
* Chassis drives, this URL will show all the DriveCollection
@@ -865,7 +869,7 @@ inline void buildDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
asyncResp->res.jsonValue["Name"] = driveName;
asyncResp->res.jsonValue["Id"] = driveName;
// default it to Enabled
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
nlohmann::json::object_t linkChassisNav;
linkChassisNav["@odata.id"] =
@@ -877,11 +881,10 @@ inline void buildDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
}
}
-inline void
- matchAndFillDrive(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::string& driveName,
- const std::vector<std::string>& resp)
+inline void matchAndFillDrive(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const std::string& driveName,
+ const std::vector<std::string>& resp)
{
for (const std::string& drivePath : resp)
{
@@ -899,16 +902,15 @@ inline void
[asyncResp, chassisId, driveName](
const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- buildDrive(asyncResp, chassisId, driveName, ec, subtree);
- });
+ buildDrive(asyncResp, chassisId, driveName, ec, subtree);
+ });
}
}
-inline void
- handleChassisDriveGet(crow::App& app, const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& chassisId,
- const std::string& driveName)
+inline void handleChassisDriveGet(
+ crow::App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& chassisId, const std::string& driveName)
{
if (!redfish::setUpRedfishRoute(app, req, asyncResp))
{
@@ -924,41 +926,42 @@ inline void
[asyncResp, chassisId,
driveName](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Iterate over all retrieved ObjectPaths.
- for (const auto& [path, connectionNames] : subtree)
- {
- sdbusplus::message::object_path objPath(path);
- if (objPath.filename() != chassisId)
+ if (ec)
{
- continue;
+ messages::internalError(asyncResp->res);
+ return;
}
- if (connectionNames.empty())
+ // Iterate over all retrieved ObjectPaths.
+ for (const auto& [path, connectionNames] : subtree)
{
- BMCWEB_LOG_ERROR("Got 0 Connection names");
- continue;
- }
+ sdbusplus::message::object_path objPath(path);
+ if (objPath.filename() != chassisId)
+ {
+ continue;
+ }
- dbus::utility::getAssociationEndPoints(
- path + "/drive",
- [asyncResp, chassisId,
- driveName](const boost::system::error_code& ec3,
- const dbus::utility::MapperEndPoints& resp) {
- if (ec3)
+ if (connectionNames.empty())
{
- return; // no drives = no failures
+ BMCWEB_LOG_ERROR("Got 0 Connection names");
+ continue;
}
- matchAndFillDrive(asyncResp, chassisId, driveName, resp);
- });
- break;
- }
- });
+
+ dbus::utility::getAssociationEndPoints(
+ path + "/drive",
+ [asyncResp, chassisId,
+ driveName](const boost::system::error_code& ec3,
+ const dbus::utility::MapperEndPoints& resp) {
+ if (ec3)
+ {
+ return; // no drives = no failures
+ }
+ matchAndFillDrive(asyncResp, chassisId, driveName,
+ resp);
+ });
+ break;
+ }
+ });
}
/**
@@ -1031,24 +1034,25 @@ inline void populateStorageController(
BMCWEB_REDFISH_SYSTEM_URI_NAME, controllerId);
asyncResp->res.jsonValue["Name"] = controllerId;
asyncResp->res.jsonValue["Id"] = controllerId;
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
sdbusplus::asio::getProperty<bool>(
*crow::connections::systemBus, connectionName, path,
"xyz.openbmc_project.Inventory.Item", "Present",
[asyncResp](const boost::system::error_code& ec, bool isPresent) {
- // this interface isn't necessary, only check it
- // if we get a good return
- if (ec)
- {
- BMCWEB_LOG_DEBUG("Failed to get Present property");
- return;
- }
- if (!isPresent)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- }
- });
+ // this interface isn't necessary, only check it
+ // if we get a good return
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("Failed to get Present property");
+ return;
+ }
+ if (!isPresent)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ }
+ });
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, connectionName, path,
@@ -1057,8 +1061,8 @@ inline void populateStorageController(
const std::vector<
std::pair<std::string, dbus::utility::DbusVariantType>>&
propertiesList) {
- getStorageControllerAsset(asyncResp, ec, propertiesList);
- });
+ getStorageControllerAsset(asyncResp, ec, propertiesList);
+ });
}
inline void getStorageControllerHandler(
@@ -1166,8 +1170,8 @@ inline void handleSystemsStorageControllerCollectionGet(
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreePathsResponse&
controllerList) {
- populateStorageControllerCollection(asyncResp, ec, controllerList);
- });
+ populateStorageControllerCollection(asyncResp, ec, controllerList);
+ });
}
inline void handleSystemsStorageControllerGet(
@@ -1194,8 +1198,8 @@ inline void handleSystemsStorageControllerGet(
[asyncResp,
controllerId](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- getStorageControllerHandler(asyncResp, controllerId, ec, subtree);
- });
+ getStorageControllerHandler(asyncResp, controllerId, ec, subtree);
+ });
}
inline void requestRoutesStorageControllerCollection(App& app)
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 5d7dba1c36..d9a8d17455 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -20,7 +20,9 @@
#include "app.hpp"
#include "dbus_singleton.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/action_info.hpp"
#include "generated/enums/computer_system.hpp"
+#include "generated/enums/open_bmc_computer_system.hpp"
#include "generated/enums/resource.hpp"
#include "hypervisor_system.hpp"
#include "led.hpp"
@@ -65,9 +67,8 @@ const static std::array<std::pair<std::string_view, std::string_view>, 2>
*
* @return None.
*/
-inline void
- updateDimmProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- bool isDimmFunctional)
+inline void updateDimmProperties(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isDimmFunctional)
{
BMCWEB_LOG_DEBUG("Dimm Functional: {}", isDimmFunctional);
@@ -124,9 +125,8 @@ inline void modifyCpuFunctionalState(
*
* @return None.
*/
-inline void
- modifyCpuPresenceState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- bool isCpuPresent)
+inline void modifyCpuPresenceState(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, bool isCpuPresent)
{
BMCWEB_LOG_DEBUG("Cpu Present: {}", isCpuPresent);
@@ -216,14 +216,14 @@ inline void
[asyncResp, service,
path](const boost::system::error_code& ec2,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec2)
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
- messages::internalError(asyncResp->res);
- return;
- }
- getProcessorProperties(asyncResp, properties);
- });
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ getProcessorProperties(asyncResp, properties);
+ });
}
/*
@@ -295,14 +295,14 @@ inline void
[asyncResp, service,
path](const boost::system::error_code& ec2,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec2)
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
- messages::internalError(asyncResp->res);
- return;
- }
- processMemoryProperties(asyncResp, properties);
- });
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ processMemoryProperties(asyncResp, properties);
+ });
}
inline void afterGetUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -403,10 +403,9 @@ inline void
"BiosVersion", false);
}
-inline void
- afterGetAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const boost::system::error_code& ec,
- const std::string& value)
+inline void afterGetAssetTag(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::system::error_code& ec, const std::string& value)
{
if (ec)
{
@@ -473,8 +472,8 @@ inline void afterSystemGetSubTree(
[asyncResp](const boost::system::error_code& ec3,
const dbus::utility::DBusPropertiesMap&
properties) {
- afterGetUUID(asyncResp, ec3, properties);
- });
+ afterGetUUID(asyncResp, ec3, properties);
+ });
}
else if (interfaceName ==
"xyz.openbmc_project.Inventory.Item.System")
@@ -485,8 +484,8 @@ inline void afterSystemGetSubTree(
[asyncResp](const boost::system::error_code& ec3,
const dbus::utility::DBusPropertiesMap&
properties) {
- afterGetInventory(asyncResp, ec3, properties);
- });
+ afterGetInventory(asyncResp, ec3, properties);
+ });
sdbusplus::asio::getProperty<std::string>(
*crow::connections::systemBus, connection.first, path,
@@ -539,58 +538,71 @@ inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
"CurrentHostState",
[asyncResp](const boost::system::error_code& ec,
const std::string& hostState) {
- if (ec)
- {
- if (ec == boost::system::errc::host_unreachable)
+ if (ec)
{
- // Service not available, no error, just don't return
- // host state info
- BMCWEB_LOG_DEBUG("Service not available {}", ec);
+ if (ec == boost::system::errc::host_unreachable)
+ {
+ // Service not available, no error, just don't return
+ // host state info
+ BMCWEB_LOG_DEBUG("Service not available {}", ec);
+ return;
+ }
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG("Host state: {}", hostState);
- // Verify Host State
- if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- }
- else if (hostState ==
- "xyz.openbmc_project.State.Host.HostState.Quiesced")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "Quiesced";
- }
- else if (hostState ==
- "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
- {
- asyncResp->res.jsonValue["PowerState"] = "On";
- asyncResp->res.jsonValue["Status"]["State"] = "InTest";
- }
- else if (
- hostState ==
- "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
- {
- asyncResp->res.jsonValue["PowerState"] = "PoweringOn";
- asyncResp->res.jsonValue["Status"]["State"] = "Starting";
- }
- else if (hostState ==
- "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
- {
- asyncResp->res.jsonValue["PowerState"] = "PoweringOff";
- asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
- }
- else
- {
- asyncResp->res.jsonValue["PowerState"] = "Off";
- asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
- }
- });
+ BMCWEB_LOG_DEBUG("Host state: {}", hostState);
+ // Verify Host State
+ if (hostState == "xyz.openbmc_project.State.Host.HostState.Running")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+ }
+ else if (hostState ==
+ "xyz.openbmc_project.State.Host.HostState.Quiesced")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Quiesced;
+ }
+ else if (hostState ==
+ "xyz.openbmc_project.State.Host.HostState.DiagnosticMode")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::On;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::InTest;
+ }
+ else if (
+ hostState ==
+ "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::PoweringOn;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Starting;
+ }
+ else if (
+ hostState ==
+ "xyz.openbmc_project.State.Host.HostState.TransitioningToOff")
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::PoweringOff;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Disabled;
+ }
+ else
+ {
+ asyncResp->res.jsonValue["PowerState"] =
+ resource::PowerState::Off;
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Disabled;
+ }
+ });
}
/**
@@ -763,10 +775,9 @@ inline std::string dbusToRfBootProgress(const std::string& dbusBootProgress)
*
* @return Integer error code.
*/
-inline int
- assignBootParameters(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& rfSource, std::string& bootSource,
- std::string& bootMode)
+inline int assignBootParameters(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& rfSource, std::string& bootSource, std::string& bootMode)
{
bootSource = "xyz.openbmc_project.Control.Boot.Source.Sources.Default";
bootMode = "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
@@ -828,18 +839,18 @@ inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
"xyz.openbmc_project.State.Boot.Progress", "BootProgress",
[asyncResp](const boost::system::error_code& ec,
const std::string& bootProgressStr) {
- if (ec)
- {
- // BootProgress is an optional object so just do nothing if
- // not found
- return;
- }
+ if (ec)
+ {
+ // BootProgress is an optional object so just do nothing if
+ // not found
+ return;
+ }
- BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
+ BMCWEB_LOG_DEBUG("Boot Progress: {}", bootProgressStr);
- asyncResp->res.jsonValue["BootProgress"]["LastState"] =
- dbusToRfBootProgress(bootProgressStr);
- });
+ asyncResp->res.jsonValue["BootProgress"]["LastState"] =
+ dbusToRfBootProgress(bootProgressStr);
+ });
}
/**
@@ -858,22 +869,22 @@ inline void getBootProgressLastStateTime(
"xyz.openbmc_project.State.Boot.Progress", "BootProgressLastUpdate",
[asyncResp](const boost::system::error_code& ec,
const uint64_t lastStateTime) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
+ return;
+ }
- // BootProgressLastUpdate is the last time the BootProgress property
- // was updated. The time is the Epoch time, number of microseconds
- // since 1 Jan 1970 00::00::00 UTC."
- // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
- // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
+ // BootProgressLastUpdate is the last time the BootProgress property
+ // was updated. The time is the Epoch time, number of microseconds
+ // since 1 Jan 1970 00::00::00 UTC."
+ // https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/
+ // yaml/xyz/openbmc_project/State/Boot/Progress.interface.yaml#L11
- // Convert to ISO 8601 standard
- asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
- redfish::time_utils::getDateTimeUintUs(lastStateTime);
- });
+ // Convert to ISO 8601 standard
+ asyncResp->res.jsonValue["BootProgress"]["LastStateTime"] =
+ redfish::time_utils::getDateTimeUintUs(lastStateTime);
+ });
}
/**
@@ -893,28 +904,28 @@ inline void
"xyz.openbmc_project.Control.Boot.Type", "BootType",
[asyncResp](const boost::system::error_code& ec,
const std::string& bootType) {
- if (ec)
- {
- // not an error, don't have to have the interface
- return;
- }
+ if (ec)
+ {
+ // not an error, don't have to have the interface
+ return;
+ }
- BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
+ BMCWEB_LOG_DEBUG("Boot type: {}", bootType);
- asyncResp->res
- .jsonValue["Boot"]
- ["BootSourceOverrideMode@Redfish.AllowableValues"] =
- nlohmann::json::array_t({"Legacy", "UEFI"});
+ asyncResp->res
+ .jsonValue["Boot"]
+ ["BootSourceOverrideMode@Redfish.AllowableValues"] =
+ nlohmann::json::array_t({"Legacy", "UEFI"});
- auto rfType = dbusToRfBootType(bootType);
- if (rfType.empty())
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ auto rfType = dbusToRfBootType(bootType);
+ if (rfType.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
- });
+ asyncResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType;
+ });
}
/**
@@ -934,39 +945,39 @@ inline void
"xyz.openbmc_project.Control.Boot.Mode", "BootMode",
[asyncResp](const boost::system::error_code& ec,
const std::string& bootModeStr) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
-
- nlohmann::json::array_t allowed;
- allowed.emplace_back("None");
- allowed.emplace_back("Pxe");
- allowed.emplace_back("Hdd");
- allowed.emplace_back("Cd");
- allowed.emplace_back("Diags");
- allowed.emplace_back("BiosSetup");
- allowed.emplace_back("Usb");
-
- asyncResp->res
- .jsonValue["Boot"]
- ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
- std::move(allowed);
- if (bootModeStr !=
- "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
- {
- auto rfMode = dbusToRfBootMode(bootModeStr);
- if (!rfMode.empty())
+ BMCWEB_LOG_DEBUG("Boot mode: {}", bootModeStr);
+
+ nlohmann::json::array_t allowed;
+ allowed.emplace_back("None");
+ allowed.emplace_back("Pxe");
+ allowed.emplace_back("Hdd");
+ allowed.emplace_back("Cd");
+ allowed.emplace_back("Diags");
+ allowed.emplace_back("BiosSetup");
+ allowed.emplace_back("Usb");
+
+ asyncResp->res
+ .jsonValue["Boot"]
+ ["BootSourceOverrideTarget@Redfish.AllowableValues"] =
+ std::move(allowed);
+ if (bootModeStr !=
+ "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular")
{
- asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
- rfMode;
+ auto rfMode = dbusToRfBootMode(bootModeStr);
+ if (!rfMode.empty())
+ {
+ asyncResp->res
+ .jsonValue["Boot"]["BootSourceOverrideTarget"] = rfMode;
+ }
}
- }
- });
+ });
}
/**
@@ -986,30 +997,30 @@ inline void
"xyz.openbmc_project.Control.Boot.Source", "BootSource",
[asyncResp](const boost::system::error_code& ec,
const std::string& bootSourceStr) {
- if (ec)
- {
- if (ec.value() == boost::asio::error::host_unreachable)
+ if (ec)
{
+ if (ec.value() == boost::asio::error::host_unreachable)
+ {
+ return;
+ }
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
+ BMCWEB_LOG_DEBUG("Boot source: {}", bootSourceStr);
- auto rfSource = dbusToRfBootSource(bootSourceStr);
- if (!rfSource.empty())
- {
- asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
- rfSource;
- }
+ auto rfSource = dbusToRfBootSource(bootSourceStr);
+ if (!rfSource.empty())
+ {
+ asyncResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] =
+ rfSource;
+ }
- // Get BootMode as BootSourceOverrideTarget is constructed
- // from both BootSource and BootMode
- getBootOverrideMode(asyncResp);
- });
+ // Get BootMode as BootSourceOverrideTarget is constructed
+ // from both BootSource and BootMode
+ getBootOverrideMode(asyncResp);
+ });
}
/**
@@ -1040,24 +1051,24 @@ inline void processBootOverrideEnable(
"/xyz/openbmc_project/control/host0/boot/one_time",
"xyz.openbmc_project.Object.Enable", "Enabled",
[asyncResp](const boost::system::error_code& ec, bool oneTimeSetting) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (oneTimeSetting)
- {
- asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
- "Once";
- }
- else
- {
- asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
- "Continuous";
- }
- });
+ if (oneTimeSetting)
+ {
+ asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
+ "Once";
+ }
+ else
+ {
+ asyncResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] =
+ "Continuous";
+ }
+ });
}
/**
@@ -1077,19 +1088,19 @@ inline void
"xyz.openbmc_project.Object.Enable", "Enabled",
[asyncResp](const boost::system::error_code& ec,
const bool bootOverrideEnable) {
- if (ec)
- {
- if (ec.value() == boost::asio::error::host_unreachable)
+ if (ec)
{
+ if (ec.value() == boost::asio::error::host_unreachable)
+ {
+ return;
+ }
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- processBootOverrideEnable(asyncResp, bootOverrideEnable);
- });
+ processBootOverrideEnable(asyncResp, bootOverrideEnable);
+ });
}
/**
@@ -1132,20 +1143,20 @@ inline void
"xyz.openbmc_project.State.Chassis", "LastStateChangeTime",
[asyncResp](const boost::system::error_code& ec,
uint64_t lastResetTime) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("D-BUS response error {}", ec);
+ return;
+ }
- // LastStateChangeTime is epoch time, in milliseconds
- // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
- uint64_t lastResetTimeStamp = lastResetTime / 1000;
+ // LastStateChangeTime is epoch time, in milliseconds
+ // https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
+ uint64_t lastResetTimeStamp = lastResetTime / 1000;
- // Convert to ISO 8601 standard
- asyncResp->res.jsonValue["LastResetTime"] =
- redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
- });
+ // Convert to ISO 8601 standard
+ asyncResp->res.jsonValue["LastResetTime"] =
+ redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
+ });
}
/**
@@ -1172,42 +1183,42 @@ inline void getAutomaticRebootAttempts(
[asyncResp{asyncResp}](
const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- const uint32_t* attemptsLeft = nullptr;
- const uint32_t* retryAttempts = nullptr;
+ const uint32_t* attemptsLeft = nullptr;
+ const uint32_t* retryAttempts = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList, "AttemptsLeft",
- attemptsLeft, "RetryAttempts", retryAttempts);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList,
+ "AttemptsLeft", attemptsLeft, "RetryAttempts", retryAttempts);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (attemptsLeft != nullptr)
- {
- asyncResp->res
- .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
- *attemptsLeft;
- }
+ if (attemptsLeft != nullptr)
+ {
+ asyncResp->res
+ .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] =
+ *attemptsLeft;
+ }
- if (retryAttempts != nullptr)
- {
- asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
- *retryAttempts;
- }
- });
+ if (retryAttempts != nullptr)
+ {
+ asyncResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] =
+ *retryAttempts;
+ }
+ });
}
/**
@@ -1228,39 +1239,40 @@ inline void
"xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot",
[asyncResp](const boost::system::error_code& ec,
bool autoRebootEnabled) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
-
- BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
- if (autoRebootEnabled)
- {
- asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
- "RetryAttempts";
- }
- else
- {
- asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
- "Disabled";
- }
- getAutomaticRebootAttempts(asyncResp);
- // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
- // and RetryAttempts. OpenBMC only supports Disabled and
- // RetryAttempts.
- nlohmann::json::array_t allowed;
- allowed.emplace_back("Disabled");
- allowed.emplace_back("RetryAttempts");
- asyncResp->res
- .jsonValue["Boot"]["AutomaticRetryConfig@Redfish.AllowableValues"] =
- std::move(allowed);
- });
+ BMCWEB_LOG_DEBUG("Auto Reboot: {}", autoRebootEnabled);
+ if (autoRebootEnabled)
+ {
+ asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
+ "RetryAttempts";
+ }
+ else
+ {
+ asyncResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] =
+ "Disabled";
+ }
+ getAutomaticRebootAttempts(asyncResp);
+
+ // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways,
+ // and RetryAttempts. OpenBMC only supports Disabled and
+ // RetryAttempts.
+ nlohmann::json::array_t allowed;
+ allowed.emplace_back("Disabled");
+ allowed.emplace_back("RetryAttempts");
+ asyncResp->res
+ .jsonValue["Boot"]
+ ["AutomaticRetryConfig@Redfish.AllowableValues"] =
+ std::move(allowed);
+ });
}
/**
@@ -1327,21 +1339,21 @@ inline void
"xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy",
[asyncResp](const boost::system::error_code& ec,
const std::string& policy) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- return;
- }
- computer_system::PowerRestorePolicyTypes restore =
- redfishPowerRestorePolicyFromDbus(policy);
- if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ return;
+ }
+ computer_system::PowerRestorePolicyTypes restore =
+ redfishPowerRestorePolicyFromDbus(policy);
+ if (restore == computer_system::PowerRestorePolicyTypes::Invalid)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
- });
+ asyncResp->res.jsonValue["PowerRestorePolicy"] = restore;
+ });
}
/**
@@ -1361,25 +1373,27 @@ inline void
"/xyz/openbmc_project/logging/settings",
"xyz.openbmc_project.Logging.Settings", "QuiesceOnHwError",
[asyncResp](const boost::system::error_code& ec, bool value) {
- if (ec)
- {
- if (ec.value() != EBADR)
+ if (ec)
{
- BMCWEB_LOG_ERROR("DBUS response error {}", ec);
- messages::internalError(asyncResp->res);
+ if (ec.value() != EBADR)
+ {
+ BMCWEB_LOG_ERROR("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ }
+ return;
}
- return;
- }
- if (value)
- {
- asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "AnyFault";
- }
- else
- {
- asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] = "Never";
- }
- });
+ if (value)
+ {
+ asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
+ computer_system::StopBootOnFault::AnyFault;
+ }
+ else
+ {
+ asyncResp->res.jsonValue["Boot"]["StopBootOnFault"] =
+ computer_system::StopBootOnFault::Never;
+ }
+ });
}
/**
@@ -1400,72 +1414,72 @@ inline void getTrustedModuleRequiredToBoot(
"/", 0, interfaces,
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error on TPM.Policy GetSubTree{}",
- ec);
- // This is an optional D-Bus object so just return if
- // error occurs
- return;
- }
- if (subtree.empty())
- {
- // As noted above, this is an optional interface so just return
- // if there is no instance found
- return;
- }
-
- /* When there is more than one TPMEnable object... */
- if (subtree.size() > 1)
- {
- BMCWEB_LOG_DEBUG(
- "DBUS response has more than 1 TPM Enable object:{}",
- subtree.size());
- // Throw an internal Error and return
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Make sure the Dbus response map has a service and objectPath
- // field
- if (subtree[0].first.empty() || subtree[0].second.size() != 1)
- {
- BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
-
- const std::string& path = subtree[0].first;
- const std::string& serv = subtree[0].second.begin()->first;
-
- // Valid TPM Enable object found, now reading the current value
- sdbusplus::asio::getProperty<bool>(
- *crow::connections::systemBus, serv, path,
- "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
- [asyncResp](const boost::system::error_code& ec2,
- bool tpmRequired) {
- if (ec2)
+ if (ec)
{
- BMCWEB_LOG_ERROR("D-BUS response error on TPM.Policy Get{}",
- ec2);
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG(
+ "DBUS response error on TPM.Policy GetSubTree{}", ec);
+ // This is an optional D-Bus object so just return if
+ // error occurs
+ return;
+ }
+ if (subtree.empty())
+ {
+ // As noted above, this is an optional interface so just return
+ // if there is no instance found
return;
}
- if (tpmRequired)
+ /* When there is more than one TPMEnable object... */
+ if (subtree.size() > 1)
{
- asyncResp->res
- .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
- "Required";
+ BMCWEB_LOG_DEBUG(
+ "DBUS response has more than 1 TPM Enable object:{}",
+ subtree.size());
+ // Throw an internal Error and return
+ messages::internalError(asyncResp->res);
+ return;
}
- else
+
+ // Make sure the Dbus response map has a service and objectPath
+ // field
+ if (subtree[0].first.empty() || subtree[0].second.size() != 1)
{
- asyncResp->res
- .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
- "Disabled";
+ BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
}
+
+ const std::string& path = subtree[0].first;
+ const std::string& serv = subtree[0].second.begin()->first;
+
+ // Valid TPM Enable object found, now reading the current value
+ sdbusplus::asio::getProperty<bool>(
+ *crow::connections::systemBus, serv, path,
+ "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable",
+ [asyncResp](const boost::system::error_code& ec2,
+ bool tpmRequired) {
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "D-BUS response error on TPM.Policy Get{}", ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (tpmRequired)
+ {
+ asyncResp->res
+ .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
+ "Required";
+ }
+ else
+ {
+ asyncResp->res
+ .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] =
+ "Disabled";
+ }
+ });
});
- });
}
/**
@@ -1488,55 +1502,56 @@ inline void setTrustedModuleRequiredToBoot(
[asyncResp,
tpmRequired](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error on TPM.Policy GetSubTree{}",
- ec);
- messages::internalError(asyncResp->res);
- return;
- }
- if (subtree.empty())
- {
- messages::propertyValueNotInList(asyncResp->res, "ComputerSystem",
- "TrustedModuleRequiredToBoot");
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBUS response error on TPM.Policy GetSubTree{}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (subtree.empty())
+ {
+ messages::propertyValueNotInList(asyncResp->res,
+ "ComputerSystem",
+ "TrustedModuleRequiredToBoot");
+ return;
+ }
- /* When there is more than one TPMEnable object... */
- if (subtree.size() > 1)
- {
- BMCWEB_LOG_DEBUG(
- "DBUS response has more than 1 TPM Enable object:{}",
- subtree.size());
- // Throw an internal Error and return
- messages::internalError(asyncResp->res);
- return;
- }
+ /* When there is more than one TPMEnable object... */
+ if (subtree.size() > 1)
+ {
+ BMCWEB_LOG_DEBUG(
+ "DBUS response has more than 1 TPM Enable object:{}",
+ subtree.size());
+ // Throw an internal Error and return
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Make sure the Dbus response map has a service and objectPath
- // field
- if (subtree[0].first.empty() || subtree[0].second.size() != 1)
- {
- BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ // Make sure the Dbus response map has a service and objectPath
+ // field
+ if (subtree[0].first.empty() || subtree[0].second.size() != 1)
+ {
+ BMCWEB_LOG_DEBUG("TPM.Policy mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const std::string& path = subtree[0].first;
- const std::string& serv = subtree[0].second.begin()->first;
+ const std::string& path = subtree[0].first;
+ const std::string& serv = subtree[0].second.begin()->first;
- if (serv.empty())
- {
- BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (serv.empty())
+ {
+ BMCWEB_LOG_DEBUG("TPM.Policy service mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Valid TPM Enable object found, now setting the value
- setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
- path, "xyz.openbmc_project.Control.TPM.Policy",
- "TPMEnable", tpmRequired);
- });
+ // Valid TPM Enable object found, now setting the value
+ setDbusProperty(asyncResp, "Boot/TrustedModuleRequiredToBoot", serv,
+ path, "xyz.openbmc_project.Control.TPM.Policy",
+ "TPMEnable", tpmRequired);
+ });
}
/**
@@ -1755,47 +1770,47 @@ inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
[asyncResp,
assetTag](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- if (subtree.empty())
- {
- BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
- messages::internalError(asyncResp->res);
- return;
- }
- // Assume only 1 system D-Bus object
- // Throw an error if there is more than 1
- if (subtree.size() > 1)
- {
- BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
- messages::internalError(asyncResp->res);
- return;
- }
- if (subtree[0].first.empty() || subtree[0].second.size() != 1)
- {
- BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("D-Bus response error on GetSubTree {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (subtree.empty())
+ {
+ BMCWEB_LOG_DEBUG("Can't find system D-Bus object!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // Assume only 1 system D-Bus object
+ // Throw an error if there is more than 1
+ if (subtree.size() > 1)
+ {
+ BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus object!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (subtree[0].first.empty() || subtree[0].second.size() != 1)
+ {
+ BMCWEB_LOG_DEBUG("Asset Tag Set mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const std::string& path = subtree[0].first;
- const std::string& service = subtree[0].second.begin()->first;
+ const std::string& path = subtree[0].first;
+ const std::string& service = subtree[0].second.begin()->first;
- if (service.empty())
- {
- BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (service.empty())
+ {
+ BMCWEB_LOG_DEBUG("Asset Tag Set service mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- setDbusProperty(asyncResp, "AssetTag", service, path,
- "xyz.openbmc_project.Inventory.Decorator.AssetTag",
- "AssetTag", assetTag);
- });
+ setDbusProperty(asyncResp, "AssetTag", service, path,
+ "xyz.openbmc_project.Inventory.Decorator.AssetTag",
+ "AssetTag", assetTag);
+ });
}
/**
@@ -1962,56 +1977,62 @@ inline void
"/xyz/openbmc_project/pfr", "xyz.openbmc_project.PFR.Attributes",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- nlohmann::json& oemPFR =
- asyncResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
- asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
- "#OemComputerSystem.OpenBmc";
- oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning";
+ nlohmann::json& oemPFR =
+ asyncResp->res
+ .jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"];
+ asyncResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] =
+ "#OpenBMCComputerSystem.v1_0_0.OpenBmc";
+ oemPFR["@odata.type"] =
+ "#OpenBMCComputerSystem.FirmwareProvisioning";
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- // not an error, don't have to have the interface
- oemPFR["ProvisioningStatus"] = "NotProvisioned";
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ // not an error, don't have to have the interface
+ oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
+ FirmwareProvisioningStatus::NotProvisioned;
+ return;
+ }
- const bool* provState = nullptr;
- const bool* lockState = nullptr;
+ const bool* provState = nullptr;
+ const bool* lockState = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList, "UfmProvisioned",
- provState, "UfmLocked", lockState);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList,
+ "UfmProvisioned", provState, "UfmLocked", lockState);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if ((provState == nullptr) || (lockState == nullptr))
- {
- BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
- messages::internalError(asyncResp->res);
- return;
- }
+ if ((provState == nullptr) || (lockState == nullptr))
+ {
+ BMCWEB_LOG_DEBUG("Unable to get PFR attributes.");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (*provState)
- {
- if (*lockState)
+ if (*provState)
{
- oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked";
+ if (*lockState)
+ {
+ oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
+ FirmwareProvisioningStatus::ProvisionedAndLocked;
+ }
+ else
+ {
+ oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
+ FirmwareProvisioningStatus::ProvisionedButNotLocked;
+ }
}
else
{
- oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked";
+ oemPFR["ProvisioningStatus"] = open_bmc_computer_system::
+ FirmwareProvisioningStatus::NotProvisioned;
}
- }
- else
- {
- oemPFR["ProvisioningStatus"] = "NotProvisioned";
- }
- });
+ });
}
/**
@@ -2139,54 +2160,55 @@ inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
"/", 0, interfaces,
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error on Power.Mode GetSubTree {}",
- ec);
- // This is an optional D-Bus object so just return if
- // error occurs
- return;
- }
- if (subtree.empty())
- {
- // As noted above, this is an optional interface so just return
- // if there is no instance found
- return;
- }
- if (subtree.size() > 1)
- {
- // More then one PowerMode object is not supported and is an
- // error
- BMCWEB_LOG_DEBUG(
- "Found more than 1 system D-Bus Power.Mode objects: {}",
- subtree.size());
- messages::internalError(asyncResp->res);
- return;
- }
- if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
- {
- BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& path = subtree[0].first;
- const std::string& service = subtree[0].second.begin()->first;
- if (service.empty())
- {
- BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG(
+ "DBUS response error on Power.Mode GetSubTree {}", ec);
+ // This is an optional D-Bus object so just return if
+ // error occurs
+ return;
+ }
+ if (subtree.empty())
+ {
+ // As noted above, this is an optional interface so just return
+ // if there is no instance found
+ return;
+ }
+ if (subtree.size() > 1)
+ {
+ // More then one PowerMode object is not supported and is an
+ // error
+ BMCWEB_LOG_DEBUG(
+ "Found more than 1 system D-Bus Power.Mode objects: {}",
+ subtree.size());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
+ {
+ BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string& path = subtree[0].first;
+ const std::string& service = subtree[0].second.begin()->first;
+ if (service.empty())
+ {
+ BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Valid Power Mode object found, now read the mode properties
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, service, path,
- "xyz.openbmc_project.Control.Power.Mode",
- [asyncResp](const boost::system::error_code& ec2,
- const dbus::utility::DBusPropertiesMap& properties) {
- afterGetPowerMode(asyncResp, ec2, properties);
+ // Valid Power Mode object found, now read the mode properties
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, service, path,
+ "xyz.openbmc_project.Control.Power.Mode",
+ [asyncResp](
+ const boost::system::error_code& ec2,
+ const dbus::utility::DBusPropertiesMap& properties) {
+ afterGetPowerMode(asyncResp, ec2, properties);
+ });
});
- });
}
/**
@@ -2268,53 +2290,53 @@ inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
[asyncResp,
powerMode](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("DBUS response error on Power.Mode GetSubTree {}",
- ec);
- // This is an optional D-Bus object, but user attempted to patch
- messages::internalError(asyncResp->res);
- return;
- }
- if (subtree.empty())
- {
- // This is an optional D-Bus object, but user attempted to patch
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- "PowerMode");
- return;
- }
- if (subtree.size() > 1)
- {
- // More then one PowerMode object is not supported and is an
- // error
- BMCWEB_LOG_DEBUG(
- "Found more than 1 system D-Bus Power.Mode objects: {}",
- subtree.size());
- messages::internalError(asyncResp->res);
- return;
- }
- if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
- {
- BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& path = subtree[0].first;
- const std::string& service = subtree[0].second.begin()->first;
- if (service.empty())
- {
- BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBUS response error on Power.Mode GetSubTree {}", ec);
+ // This is an optional D-Bus object, but user attempted to patch
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (subtree.empty())
+ {
+ // This is an optional D-Bus object, but user attempted to patch
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ "PowerMode");
+ return;
+ }
+ if (subtree.size() > 1)
+ {
+ // More then one PowerMode object is not supported and is an
+ // error
+ BMCWEB_LOG_DEBUG(
+ "Found more than 1 system D-Bus Power.Mode objects: {}",
+ subtree.size());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
+ {
+ BMCWEB_LOG_DEBUG("Power.Mode mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string& path = subtree[0].first;
+ const std::string& service = subtree[0].second.begin()->first;
+ if (service.empty())
+ {
+ BMCWEB_LOG_DEBUG("Power.Mode service mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
+ BMCWEB_LOG_DEBUG("Setting power mode({}) -> {}", powerMode, path);
- // Set the Power Mode property
- setDbusProperty(asyncResp, "PowerMode", service, path,
- "xyz.openbmc_project.Control.Power.Mode", "PowerMode",
- powerMode);
- });
+ // Set the Power Mode property
+ setDbusProperty(asyncResp, "PowerMode", service, path,
+ "xyz.openbmc_project.Control.Power.Mode",
+ "PowerMode", powerMode);
+ });
}
/**
@@ -2395,50 +2417,50 @@ inline void
"xyz.openbmc_project.State.Watchdog",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& properties) {
- if (ec)
- {
- // watchdog service is stopped
- BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
- return;
- }
+ if (ec)
+ {
+ // watchdog service is stopped
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ return;
+ }
- BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
+ BMCWEB_LOG_DEBUG("Got {} wdt prop.", properties.size());
- nlohmann::json& hostWatchdogTimer =
- asyncResp->res.jsonValue["HostWatchdogTimer"];
+ nlohmann::json& hostWatchdogTimer =
+ asyncResp->res.jsonValue["HostWatchdogTimer"];
- // watchdog service is running/enabled
- hostWatchdogTimer["Status"]["State"] = "Enabled";
+ // watchdog service is running/enabled
+ hostWatchdogTimer["Status"]["State"] = resource::State::Enabled;
- const bool* enabled = nullptr;
- const std::string* expireAction = nullptr;
+ const bool* enabled = nullptr;
+ const std::string* expireAction = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
- "ExpireAction", expireAction);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), properties, "Enabled",
+ enabled, "ExpireAction", expireAction);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (enabled != nullptr)
- {
- hostWatchdogTimer["FunctionEnabled"] = *enabled;
- }
-
- if (expireAction != nullptr)
- {
- std::string action = dbusToRfWatchdogAction(*expireAction);
- if (action.empty())
+ if (!success)
{
messages::internalError(asyncResp->res);
return;
}
- hostWatchdogTimer["TimeoutAction"] = action;
- }
- });
+
+ if (enabled != nullptr)
+ {
+ hostWatchdogTimer["FunctionEnabled"] = *enabled;
+ }
+
+ if (expireAction != nullptr)
+ {
+ std::string action = dbusToRfWatchdogAction(*expireAction);
+ if (action.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ hostWatchdogTimer["TimeoutAction"] = action;
+ }
+ });
}
/**
@@ -2574,67 +2596,69 @@ inline void
"/", 0, interfaces,
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR(
- "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
- ec);
- messages::internalError(asyncResp->res);
- return;
- }
- if (subtree.empty())
- {
- // This is an optional interface so just return
- // if there is no instance found
- BMCWEB_LOG_DEBUG("No instances found");
- return;
- }
- if (subtree.size() > 1)
- {
- // More then one PowerIdlePowerSaver object is not supported and
- // is an error
- BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
- "Power.IdlePowerSaver objects: {}",
- subtree.size());
- messages::internalError(asyncResp->res);
- return;
- }
- if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
- {
- BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& path = subtree[0].first;
- const std::string& service = subtree[0].second.begin()->first;
- if (service.empty())
- {
- BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Valid IdlePowerSaver object found, now read the current values
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, service, path,
- "xyz.openbmc_project.Control.Power.IdlePowerSaver",
- [asyncResp](const boost::system::error_code& ec2,
- const dbus::utility::DBusPropertiesMap& properties) {
- if (ec2)
+ if (ec)
{
BMCWEB_LOG_ERROR(
- "DBUS response error on IdlePowerSaver GetAll: {}", ec2);
+ "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
+ ec);
messages::internalError(asyncResp->res);
return;
}
-
- if (!parseIpsProperties(asyncResp, properties))
+ if (subtree.empty())
{
+ // This is an optional interface so just return
+ // if there is no instance found
+ BMCWEB_LOG_DEBUG("No instances found");
+ return;
+ }
+ if (subtree.size() > 1)
+ {
+ // More then one PowerIdlePowerSaver object is not supported and
+ // is an error
+ BMCWEB_LOG_DEBUG("Found more than 1 system D-Bus "
+ "Power.IdlePowerSaver objects: {}",
+ subtree.size());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
+ {
+ BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string& path = subtree[0].first;
+ const std::string& service = subtree[0].second.begin()->first;
+ if (service.empty())
+ {
+ BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
messages::internalError(asyncResp->res);
return;
}
+
+ // Valid IdlePowerSaver object found, now read the current values
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, service, path,
+ "xyz.openbmc_project.Control.Power.IdlePowerSaver",
+ [asyncResp](
+ const boost::system::error_code& ec2,
+ const dbus::utility::DBusPropertiesMap& properties) {
+ if (ec2)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBUS response error on IdlePowerSaver GetAll: {}",
+ ec2);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (!parseIpsProperties(asyncResp, properties))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ });
});
- });
BMCWEB_LOG_DEBUG("EXIT: Get idle power saver parameters");
}
@@ -2654,13 +2678,13 @@ inline void
*
* @return None.
*/
-inline void
- setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::optional<bool> ipsEnable,
- const std::optional<uint8_t> ipsEnterUtil,
- const std::optional<uint64_t> ipsEnterTime,
- const std::optional<uint8_t> ipsExitUtil,
- const std::optional<uint64_t> ipsExitTime)
+inline void setIdlePowerSaver(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::optional<bool> ipsEnable,
+ const std::optional<uint8_t> ipsEnterUtil,
+ const std::optional<uint64_t> ipsEnterTime,
+ const std::optional<uint8_t> ipsExitUtil,
+ const std::optional<uint64_t> ipsExitTime)
{
BMCWEB_LOG_DEBUG("Set idle power saver properties");
@@ -2672,88 +2696,90 @@ inline void
[asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil,
ipsExitTime](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- if (ec)
- {
- BMCWEB_LOG_ERROR(
- "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
- ec);
- messages::internalError(asyncResp->res);
- return;
- }
- if (subtree.empty())
- {
- // This is an optional D-Bus object, but user attempted to patch
- messages::resourceNotFound(asyncResp->res, "ComputerSystem",
- "IdlePowerSaver");
- return;
- }
- if (subtree.size() > 1)
- {
- // More then one PowerIdlePowerSaver object is not supported and
- // is an error
- BMCWEB_LOG_DEBUG(
- "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
- subtree.size());
- messages::internalError(asyncResp->res);
- return;
- }
- if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
- {
- BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
- const std::string& path = subtree[0].first;
- const std::string& service = subtree[0].second.begin()->first;
- if (service.empty())
- {
- BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR(
+ "DBUS response error on Power.IdlePowerSaver GetSubTree {}",
+ ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (subtree.empty())
+ {
+ // This is an optional D-Bus object, but user attempted to patch
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ "IdlePowerSaver");
+ return;
+ }
+ if (subtree.size() > 1)
+ {
+ // More then one PowerIdlePowerSaver object is not supported and
+ // is an error
+ BMCWEB_LOG_DEBUG(
+ "Found more than 1 system D-Bus Power.IdlePowerSaver objects: {}",
+ subtree.size());
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1))
+ {
+ BMCWEB_LOG_DEBUG("Power.IdlePowerSaver mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string& path = subtree[0].first;
+ const std::string& service = subtree[0].second.begin()->first;
+ if (service.empty())
+ {
+ BMCWEB_LOG_DEBUG("Power.IdlePowerSaver service mapper error!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- // Valid Power IdlePowerSaver object found, now set any values that
- // need to be updated
+ // Valid Power IdlePowerSaver object found, now set any values that
+ // need to be updated
- if (ipsEnable)
- {
- setDbusProperty(asyncResp, "IdlePowerSaver/Enabled", service, path,
- "xyz.openbmc_project.Control.Power.IdlePowerSaver",
- "Enabled", *ipsEnable);
- }
- if (ipsEnterUtil)
- {
- setDbusProperty(asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
- service, path,
- "xyz.openbmc_project.Control.Power.IdlePowerSaver",
- "EnterUtilizationPercent", *ipsEnterUtil);
- }
- if (ipsEnterTime)
- {
- // Convert from seconds into milliseconds for DBus
- const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
- setDbusProperty(asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds",
- service, path,
- "xyz.openbmc_project.Control.Power.IdlePowerSaver",
- "EnterDwellTime", timeMilliseconds);
- }
- if (ipsExitUtil)
- {
- setDbusProperty(asyncResp, "IdlePowerSaver/ExitUtilizationPercent",
- service, path,
- "xyz.openbmc_project.Control.Power.IdlePowerSaver",
- "ExitUtilizationPercent", *ipsExitUtil);
- }
- if (ipsExitTime)
- {
- // Convert from seconds into milliseconds for DBus
- const uint64_t timeMilliseconds = *ipsExitTime * 1000;
- setDbusProperty(asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds",
- service, path,
- "xyz.openbmc_project.Control.Power.IdlePowerSaver",
- "ExitDwellTime", timeMilliseconds);
- }
- });
+ if (ipsEnable)
+ {
+ setDbusProperty(
+ asyncResp, "IdlePowerSaver/Enabled", service, path,
+ "xyz.openbmc_project.Control.Power.IdlePowerSaver",
+ "Enabled", *ipsEnable);
+ }
+ if (ipsEnterUtil)
+ {
+ setDbusProperty(
+ asyncResp, "IdlePowerSaver/EnterUtilizationPercent",
+ service, path,
+ "xyz.openbmc_project.Control.Power.IdlePowerSaver",
+ "EnterUtilizationPercent", *ipsEnterUtil);
+ }
+ if (ipsEnterTime)
+ {
+ // Convert from seconds into milliseconds for DBus
+ const uint64_t timeMilliseconds = *ipsEnterTime * 1000;
+ setDbusProperty(
+ asyncResp, "IdlePowerSaver/EnterDwellTimeSeconds", service,
+ path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
+ "EnterDwellTime", timeMilliseconds);
+ }
+ if (ipsExitUtil)
+ {
+ setDbusProperty(
+ asyncResp, "IdlePowerSaver/ExitUtilizationPercent", service,
+ path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
+ "ExitUtilizationPercent", *ipsExitUtil);
+ }
+ if (ipsExitTime)
+ {
+ // Convert from seconds into milliseconds for DBus
+ const uint64_t timeMilliseconds = *ipsExitTime * 1000;
+ setDbusProperty(
+ asyncResp, "IdlePowerSaver/ExitDwellTimeSeconds", service,
+ path, "xyz.openbmc_project.Control.Power.IdlePowerSaver",
+ "ExitDwellTime", timeMilliseconds);
+ }
+ });
BMCWEB_LOG_DEBUG("EXIT: Set idle power saver parameters");
}
@@ -2801,35 +2827,16 @@ inline void handleComputerSystemCollectionGet(
system["@odata.id"] = boost::urls::format("/redfish/v1/Systems/{}",
BMCWEB_REDFISH_SYSTEM_URI_NAME);
ifaceArray.emplace_back(std::move(system));
- sdbusplus::asio::getProperty<std::string>(
- *crow::connections::systemBus, "xyz.openbmc_project.Settings",
- "/xyz/openbmc_project/network/hypervisor",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
- [asyncResp](const boost::system::error_code& ec2,
- const std::string& /*hostName*/) {
- if (ec2)
- {
- return;
- }
- auto val = asyncResp->res.jsonValue.find("Members@odata.count");
- if (val == asyncResp->res.jsonValue.end())
- {
- BMCWEB_LOG_CRITICAL("Count wasn't found??");
- return;
- }
- uint64_t* count = val->get_ptr<uint64_t*>();
- if (count == nullptr)
- {
- BMCWEB_LOG_CRITICAL("Count wasn't found??");
- return;
- }
- *count = *count + 1;
+
+ if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
+ {
BMCWEB_LOG_DEBUG("Hypervisor is available");
- nlohmann::json& ifaceArray2 = asyncResp->res.jsonValue["Members"];
+ asyncResp->res.jsonValue["Members@odata.count"] = 2;
+
nlohmann::json::object_t hypervisor;
hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor";
- ifaceArray2.emplace_back(std::move(hypervisor));
- });
+ ifaceArray.emplace_back(std::move(hypervisor));
+ }
}
/**
@@ -2845,14 +2852,14 @@ inline void doNMI(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- messages::success(asyncResp->res);
- },
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR(" Bad D-Bus request error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
serviceName, objectPath, interfaceName, method);
}
@@ -2865,6 +2872,16 @@ inline void handleComputerSystemResetActionPost(
{
return;
}
+
+ if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
+ {
+ if (systemName == "hypervisor")
+ {
+ handleHypervisorSystemResetPost(req, asyncResp);
+ return;
+ }
+ }
+
if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
{
messages::resourceNotFound(asyncResp->res, "ComputerSystem",
@@ -3017,10 +3034,13 @@ inline void
return;
}
- if (systemName == "hypervisor")
+ if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
{
- handleHypervisorSystemGet(asyncResp);
- return;
+ if (systemName == "hypervisor")
+ {
+ handleHypervisorSystemGet(asyncResp);
+ return;
+ }
}
if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
@@ -3036,7 +3056,8 @@ inline void
"#ComputerSystem.v1_22_0.ComputerSystem";
asyncResp->res.jsonValue["Name"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_SYSTEM_URI_NAME;
- asyncResp->res.jsonValue["SystemType"] = "Physical";
+ asyncResp->res.jsonValue["SystemType"] =
+ computer_system::SystemType::Physical;
asyncResp->res.jsonValue["Description"] = "Computer System";
asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0;
asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] =
@@ -3073,8 +3094,8 @@ inline void
manager["@odata.id"] = boost::urls::format("/redfish/v1/Managers/{}",
BMCWEB_REDFISH_MANAGER_URI_NAME);
asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy);
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
// Fill in SerialConsole info
asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15;
@@ -3097,15 +3118,15 @@ inline void
nlohmann::json::array_t({"KVMIP"});
}
- getMainChassisId(asyncResp,
- [](const std::string& chassisId,
- const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
- nlohmann::json::array_t chassisArray;
- nlohmann::json& chassis = chassisArray.emplace_back();
- chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
- chassisId);
- aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
- });
+ getMainChassisId(
+ asyncResp, [](const std::string& chassisId,
+ const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
+ nlohmann::json::array_t chassisArray;
+ nlohmann::json& chassis = chassisArray.emplace_back();
+ chassis["@odata.id"] =
+ boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
+ aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
+ });
getSystemLocationIndicatorActive(asyncResp);
// TODO (Gunnar): Remove IndicatorLED after enough time has passed
@@ -3179,30 +3200,30 @@ inline void handleComputerSystemPatch(
std::optional<uint64_t> ipsExitTime;
// clang-format off
- if (!json_util::readJsonPatch(
- req, asyncResp->res,
- "IndicatorLED", indicatorLed,
- "LocationIndicatorActive", locationIndicatorActive,
- "AssetTag", assetTag,
- "PowerRestorePolicy", powerRestorePolicy,
- "PowerMode", powerMode,
- "HostWatchdogTimer/FunctionEnabled", wdtEnable,
- "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
- "Boot/BootSourceOverrideTarget", bootSource,
- "Boot/BootSourceOverrideMode", bootType,
- "Boot/BootSourceOverrideEnabled", bootEnable,
- "Boot/AutomaticRetryConfig", bootAutomaticRetry,
- "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
- "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
- "Boot/StopBootOnFault", stopBootOnFault,
- "IdlePowerSaver/Enabled", ipsEnable,
- "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
- "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
- "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
- "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
- {
- return;
- }
+ if (!json_util::readJsonPatch(
+ req, asyncResp->res,
+ "IndicatorLED", indicatorLed,
+ "LocationIndicatorActive", locationIndicatorActive,
+ "AssetTag", assetTag,
+ "PowerRestorePolicy", powerRestorePolicy,
+ "PowerMode", powerMode,
+ "HostWatchdogTimer/FunctionEnabled", wdtEnable,
+ "HostWatchdogTimer/TimeoutAction", wdtTimeOutAction,
+ "Boot/BootSourceOverrideTarget", bootSource,
+ "Boot/BootSourceOverrideMode", bootType,
+ "Boot/BootSourceOverrideEnabled", bootEnable,
+ "Boot/AutomaticRetryConfig", bootAutomaticRetry,
+ "Boot/AutomaticRetryAttempts", bootAutomaticRetryAttempts,
+ "Boot/TrustedModuleRequiredToBoot", bootTrustedModuleRequired,
+ "Boot/StopBootOnFault", stopBootOnFault,
+ "IdlePowerSaver/Enabled", ipsEnable,
+ "IdlePowerSaver/EnterUtilizationPercent", ipsEnterUtil,
+ "IdlePowerSaver/EnterDwellTimeSeconds", ipsEnterTime,
+ "IdlePowerSaver/ExitUtilizationPercent", ipsExitUtil,
+ "IdlePowerSaver/ExitDwellTimeSeconds", ipsExitTime))
+ {
+ return;
+ }
// clang-format on
asyncResp->res.result(boost::beast::http::status::no_content);
@@ -3373,7 +3394,7 @@ inline void afterGetAllowedHostTransitions(
nlohmann::json::object_t parameter;
parameter["Name"] = "ResetType";
parameter["Required"] = true;
- parameter["DataType"] = "String";
+ parameter["DataType"] = action_info::ParameterTypes::String;
parameter["AllowableValues"] = std::move(allowableValues);
nlohmann::json::array_t parameters;
parameters.emplace_back(std::move(parameter));
@@ -3397,10 +3418,13 @@ inline void handleSystemCollectionResetActionGet(
return;
}
- if (systemName == "hypervisor")
+ if constexpr (BMCWEB_HYPERVISOR_COMPUTER_SYSTEM)
{
- handleHypervisorResetActionGet(asyncResp);
- return;
+ if (systemName == "hypervisor")
+ {
+ handleHypervisorResetActionGet(asyncResp);
+ return;
+ }
}
if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
@@ -3428,8 +3452,9 @@ inline void handleSystemCollectionResetActionGet(
"AllowedHostTransitions",
[asyncResp](const boost::system::error_code& ec,
const std::vector<std::string>& allowedHostTransitions) {
- afterGetAllowedHostTransitions(asyncResp, ec, allowedHostTransitions);
- });
+ afterGetAllowedHostTransitions(asyncResp, ec,
+ allowedHostTransitions);
+ });
}
/**
* SystemResetActionInfo derived class for delivering Computer Systems
diff --git a/redfish-core/lib/systems_logservices_hostlogger.hpp b/redfish-core/lib/systems_logservices_hostlogger.hpp
new file mode 100644
index 0000000000..98be6f3ac2
--- /dev/null
+++ b/redfish-core/lib/systems_logservices_hostlogger.hpp
@@ -0,0 +1,241 @@
+#pragma once
+
+#include "app.hpp"
+#include "generated/enums/log_entry.hpp"
+#include "query.hpp"
+#include "registries/openbmc_message_registry.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/time_utils.hpp"
+
+#include <cstdint>
+#include <memory>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace redfish
+{
+
+inline void fillHostLoggerEntryJson(std::string_view logEntryID,
+ std::string_view msg,
+ nlohmann::json::object_t& logEntryJson)
+{
+ // Fill in the log entry with the gathered data.
+ logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+ logEntryJson["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, logEntryID);
+ logEntryJson["Name"] = "Host Logger Entry";
+ logEntryJson["Id"] = logEntryID;
+ logEntryJson["Message"] = msg;
+ logEntryJson["EntryType"] = log_entry::LogEntryType::Oem;
+ logEntryJson["Severity"] = log_entry::EventSeverity::OK;
+ logEntryJson["OemRecordFormat"] = "Host Logger Entry";
+}
+
+inline void handleSystemsLogServicesHostloggerGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/HostLogger",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "Host Logger Service";
+ asyncResp->res.jsonValue["Description"] = "Host Logger Service";
+ asyncResp->res.jsonValue["Id"] = "HostLogger";
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+}
+
+inline void handleSystemsLogServicesHostloggerEntriesGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ query_param::QueryCapabilities capabilities = {
+ .canDelegateTop = true,
+ .canDelegateSkip = true,
+ };
+ query_param::Query delegatedQuery;
+ if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
+ delegatedQuery, capabilities))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/HostLogger/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["Name"] = "HostLogger Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of HostLogger Entries";
+ nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
+ logEntryArray = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ std::vector<std::filesystem::path> hostLoggerFiles;
+ if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
+ {
+ BMCWEB_LOG_DEBUG("Failed to get host log file path");
+ return;
+ }
+ // If we weren't provided top and skip limits, use the defaults.
+ size_t skip = delegatedQuery.skip.value_or(0);
+ size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
+ size_t logCount = 0;
+ // This vector only store the entries we want to expose that
+ // control by skip and top.
+ std::vector<std::string> logEntries;
+ if (!getHostLoggerEntries(hostLoggerFiles, skip, top, logEntries, logCount))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ // If vector is empty, that means skip value larger than total
+ // log count
+ if (logEntries.empty())
+ {
+ asyncResp->res.jsonValue["Members@odata.count"] = logCount;
+ return;
+ }
+ if (!logEntries.empty())
+ {
+ for (size_t i = 0; i < logEntries.size(); i++)
+ {
+ nlohmann::json::object_t hostLogEntry;
+ fillHostLoggerEntryJson(std::to_string(skip + i), logEntries[i],
+ hostLogEntry);
+ logEntryArray.emplace_back(std::move(hostLogEntry));
+ }
+
+ asyncResp->res.jsonValue["Members@odata.count"] = logCount;
+ if (skip + top < logCount)
+ {
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ std::format(
+ "/redfish/v1/Systems/{}/LogServices/HostLogger/Entries?$skip=",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME) +
+ std::to_string(skip + top);
+ }
+ }
+}
+
+inline void handleSystemsLogServicesHostloggerEntriesEntryGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& param)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ std::string_view targetID = param;
+
+ uint64_t idInt = 0;
+
+ auto [ptr, ec] = std::from_chars(targetID.begin(), targetID.end(), idInt);
+ if (ec != std::errc{} || ptr != targetID.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", param);
+ return;
+ }
+
+ std::vector<std::filesystem::path> hostLoggerFiles;
+ if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles))
+ {
+ BMCWEB_LOG_DEBUG("Failed to get host log file path");
+ return;
+ }
+
+ size_t logCount = 0;
+ size_t top = 1;
+ std::vector<std::string> logEntries;
+ // We can get specific entry by skip and top. For example, if we
+ // want to get nth entry, we can set skip = n-1 and top = 1 to
+ // get that entry
+ if (!getHostLoggerEntries(hostLoggerFiles, idInt, top, logEntries,
+ logCount))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (!logEntries.empty())
+ {
+ nlohmann::json::object_t hostLogEntry;
+ fillHostLoggerEntryJson(targetID, logEntries[0], hostLogEntry);
+ asyncResp->res.jsonValue.update(hostLogEntry);
+ return;
+ }
+
+ // Requested ID was not found
+ messages::resourceNotFound(asyncResp->res, "LogEntry", param);
+}
+
+inline void requestRoutesSystemsLogServiceHostlogger(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/")
+ .privileges(redfish::privileges::getLogService)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesHostloggerGet, std::ref(app)));
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/")
+ .privileges(redfish::privileges::getLogEntryCollection)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesHostloggerEntriesGet, std::ref(app)));
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/<str>/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesHostloggerEntriesEntryGet, std::ref(app)));
+}
+
+} // namespace redfish
diff --git a/redfish-core/lib/systems_logservices_postcodes.hpp b/redfish-core/lib/systems_logservices_postcodes.hpp
new file mode 100644
index 0000000000..90782bde51
--- /dev/null
+++ b/redfish-core/lib/systems_logservices_postcodes.hpp
@@ -0,0 +1,615 @@
+#pragma once
+
+#include "app.hpp"
+#include "generated/enums/log_service.hpp"
+#include "query.hpp"
+#include "registries/openbmc_message_registry.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/time_utils.hpp"
+
+#include <cstdint>
+#include <memory>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace redfish
+{
+
+inline void handleSystemsLogServicesPostCodesGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/PostCodes",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
+ asyncResp->res.jsonValue["Name"] = "POST Code Log Service";
+ asyncResp->res.jsonValue["Description"] = "POST Code Log Service";
+ asyncResp->res.jsonValue["Id"] = "PostCodes";
+ asyncResp->res.jsonValue["OverWritePolicy"] =
+ log_service::OverWritePolicy::WrapsWhenFull;
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/PostCodes/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+
+ std::pair<std::string, std::string> redfishDateTimeOffset =
+ redfish::time_utils::getDateTimeOffsetNow();
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+ redfishDateTimeOffset.second;
+
+ asyncResp->res
+ .jsonValue["Actions"]["#LogService.ClearLog"]["target"] = std::format(
+ "/redfish/v1/Systems/{}/LogServices/PostCodes/Actions/LogService.ClearLog",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+}
+
+inline void handleSystemsLogServicesPostCodesPost(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ BMCWEB_LOG_DEBUG("Do delete all postcodes entries.");
+
+ // Make call to post-code service to request clear all
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ // TODO Handle for specific error code
+ BMCWEB_LOG_ERROR("doClearPostCodes resp_handler got error {}",
+ ec);
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ messages::success(asyncResp->res);
+ },
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
+}
+
+/**
+ * @brief Parse post code ID and get the current value and index value
+ * eg: postCodeID=B1-2, currentValue=1, index=2
+ *
+ * @param[in] postCodeID Post Code ID
+ * @param[out] currentValue Current value
+ * @param[out] index Index value
+ *
+ * @return bool true if the parsing is successful, false the parsing fails
+ */
+inline bool parsePostCode(std::string_view postCodeID, uint64_t& currentValue,
+ uint16_t& index)
+{
+ std::vector<std::string> split;
+ bmcweb::split(split, postCodeID, '-');
+ if (split.size() != 2)
+ {
+ return false;
+ }
+ std::string_view postCodeNumber = split[0];
+ if (postCodeNumber.size() < 2)
+ {
+ return false;
+ }
+ if (postCodeNumber[0] != 'B')
+ {
+ return false;
+ }
+ postCodeNumber.remove_prefix(1);
+ auto [ptrIndex, ecIndex] =
+ std::from_chars(postCodeNumber.begin(), postCodeNumber.end(), index);
+ if (ptrIndex != postCodeNumber.end() || ecIndex != std::errc())
+ {
+ return false;
+ }
+
+ std::string_view postCodeIndex = split[1];
+
+ auto [ptrValue, ecValue] = std::from_chars(
+ postCodeIndex.begin(), postCodeIndex.end(), currentValue);
+
+ return ptrValue == postCodeIndex.end() && ecValue == std::errc();
+}
+
+static bool fillPostCodeEntry(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const boost::container::flat_map<
+ uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& postcode,
+ const uint16_t bootIndex, const uint64_t codeIndex = 0,
+ const uint64_t skip = 0, const uint64_t top = 0)
+{
+ // Get the Message from the MessageRegistry
+ const registries::Message* message =
+ registries::getMessage("OpenBMC.0.2.BIOSPOSTCode");
+ if (message == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Couldn't find known message?");
+ return false;
+ }
+ uint64_t currentCodeIndex = 0;
+ uint64_t firstCodeTimeUs = 0;
+ for (const std::pair<uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
+ code : postcode)
+ {
+ currentCodeIndex++;
+ std::string postcodeEntryID =
+ "B" + std::to_string(bootIndex) + "-" +
+ std::to_string(currentCodeIndex); // 1 based index in EntryID string
+
+ uint64_t usecSinceEpoch = code.first;
+ uint64_t usTimeOffset = 0;
+
+ if (1 == currentCodeIndex)
+ { // already incremented
+ firstCodeTimeUs = code.first;
+ }
+ else
+ {
+ usTimeOffset = code.first - firstCodeTimeUs;
+ }
+
+ // skip if no specific codeIndex is specified and currentCodeIndex does
+ // not fall between top and skip
+ if ((codeIndex == 0) &&
+ (currentCodeIndex <= skip || currentCodeIndex > top))
+ {
+ continue;
+ }
+
+ // skip if a specific codeIndex is specified and does not match the
+ // currentIndex
+ if ((codeIndex > 0) && (currentCodeIndex != codeIndex))
+ {
+ // This is done for simplicity. 1st entry is needed to calculate
+ // time offset. To improve efficiency, one can get to the entry
+ // directly (possibly with flatmap's nth method)
+ continue;
+ }
+
+ // currentCodeIndex is within top and skip or equal to specified code
+ // index
+
+ // Get the Created time from the timestamp
+ std::string entryTimeStr;
+ entryTimeStr = redfish::time_utils::getDateTimeUintUs(usecSinceEpoch);
+
+ // assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
+ std::ostringstream hexCode;
+ hexCode << "0x" << std::setfill('0') << std::setw(2) << std::hex
+ << std::get<0>(code.second);
+ std::ostringstream timeOffsetStr;
+ // Set Fixed -Point Notation
+ timeOffsetStr << std::fixed;
+ // Set precision to 4 digits
+ timeOffsetStr << std::setprecision(4);
+ // Add double to stream
+ timeOffsetStr << static_cast<double>(usTimeOffset) / 1000 / 1000;
+
+ std::string bootIndexStr = std::to_string(bootIndex);
+ std::string timeOffsetString = timeOffsetStr.str();
+ std::string hexCodeStr = hexCode.str();
+
+ std::array<std::string_view, 3> messageArgs = {
+ bootIndexStr, timeOffsetString, hexCodeStr};
+
+ std::string msg =
+ redfish::registries::fillMessageArgs(messageArgs, message->message);
+ if (msg.empty())
+ {
+ messages::internalError(asyncResp->res);
+ return false;
+ }
+
+ // Get Severity template from message registry
+ std::string severity;
+ if (message != nullptr)
+ {
+ severity = message->messageSeverity;
+ }
+
+ // Format entry
+ nlohmann::json::object_t bmcLogEntry;
+ bmcLogEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
+ bmcLogEntry["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries/{}",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME, postcodeEntryID);
+ bmcLogEntry["Name"] = "POST Code Log Entry";
+ bmcLogEntry["Id"] = postcodeEntryID;
+ bmcLogEntry["Message"] = std::move(msg);
+ bmcLogEntry["MessageId"] = "OpenBMC.0.2.BIOSPOSTCode";
+ bmcLogEntry["MessageArgs"] = messageArgs;
+ bmcLogEntry["EntryType"] = "Event";
+ bmcLogEntry["Severity"] = std::move(severity);
+ bmcLogEntry["Created"] = entryTimeStr;
+ if (!std::get<std::vector<uint8_t>>(code.second).empty())
+ {
+ bmcLogEntry["AdditionalDataURI"] =
+ std::format(
+ "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries/",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME) +
+ postcodeEntryID + "/attachment";
+ }
+
+ // codeIndex is only specified when querying single entry, return only
+ // that entry in this case
+ if (codeIndex != 0)
+ {
+ asyncResp->res.jsonValue.update(bmcLogEntry);
+ return true;
+ }
+
+ nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
+ logEntryArray.emplace_back(std::move(bmcLogEntry));
+ }
+
+ // Return value is always false when querying multiple entries
+ return false;
+}
+
+inline void
+ getPostCodeForEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& entryId)
+{
+ uint16_t bootIndex = 0;
+ uint64_t codeIndex = 0;
+ if (!parsePostCode(entryId, codeIndex, bootIndex))
+ {
+ // Requested ID was not found
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
+ return;
+ }
+
+ if (bootIndex == 0 || codeIndex == 0)
+ {
+ // 0 is an invalid index
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, entryId, bootIndex,
+ codeIndex](const boost::system::error_code& ec,
+ const boost::container::flat_map<
+ uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
+ postcode) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS POST CODE PostCode response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (postcode.empty())
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
+ return;
+ }
+
+ if (!fillPostCodeEntry(asyncResp, postcode, bootIndex, codeIndex))
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
+ return;
+ }
+ },
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp",
+ bootIndex);
+}
+
+inline void
+ getPostCodeForBoot(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const uint16_t bootIndex, const uint16_t bootCount,
+ const uint64_t entryCount, size_t skip, size_t top)
+{
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, bootIndex, bootCount, entryCount, skip,
+ top](const boost::system::error_code& ec,
+ const boost::container::flat_map<
+ uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
+ postcode) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS POST CODE PostCode response error");
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ uint64_t endCount = entryCount;
+ if (!postcode.empty())
+ {
+ endCount = entryCount + postcode.size();
+ if (skip < endCount && (top + skip) > entryCount)
+ {
+ uint64_t thisBootSkip =
+ std::max(static_cast<uint64_t>(skip), entryCount) -
+ entryCount;
+ uint64_t thisBootTop =
+ std::min(static_cast<uint64_t>(top + skip), endCount) -
+ entryCount;
+
+ fillPostCodeEntry(asyncResp, postcode, bootIndex, 0,
+ thisBootSkip, thisBootTop);
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = endCount;
+ }
+
+ // continue to previous bootIndex
+ if (bootIndex < bootCount)
+ {
+ getPostCodeForBoot(asyncResp,
+ static_cast<uint16_t>(bootIndex + 1),
+ bootCount, endCount, skip, top);
+ }
+ else if (skip + top < endCount)
+ {
+ asyncResp->res.jsonValue["Members@odata.nextLink"] =
+ std::format(
+ "/redfish/v1/Systems/{}/LogServices/PostCodes/Entries?$skip=",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME) +
+ std::to_string(skip + top);
+ }
+ },
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodesWithTimeStamp",
+ bootIndex);
+}
+
+inline void
+ getCurrentBootNumber(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ size_t skip, size_t top)
+{
+ uint64_t entryCount = 0;
+ sdbusplus::asio::getProperty<uint16_t>(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount",
+ [asyncResp, entryCount, skip,
+ top](const boost::system::error_code& ec, const uint16_t bootCount) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ getPostCodeForBoot(asyncResp, 1, bootCount, entryCount, skip, top);
+ });
+}
+
+inline void handleSystemsLogServicesPostCodesEntriesGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName)
+{
+ query_param::QueryCapabilities capabilities = {
+ .canDelegateTop = true,
+ .canDelegateSkip = true,
+ };
+ query_param::Query delegatedQuery;
+ if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
+ delegatedQuery, capabilities))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ std::format("/redfish/v1/Systems/{}/LogServices/PostCodes/Entries",
+ BMCWEB_REDFISH_SYSTEM_URI_NAME);
+ asyncResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of POST Code Log Entries";
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+ size_t skip = delegatedQuery.skip.value_or(0);
+ size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
+ getCurrentBootNumber(asyncResp, skip, top);
+}
+
+inline void handleSystemsLogServicesPostCodesEntriesEntryAdditionalDataGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& postCodeID)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if (!http_helpers::isContentTypeAllowed(
+ req.getHeaderValue("Accept"),
+ http_helpers::ContentType::OctetStream, true))
+ {
+ asyncResp->res.result(boost::beast::http::status::bad_request);
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ uint64_t currentValue = 0;
+ uint16_t index = 0;
+ if (!parsePostCode(postCodeID, currentValue, index))
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry", postCodeID);
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, postCodeID, currentValue](
+ const boost::system::error_code& ec,
+ const std::vector<std::tuple<uint64_t, std::vector<uint8_t>>>&
+ postcodes) {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res, "LogEntry",
+ postCodeID);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ size_t value = static_cast<size_t>(currentValue) - 1;
+ if (value == std::string::npos || postcodes.size() < currentValue)
+ {
+ BMCWEB_LOG_WARNING("Wrong currentValue value");
+ messages::resourceNotFound(asyncResp->res, "LogEntry",
+ postCodeID);
+ return;
+ }
+
+ const auto& [tID, c] = postcodes[value];
+ if (c.empty())
+ {
+ BMCWEB_LOG_WARNING("No found post code data");
+ messages::resourceNotFound(asyncResp->res, "LogEntry",
+ postCodeID);
+ return;
+ }
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ const char* d = reinterpret_cast<const char*>(c.data());
+ std::string_view strData(d, c.size());
+
+ asyncResp->res.addHeader(boost::beast::http::field::content_type,
+ "application/octet-stream");
+ asyncResp->res.addHeader(
+ boost::beast::http::field::content_transfer_encoding, "Base64");
+ asyncResp->res.write(crow::utility::base64encode(strData));
+ },
+ "xyz.openbmc_project.State.Boot.PostCode0",
+ "/xyz/openbmc_project/State/Boot/PostCode0",
+ "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodes", index);
+}
+
+inline void handleSystemsLogServicesPostCodesEntriesEntryGet(
+ App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& systemName, const std::string& targetID)
+{
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+ {
+ // Option currently returns no systems. TBD
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+ if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+ {
+ messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+ systemName);
+ return;
+ }
+
+ getPostCodeForEntry(asyncResp, targetID);
+}
+
+inline void requestRoutesSystemsLogServicesPostCode(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/")
+ .privileges(redfish::privileges::getLogService)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesPostCodesGet, std::ref(app)));
+
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/<str>/LogServices/PostCodes/Actions/LogService.ClearLog/")
+ // The following privilege is correct; we need "SubordinateOverrides"
+ // before we can automate it.
+ .privileges({{"ConfigureComponents"}})
+ .methods(boost::beast::http::verb::post)(std::bind_front(
+ handleSystemsLogServicesPostCodesPost, std::ref(app)));
+
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/")
+ .privileges(redfish::privileges::getLogEntryCollection)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesPostCodesEntriesGet, std::ref(app)));
+
+ BMCWEB_ROUTE(
+ app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesPostCodesEntriesEntryGet, std::ref(app)));
+
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/attachment/")
+ .privileges(redfish::privileges::getLogEntry)
+ .methods(boost::beast::http::verb::get)(std::bind_front(
+ handleSystemsLogServicesPostCodesEntriesEntryAdditionalDataGet,
+ std::ref(app)));
+}
+} // namespace redfish
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index a2959b8455..5f67cf0448 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -1,23 +1,25 @@
/*
-// Copyright (c) 2020 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2020 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
#include "app.hpp"
#include "dbus_utility.hpp"
#include "event_service_manager.hpp"
+#include "generated/enums/resource.hpp"
+#include "generated/enums/task_service.hpp"
#include "http/parsing.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
@@ -72,8 +74,8 @@ struct Payload
continue;
}
std::string header;
- header.reserve(field.name_string().size() + 2 +
- field.value().size());
+ header.reserve(
+ field.name_string().size() + 2 + field.value().size());
header += field.name_string();
header += ": ";
header += field.value();
@@ -95,8 +97,7 @@ struct TaskData : std::enable_shared_from_this<TaskData>
std::function<bool(boost::system::error_code, sdbusplus::message_t&,
const std::shared_ptr<TaskData>&)>&& handler,
const std::string& matchIn, size_t idx) :
- callback(std::move(handler)),
- matchStr(matchIn), index(idx),
+ callback(std::move(handler)), matchStr(matchIn), index(idx),
startTime(std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now())),
status("OK"), state("Running"), messages(nlohmann::json::array()),
@@ -144,7 +145,8 @@ struct TaskData : std::enable_shared_from_this<TaskData>
{
res.result(boost::beast::http::status::accepted);
std::string strIdx = std::to_string(index);
- std::string uri = "/redfish/v1/TaskService/Tasks/" + strIdx;
+ boost::urls::url uri =
+ boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strIdx);
res.jsonValue["@odata.id"] = uri;
res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
@@ -152,8 +154,11 @@ struct TaskData : std::enable_shared_from_this<TaskData>
res.jsonValue["TaskState"] = state;
res.jsonValue["TaskStatus"] = status;
+ boost::urls::url taskMonitor = boost::urls::format(
+ "/redfish/v1/TaskService/TaskMonitors/{}", strIdx);
+
res.addHeader(boost::beast::http::field::location,
- uri + "/Monitor");
+ taskMonitor.buffer());
res.addHeader(boost::beast::http::field::retry_after,
std::to_string(retryAfterSeconds));
}
@@ -175,33 +180,30 @@ struct TaskData : std::enable_shared_from_this<TaskData>
timer.expires_after(timeout);
timer.async_wait(
[self = shared_from_this()](boost::system::error_code ec) {
- if (ec == boost::asio::error::operation_aborted)
- {
- return; // completed successfully
- }
- if (!ec)
- {
- // change ec to error as timer expired
- ec = boost::asio::error::operation_aborted;
- }
- self->match.reset();
- sdbusplus::message_t msg;
- self->finishTask();
- self->state = "Cancelled";
- self->status = "Warning";
- self->messages.emplace_back(
- messages::taskAborted(std::to_string(self->index)));
- // Send event :TaskAborted
- self->sendTaskEvent(self->state, self->index);
- self->callback(ec, msg, self);
- });
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ return; // completed successfully
+ }
+ if (!ec)
+ {
+ // change ec to error as timer expired
+ ec = boost::asio::error::operation_aborted;
+ }
+ self->match.reset();
+ sdbusplus::message_t msg;
+ self->finishTask();
+ self->state = "Cancelled";
+ self->status = "Warning";
+ self->messages.emplace_back(
+ messages::taskAborted(std::to_string(self->index)));
+ // Send event :TaskAborted
+ self->sendTaskEvent(self->state, self->index);
+ self->callback(ec, msg, self);
+ });
}
static void sendTaskEvent(std::string_view state, size_t index)
{
- std::string origin = "/redfish/v1/TaskService/Tasks/" +
- std::to_string(index);
- std::string resType = "Task";
// TaskState enums which should send out an event are:
// "Starting" = taskResumed
// "Running" = taskStarted
@@ -213,59 +215,50 @@ struct TaskData : std::enable_shared_from_this<TaskData>
// "Killed" = taskRemoved
// "Exception" = taskCompletedWarning
// "Cancelled" = taskCancelled
+ nlohmann::json event;
+ std::string indexStr = std::to_string(index);
if (state == "Starting")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskResumed(std::to_string(index)), origin,
- resType);
+ event = redfish::messages::taskResumed(indexStr);
}
else if (state == "Running")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskStarted(std::to_string(index)), origin,
- resType);
+ event = redfish::messages::taskStarted(indexStr);
}
else if ((state == "Suspended") || (state == "Interrupted") ||
(state == "Pending"))
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskPaused(std::to_string(index)), origin,
- resType);
+ event = redfish::messages::taskPaused(indexStr);
}
else if (state == "Stopping")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskAborted(std::to_string(index)), origin,
- resType);
+ event = redfish::messages::taskAborted(indexStr);
}
else if (state == "Completed")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskCompletedOK(std::to_string(index)),
- origin, resType);
+ event = redfish::messages::taskCompletedOK(indexStr);
}
else if (state == "Killed")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskRemoved(std::to_string(index)), origin,
- resType);
+ event = redfish::messages::taskRemoved(indexStr);
}
else if (state == "Exception")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskCompletedWarning(std::to_string(index)),
- origin, resType);
+ event = redfish::messages::taskCompletedWarning(indexStr);
}
else if (state == "Cancelled")
{
- redfish::EventServiceManager::getInstance().sendEvent(
- redfish::messages::taskCancelled(std::to_string(index)), origin,
- resType);
+ event = redfish::messages::taskCancelled(indexStr);
}
else
{
BMCWEB_LOG_INFO("sendTaskEvent: No events to send");
+ return;
}
+ boost::urls::url origin =
+ boost::urls::format("/redfish/v1/TaskService/Tasks/{}", index);
+ EventServiceManager::getInstance().sendEvent(event, origin.buffer(),
+ "Task");
}
void startTimer(const std::chrono::seconds& timeout)
@@ -278,25 +271,25 @@ struct TaskData : std::enable_shared_from_this<TaskData>
static_cast<sdbusplus::bus_t&>(*crow::connections::systemBus),
matchStr,
[self = shared_from_this()](sdbusplus::message_t& message) {
- boost::system::error_code ec;
-
- // callback to return True if callback is done, callback needs
- // to update status itself if needed
- if (self->callback(ec, message, self) == task::completed)
- {
- self->timer.cancel();
- self->finishTask();
-
- // Send event
- self->sendTaskEvent(self->state, self->index);
-
- // reset the match after the callback was successful
- boost::asio::post(
- crow::connections::systemBus->get_io_context(),
- [self] { self->match.reset(); });
- return;
- }
- });
+ boost::system::error_code ec;
+
+ // callback to return True if callback is done, callback needs
+ // to update status itself if needed
+ if (self->callback(ec, message, self) == task::completed)
+ {
+ self->timer.cancel();
+ self->finishTask();
+
+ // Send event
+ self->sendTaskEvent(self->state, self->index);
+
+ // reset the match after the callback was successful
+ boost::asio::post(
+ crow::connections::systemBus->get_io_context(),
+ [self] { self->match.reset(); });
+ return;
+ }
+ });
extendTimer(timeout);
messages.emplace_back(messages::taskStarted(std::to_string(index)));
@@ -325,43 +318,45 @@ struct TaskData : std::enable_shared_from_this<TaskData>
inline void requestRoutesTaskMonitor(App& app)
{
- BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/Monitor/")
+ BMCWEB_ROUTE(app, "/redfish/v1/TaskService/TaskMonitors/<str>/")
.privileges(redfish::privileges::getTask)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& strParam) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- auto find = std::ranges::find_if(
- task::tasks,
- [&strParam](const std::shared_ptr<task::TaskData>& task) {
- if (!task)
- {
- return false;
- }
-
- // we compare against the string version as on failure
- // strtoul returns 0
- return std::to_string(task->index) == strParam;
- });
-
- if (find == task::tasks.end())
- {
- messages::resourceNotFound(asyncResp->res, "Task", strParam);
- return;
- }
- std::shared_ptr<task::TaskData>& ptr = *find;
- // monitor expires after 204
- if (ptr->gave204)
- {
- messages::resourceNotFound(asyncResp->res, "Task", strParam);
- return;
- }
- ptr->populateResp(asyncResp->res);
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ auto find = std::ranges::find_if(
+ task::tasks,
+ [&strParam](const std::shared_ptr<task::TaskData>& task) {
+ if (!task)
+ {
+ return false;
+ }
+
+ // we compare against the string version as on failure
+ // strtoul returns 0
+ return std::to_string(task->index) == strParam;
+ });
+
+ if (find == task::tasks.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "Task",
+ strParam);
+ return;
+ }
+ std::shared_ptr<task::TaskData>& ptr = *find;
+ // monitor expires after 204
+ if (ptr->gave204)
+ {
+ messages::resourceNotFound(asyncResp->res, "Task",
+ strParam);
+ return;
+ }
+ ptr->populateResp(asyncResp->res);
+ });
}
inline void requestRoutesTask(App& app)
@@ -372,66 +367,75 @@ inline void requestRoutesTask(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& strParam) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- auto find = std::ranges::find_if(
- task::tasks,
- [&strParam](const std::shared_ptr<task::TaskData>& task) {
- if (!task)
- {
- return false;
- }
-
- // we compare against the string version as on failure
- // strtoul returns 0
- return std::to_string(task->index) == strParam;
- });
-
- if (find == task::tasks.end())
- {
- messages::resourceNotFound(asyncResp->res, "Task", strParam);
- return;
- }
-
- const std::shared_ptr<task::TaskData>& ptr = *find;
-
- asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
- asyncResp->res.jsonValue["Id"] = strParam;
- asyncResp->res.jsonValue["Name"] = "Task " + strParam;
- asyncResp->res.jsonValue["TaskState"] = ptr->state;
- asyncResp->res.jsonValue["StartTime"] =
- redfish::time_utils::getDateTimeStdtime(ptr->startTime);
- if (ptr->endTime)
- {
- asyncResp->res.jsonValue["EndTime"] =
- redfish::time_utils::getDateTimeStdtime(*(ptr->endTime));
- }
- asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
- asyncResp->res.jsonValue["Messages"] = ptr->messages;
- asyncResp->res.jsonValue["@odata.id"] =
- boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strParam);
- if (!ptr->gave204)
- {
- asyncResp->res.jsonValue["TaskMonitor"] =
- "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor";
- }
-
- asyncResp->res.jsonValue["HidePayload"] = !ptr->payload;
-
- if (ptr->payload)
- {
- const task::Payload& p = *(ptr->payload);
- asyncResp->res.jsonValue["Payload"]["TargetUri"] = p.targetUri;
- asyncResp->res.jsonValue["Payload"]["HttpOperation"] =
- p.httpOperation;
- asyncResp->res.jsonValue["Payload"]["HttpHeaders"] = p.httpHeaders;
- asyncResp->res.jsonValue["Payload"]["JsonBody"] = p.jsonBody.dump(
- 2, ' ', true, nlohmann::json::error_handler_t::replace);
- }
- asyncResp->res.jsonValue["PercentComplete"] = ptr->percentComplete;
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ auto find = std::ranges::find_if(
+ task::tasks,
+ [&strParam](const std::shared_ptr<task::TaskData>& task) {
+ if (!task)
+ {
+ return false;
+ }
+
+ // we compare against the string version as on failure
+ // strtoul returns 0
+ return std::to_string(task->index) == strParam;
+ });
+
+ if (find == task::tasks.end())
+ {
+ messages::resourceNotFound(asyncResp->res, "Task",
+ strParam);
+ return;
+ }
+
+ const std::shared_ptr<task::TaskData>& ptr = *find;
+
+ asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
+ asyncResp->res.jsonValue["Id"] = strParam;
+ asyncResp->res.jsonValue["Name"] = "Task " + strParam;
+ asyncResp->res.jsonValue["TaskState"] = ptr->state;
+ asyncResp->res.jsonValue["StartTime"] =
+ redfish::time_utils::getDateTimeStdtime(ptr->startTime);
+ if (ptr->endTime)
+ {
+ asyncResp->res.jsonValue["EndTime"] =
+ redfish::time_utils::getDateTimeStdtime(
+ *(ptr->endTime));
+ }
+ asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
+ asyncResp->res.jsonValue["Messages"] = ptr->messages;
+ asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+ "/redfish/v1/TaskService/Tasks/{}", strParam);
+ if (!ptr->gave204)
+ {
+ asyncResp->res.jsonValue["TaskMonitor"] =
+ boost::urls::format(
+ "/redfish/v1/TaskService/TaskMonitors/{}",
+ strParam);
+ }
+
+ asyncResp->res.jsonValue["HidePayload"] = !ptr->payload;
+
+ if (ptr->payload)
+ {
+ const task::Payload& p = *(ptr->payload);
+ asyncResp->res.jsonValue["Payload"]["TargetUri"] =
+ p.targetUri;
+ asyncResp->res.jsonValue["Payload"]["HttpOperation"] =
+ p.httpOperation;
+ asyncResp->res.jsonValue["Payload"]["HttpHeaders"] =
+ p.httpHeaders;
+ asyncResp->res.jsonValue["Payload"]["JsonBody"] =
+ p.jsonBody.dump(
+ -1, ' ', true,
+ nlohmann::json::error_handler_t::replace);
+ }
+ asyncResp->res.jsonValue["PercentComplete"] =
+ ptr->percentComplete;
+ });
}
inline void requestRoutesTaskCollection(App& app)
@@ -441,31 +445,33 @@ inline void requestRoutesTaskCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#TaskCollection.TaskCollection";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService/Tasks";
- asyncResp->res.jsonValue["Name"] = "Task Collection";
- asyncResp->res.jsonValue["Members@odata.count"] = task::tasks.size();
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- members = nlohmann::json::array();
-
- for (const std::shared_ptr<task::TaskData>& task : task::tasks)
- {
- if (task == nullptr)
- {
- continue; // shouldn't be possible
- }
- nlohmann::json::object_t member;
- member["@odata.id"] =
- boost::urls::format("/redfish/v1/TaskService/Tasks/{}",
- std::to_string(task->index));
- members.emplace_back(std::move(member));
- }
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#TaskCollection.TaskCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TaskService/Tasks";
+ asyncResp->res.jsonValue["Name"] = "Task Collection";
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ task::tasks.size();
+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
+ members = nlohmann::json::array();
+
+ for (const std::shared_ptr<task::TaskData>& task : task::tasks)
+ {
+ if (task == nullptr)
+ {
+ continue; // shouldn't be possible
+ }
+ nlohmann::json::object_t member;
+ member["@odata.id"] =
+ boost::urls::format("/redfish/v1/TaskService/Tasks/{}",
+ std::to_string(task->index));
+ members.emplace_back(std::move(member));
+ }
+ });
}
inline void requestRoutesTaskService(App& app)
@@ -475,26 +481,30 @@ inline void requestRoutesTaskService(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#TaskService.v1_1_4.TaskService";
- asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService";
- asyncResp->res.jsonValue["Name"] = "Task Service";
- asyncResp->res.jsonValue["Id"] = "TaskService";
- asyncResp->res.jsonValue["DateTime"] =
- redfish::time_utils::getDateTimeOffsetNow().first;
- asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest";
-
- asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true;
-
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["ServiceEnabled"] = true;
- asyncResp->res.jsonValue["Tasks"]["@odata.id"] =
- "/redfish/v1/TaskService/Tasks";
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#TaskService.v1_1_4.TaskService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TaskService";
+ asyncResp->res.jsonValue["Name"] = "Task Service";
+ asyncResp->res.jsonValue["Id"] = "TaskService";
+ asyncResp->res.jsonValue["DateTime"] =
+ redfish::time_utils::getDateTimeOffsetNow().first;
+ asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] =
+ task_service::OverWritePolicy::Oldest;
+
+ asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] =
+ true;
+
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
+ asyncResp->res.jsonValue["ServiceEnabled"] = true;
+ asyncResp->res.jsonValue["Tasks"]["@odata.id"] =
+ "/redfish/v1/TaskService/Tasks";
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
index 724e8aad27..cd051dcc0c 100644
--- a/redfish-core/lib/telemetry_service.hpp
+++ b/redfish-core/lib/telemetry_service.hpp
@@ -2,6 +2,7 @@
#include "app.hpp"
#include "dbus_utility.hpp"
+#include "generated/enums/resource.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/dbus_utils.hpp"
@@ -41,53 +42,55 @@ inline void handleTelemetryServiceGet(
"xyz.openbmc_project.Telemetry.ReportManager",
[asyncResp](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& ret) {
- if (ec == boost::system::errc::host_unreachable)
- {
- asyncResp->res.jsonValue["Status"]["State"] = "Absent";
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec == boost::system::errc::host_unreachable)
+ {
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Absent;
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+ asyncResp->res.jsonValue["Status"]["State"] =
+ resource::State::Enabled;
- const size_t* maxReports = nullptr;
- const uint64_t* minInterval = nullptr;
+ const size_t* maxReports = nullptr;
+ const uint64_t* minInterval = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), ret, "MaxReports", maxReports,
- "MinInterval", minInterval);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), ret, "MaxReports", maxReports,
+ "MinInterval", minInterval);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (maxReports != nullptr)
- {
- asyncResp->res.jsonValue["MaxReports"] = *maxReports;
- }
+ if (maxReports != nullptr)
+ {
+ asyncResp->res.jsonValue["MaxReports"] = *maxReports;
+ }
- if (minInterval != nullptr)
- {
- asyncResp->res.jsonValue["MinCollectionInterval"] =
- time_utils::toDurationString(std::chrono::milliseconds(
- static_cast<time_t>(*minInterval)));
- }
- nlohmann::json::array_t supportedCollectionFunctions;
- supportedCollectionFunctions.emplace_back("Maximum");
- supportedCollectionFunctions.emplace_back("Minimum");
- supportedCollectionFunctions.emplace_back("Average");
- supportedCollectionFunctions.emplace_back("Summation");
+ if (minInterval != nullptr)
+ {
+ asyncResp->res.jsonValue["MinCollectionInterval"] =
+ time_utils::toDurationString(std::chrono::milliseconds(
+ static_cast<time_t>(*minInterval)));
+ }
+ nlohmann::json::array_t supportedCollectionFunctions;
+ supportedCollectionFunctions.emplace_back("Maximum");
+ supportedCollectionFunctions.emplace_back("Minimum");
+ supportedCollectionFunctions.emplace_back("Average");
+ supportedCollectionFunctions.emplace_back("Summation");
- asyncResp->res.jsonValue["SupportedCollectionFunctions"] =
- std::move(supportedCollectionFunctions);
- });
+ asyncResp->res.jsonValue["SupportedCollectionFunctions"] =
+ std::move(supportedCollectionFunctions);
+ });
}
inline void requestRoutesTelemetryService(App& app)
diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp
index 84bf37a04e..adcd4b995d 100644
--- a/redfish-core/lib/thermal.hpp
+++ b/redfish-core/lib/thermal.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -20,6 +20,7 @@
#include "registries/privilege_registry.hpp"
#include "sensors.hpp"
#include "utils/json_utils.hpp"
+#include "utils/sensor_utils.hpp"
namespace redfish
{
@@ -32,18 +33,19 @@ inline void requestRoutesThermal(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& chassisName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
- asyncResp, chassisName, sensors::dbus::thermalPaths,
- sensors::node::thermal);
+ auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+ asyncResp, chassisName, sensors::dbus::thermalPaths,
+ sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::thermalNode));
- // TODO Need to get Chassis Redundancy information.
- getChassisData(sensorAsyncResp);
- });
+ // TODO Need to get Chassis Redundancy information.
+ getChassisData(sensorAsyncResp);
+ });
BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Thermal/")
.privileges(redfish::privileges::patchThermal)
@@ -51,44 +53,48 @@ inline void requestRoutesThermal(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& chassisName) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
- std::optional<std::vector<nlohmann::json::object_t>>
- temperatureCollections;
- std::optional<std::vector<nlohmann::json::object_t>> fanCollections;
- std::unordered_map<std::string, std::vector<nlohmann::json::object_t>>
- allCollections;
+ std::optional<std::vector<nlohmann::json::object_t>>
+ temperatureCollections;
+ std::optional<std::vector<nlohmann::json::object_t>>
+ fanCollections;
+ std::unordered_map<std::string,
+ std::vector<nlohmann::json::object_t>>
+ allCollections;
- auto sensorsAsyncResp = std::make_shared<SensorsAsyncResp>(
- asyncResp, chassisName, sensors::dbus::thermalPaths,
- sensors::node::thermal);
+ auto sensorsAsyncResp = std::make_shared<SensorsAsyncResp>(
+ asyncResp, chassisName, sensors::dbus::thermalPaths,
+ sensor_utils::chassisSubNodeToString(
+ sensor_utils::ChassisSubNode::thermalNode));
- if (!json_util::readJsonPatch(req, sensorsAsyncResp->asyncResp->res,
- "Temperatures", temperatureCollections,
- "Fans", fanCollections))
- {
- return;
- }
- if (!temperatureCollections && !fanCollections)
- {
- messages::resourceNotFound(sensorsAsyncResp->asyncResp->res,
- "Thermal", "Temperatures / Voltages");
- return;
- }
- if (temperatureCollections)
- {
- allCollections.emplace("Temperatures",
- *std::move(temperatureCollections));
- }
- if (fanCollections)
- {
- allCollections.emplace("Fans", *std::move(fanCollections));
- }
- setSensorsOverride(sensorsAsyncResp, allCollections);
- });
+ if (!json_util::readJsonPatch(
+ req, sensorsAsyncResp->asyncResp->res, "Temperatures",
+ temperatureCollections, "Fans", fanCollections))
+ {
+ return;
+ }
+ if (!temperatureCollections && !fanCollections)
+ {
+ messages::resourceNotFound(sensorsAsyncResp->asyncResp->res,
+ "Thermal",
+ "Temperatures / Voltages");
+ return;
+ }
+ if (temperatureCollections)
+ {
+ allCollections.emplace("Temperatures",
+ *std::move(temperatureCollections));
+ }
+ if (fanCollections)
+ {
+ allCollections.emplace("Fans", *std::move(fanCollections));
+ }
+ setSensorsOverride(sensorsAsyncResp, allCollections);
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/thermal_metrics.hpp b/redfish-core/lib/thermal_metrics.hpp
index f2541182f7..da4da01858 100644
--- a/redfish-core/lib/thermal_metrics.hpp
+++ b/redfish-core/lib/thermal_metrics.hpp
@@ -48,15 +48,16 @@ inline void handleThermalMetricsHead(
asyncResp, chassisId,
[asyncResp,
chassisId](const std::optional<std::string>& validChassisPath) {
- if (!validChassisPath)
- {
- messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
- return;
- }
- asyncResp->res.addHeader(
- boost::beast::http::field::link,
- "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby");
- });
+ if (!validChassisPath)
+ {
+ messages::resourceNotFound(asyncResp->res, "Chassis",
+ chassisId);
+ return;
+ }
+ asyncResp->res.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby");
+ });
}
inline void
diff --git a/redfish-core/lib/thermal_subsystem.hpp b/redfish-core/lib/thermal_subsystem.hpp
index c52f395686..5365cb5a15 100644
--- a/redfish-core/lib/thermal_subsystem.hpp
+++ b/redfish-core/lib/thermal_subsystem.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "app.hpp"
+#include "generated/enums/resource.hpp"
#include "logging.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
@@ -46,8 +47,8 @@ inline void doThermalSubsystemCollection(
"/redfish/v1/Chassis/{}/ThermalSubsystem/ThermalMetrics",
chassisId);
- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
- asyncResp->res.jsonValue["Status"]["Health"] = "OK";
+ asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
+ asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
}
inline void handleThermalSubsystemCollectionHead(
diff --git a/redfish-core/lib/trigger.hpp b/redfish-core/lib/trigger.hpp
index a6101a2a1d..d405d26d60 100644
--- a/redfish-core/lib/trigger.hpp
+++ b/redfish-core/lib/trigger.hpp
@@ -1,15 +1,16 @@
#pragma once
#include "app.hpp"
+#include "generated/enums/metric_definition.hpp"
#include "generated/enums/resource.hpp"
#include "generated/enums/triggers.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
-#include "sensors.hpp"
#include "utility.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
+#include "utils/sensor_utils.hpp"
#include "utils/telemetry_utils.hpp"
#include "utils/time_utils.hpp"
@@ -321,9 +322,8 @@ struct NumericThresholds
}
};
-inline bool parseNumericThresholds(crow::Response& res,
- NumericThresholds& numericThresholds,
- Context& ctx)
+inline bool parseNumericThresholds(
+ crow::Response& res, NumericThresholds& numericThresholds, Context& ctx)
{
std::vector<NumericThresholdParams> parsedParams;
if (numericThresholds.upperCritical)
@@ -567,7 +567,7 @@ inline bool parseMetricProperties(crow::Response& res, Context& ctx)
}
std::pair<std::string, std::string> split =
- splitSensorNameAndType(sensorName);
+ redfish::sensor_utils::splitSensorNameAndType(sensorName);
if (split.first.empty() || split.second.empty())
{
messages::propertyValueIncorrect(
@@ -575,8 +575,8 @@ inline bool parseMetricProperties(crow::Response& res, Context& ctx)
return false;
}
- std::string sensorPath = "/xyz/openbmc_project/sensors/" + split.first +
- '/' + split.second;
+ std::string sensorPath =
+ "/xyz/openbmc_project/sensors/" + split.first + '/' + split.second;
ctx.sensors.emplace_back(sensorPath, uriStr);
uriIdx++;
@@ -900,7 +900,7 @@ inline bool fillTrigger(
json["DiscreteTriggers"] = *discreteTriggers;
json["DiscreteTriggerCondition"] =
discreteTriggers->empty() ? "Changed" : "Specified";
- json["MetricType"] = "Discrete";
+ json["MetricType"] = metric_definition::MetricType::Discrete;
}
else
{
@@ -916,7 +916,7 @@ inline bool fillTrigger(
}
json["NumericThresholds"] = *numericThresholds;
- json["MetricType"] = "Numeric";
+ json["MetricType"] = metric_definition::MetricType::Numeric;
}
}
@@ -956,8 +956,8 @@ inline void handleTriggerCollectionPost(
crow::connections::systemBus->async_method_call(
[asyncResp, id = ctx.id](const boost::system::error_code& ec,
const std::string& dbusPath) {
- afterCreateTrigger(ec, dbusPath, asyncResp, id);
- },
+ afterCreateTrigger(ec, dbusPath, asyncResp, id);
+ },
service, "/xyz/openbmc_project/Telemetry/Triggers",
"xyz.openbmc_project.Telemetry.TriggerManager", "AddTrigger",
"TelemetryService/" + ctx.id, ctx.name, ctx.actions, ctx.sensors,
@@ -973,23 +973,23 @@ inline void requestRoutesTriggerCollection(App& app)
.methods(boost::beast::http::verb::get)(
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#TriggersCollection.TriggersCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/TelemetryService/Triggers";
- asyncResp->res.jsonValue["Name"] = "Triggers Collection";
- constexpr std::array<std::string_view, 1> interfaces{
- telemetry::triggerInterface};
- collection_util::getCollectionMembers(
- asyncResp,
- boost::urls::url("/redfish/v1/TelemetryService/Triggers"),
- interfaces,
- "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#TriggersCollection.TriggersCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/TelemetryService/Triggers";
+ asyncResp->res.jsonValue["Name"] = "Triggers Collection";
+ constexpr std::array<std::string_view, 1> interfaces{
+ telemetry::triggerInterface};
+ collection_util::getCollectionMembers(
+ asyncResp,
+ boost::urls::url("/redfish/v1/TelemetryService/Triggers"),
+ interfaces,
+ "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
+ });
BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
.privileges(redfish::privileges::postTriggersCollection)
@@ -1005,36 +1005,40 @@ inline void requestRoutesTrigger(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& id) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, telemetry::service,
- telemetry::getDbusTriggerPath(id), telemetry::triggerInterface,
- [asyncResp,
- id](const boost::system::error_code& ec,
- const std::vector<std::pair<
- std::string, telemetry::TriggerGetParamsVariant>>& ret) {
- if (ec.value() == EBADR ||
- ec == boost::system::errc::host_unreachable)
- {
- messages::resourceNotFound(asyncResp->res, "Triggers", id);
- return;
- }
- if (ec)
- {
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- if (!telemetry::fillTrigger(asyncResp->res.jsonValue, id, ret))
- {
- messages::internalError(asyncResp->res);
- }
- });
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus, telemetry::service,
+ telemetry::getDbusTriggerPath(id),
+ telemetry::triggerInterface,
+ [asyncResp,
+ id](const boost::system::error_code& ec,
+ const std::vector<std::pair<
+ std::string, telemetry::TriggerGetParamsVariant>>&
+ ret) {
+ if (ec.value() == EBADR ||
+ ec == boost::system::errc::host_unreachable)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "Triggers", id);
+ return;
+ }
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if (!telemetry::fillTrigger(asyncResp->res.jsonValue,
+ id, ret))
+ {
+ messages::internalError(asyncResp->res);
+ }
+ });
+ });
BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/")
.privileges(redfish::privileges::deleteTriggers)
@@ -1042,32 +1046,35 @@ inline void requestRoutesTrigger(App& app)
[&app](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& id) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- const std::string triggerPath = telemetry::getDbusTriggerPath(id);
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, id](const boost::system::error_code& ec) {
- if (ec.value() == EBADR)
- {
- messages::resourceNotFound(asyncResp->res, "Triggers", id);
- return;
- }
-
- if (ec)
- {
- BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
-
- asyncResp->res.result(boost::beast::http::status::no_content);
- },
- telemetry::service, triggerPath,
- "xyz.openbmc_project.Object.Delete", "Delete");
- });
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ const std::string triggerPath =
+ telemetry::getDbusTriggerPath(id);
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, id](const boost::system::error_code& ec) {
+ if (ec.value() == EBADR)
+ {
+ messages::resourceNotFound(asyncResp->res,
+ "Triggers", id);
+ return;
+ }
+
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("respHandler DBus error {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ asyncResp->res.result(
+ boost::beast::http::status::no_content);
+ },
+ telemetry::service, triggerPath,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ });
}
} // namespace redfish
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 9a399affa4..eb25d1f8f6 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -118,12 +118,12 @@ inline void activateImage(const std::string& objPath,
"xyz.openbmc_project.Software.Activation", "RequestedActivation",
"xyz.openbmc_project.Software.Activation.RequestedActivations.Active",
[](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("error_code = {}", ec);
- BMCWEB_LOG_DEBUG("error msg = {}", ec.message());
- }
- });
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("error_code = {}", ec);
+ BMCWEB_LOG_DEBUG("error msg = {}", ec.message());
+ }
+ });
}
inline bool handleCreateTask(const boost::system::error_code& ec2,
@@ -243,7 +243,7 @@ inline void createTask(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
// Note that asyncResp can be either a valid pointer or nullptr. If nullptr
// then no asyncResp updates will occur
-static void
+inline void
softwareInterfaceAdded(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
sdbusplus::message_t& m, task::Payload&& payload)
{
@@ -270,40 +270,41 @@ static void
const std::vector<
std::pair<std::string, std::vector<std::string>>>&
objInfo) mutable {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("error_code = {}", ec);
- BMCWEB_LOG_DEBUG("error msg = {}", ec.message());
- if (asyncResp)
+ if (ec)
{
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_DEBUG("error_code = {}", ec);
+ BMCWEB_LOG_DEBUG("error msg = {}", ec.message());
+ if (asyncResp)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ cleanUp();
+ return;
}
- cleanUp();
- return;
- }
- // Ensure we only got one service back
- if (objInfo.size() != 1)
- {
- BMCWEB_LOG_ERROR("Invalid Object Size {}", objInfo.size());
- if (asyncResp)
+ // Ensure we only got one service back
+ if (objInfo.size() != 1)
{
- messages::internalError(asyncResp->res);
+ BMCWEB_LOG_ERROR("Invalid Object Size {}",
+ objInfo.size());
+ if (asyncResp)
+ {
+ messages::internalError(asyncResp->res);
+ }
+ cleanUp();
+ return;
}
- cleanUp();
- return;
- }
- // cancel timer only when
- // xyz.openbmc_project.Software.Activation interface
- // is added
- fwAvailableTimer = nullptr;
+ // cancel timer only when
+ // xyz.openbmc_project.Software.Activation interface
+ // is added
+ fwAvailableTimer = nullptr;
- activateImage(objPath.str, objInfo[0].first);
- if (asyncResp)
- {
- createTask(asyncResp, std::move(payload), objPath);
- }
- fwUpdateInProgress = false;
- });
+ activateImage(objPath.str, objInfo[0].first);
+ if (asyncResp)
+ {
+ createTask(asyncResp, std::move(payload), objPath);
+ }
+ fwUpdateInProgress = false;
+ });
break;
}
@@ -485,10 +486,9 @@ inline void monitorForSoftwareAvailable(
std::bind_front(afterUpdateErrorMatcher, asyncResp, url));
}
-inline std::optional<boost::urls::url>
- parseSimpleUpdateUrl(std::string imageURI,
- std::optional<std::string> transferProtocol,
- crow::Response& res)
+inline std::optional<boost::urls::url> parseSimpleUpdateUrl(
+ std::string imageURI, std::optional<std::string> transferProtocol,
+ crow::Response& res)
{
if (imageURI.find("://") == std::string::npos)
{
@@ -574,61 +574,6 @@ inline void doHttpsUpdate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
url.buffer());
}
-inline void doTftpUpdate(const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const boost::urls::url_view_base& url)
-{
- if (!BMCWEB_INSECURE_TFTP_UPDATE)
- {
- messages::actionParameterNotSupported(asyncResp->res, "ImageURI",
- url.buffer());
- return;
- }
-
- std::string path(url.encoded_path());
- if (path.size() < 2)
- {
- messages::actionParameterNotSupported(asyncResp->res, "ImageURI",
- url.buffer());
- return;
- }
- // TFTP expects a path without a /
- path.erase(0, 1);
- std::string host(url.encoded_host_and_port());
- BMCWEB_LOG_DEBUG("Server: {} File: {}", host, path);
-
- // Setup callback for when new software detected
- // Give TFTP 10 minutes to complete
- monitorForSoftwareAvailable(
- asyncResp, req,
- "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate", 600);
-
- // TFTP can take up to 10 minutes depending on image size and
- // connection speed. Return to caller as soon as the TFTP operation
- // has been started. The callback above will ensure the activate
- // is started once the download has completed
- redfish::messages::success(asyncResp->res);
-
- // Call TFTP service
- crow::connections::systemBus->async_method_call(
- [](const boost::system::error_code& ec) {
- if (ec)
- {
- // messages::internalError(asyncResp->res);
- cleanUp();
- BMCWEB_LOG_DEBUG("error_code = {}", ec);
- BMCWEB_LOG_DEBUG("error msg = {}", ec.message());
- }
- else
- {
- BMCWEB_LOG_DEBUG("Call to DownloaViaTFTP Success");
- }
- },
- "xyz.openbmc_project.Software.Download",
- "/xyz/openbmc_project/software", "xyz.openbmc_project.Common.TFTP",
- "DownloadViaTFTP", path, host);
-}
-
inline void handleUpdateServiceSimpleUpdateAction(
crow::App& app, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
@@ -662,11 +607,7 @@ inline void handleUpdateServiceSimpleUpdateAction(
{
return;
}
- if (url->scheme() == "tftp")
- {
- doTftpUpdate(req, asyncResp, *url);
- }
- else if (url->scheme() == "https")
+ if (url->scheme() == "https")
{
doHttpsUpdate(asyncResp, *url);
}
@@ -688,8 +629,8 @@ inline void uploadImageFile(crow::Response& res, std::string_view body)
std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
std::ofstream::trunc);
// set the permission of the file to 640
- std::filesystem::perms permission = std::filesystem::perms::owner_read |
- std::filesystem::perms::group_read;
+ std::filesystem::perms permission =
+ std::filesystem::perms::owner_read | std::filesystem::perms::group_read;
std::filesystem::permissions(filepath, permission);
out << body;
@@ -811,7 +752,11 @@ inline std::optional<MultiPartUpdateParameters>
{
std::vector<std::string> tempTargets;
nlohmann::json content =
- nlohmann::json::parse(formpart.content);
+ nlohmann::json::parse(formpart.content, nullptr, false);
+ if (content.is_discarded())
+ {
+ return std::nullopt;
+ }
nlohmann::json::object_t* obj =
content.get_ptr<nlohmann::json::object_t*>();
if (obj == nullptr)
@@ -872,11 +817,10 @@ inline std::optional<MultiPartUpdateParameters>
return multiRet;
}
-inline void
- handleStartUpdate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- task::Payload payload, const std::string& objectPath,
- const boost::system::error_code& ec,
- const sdbusplus::message::object_path& retPath)
+inline void handleStartUpdate(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, task::Payload payload,
+ const std::string& objectPath, const boost::system::error_code& ec,
+ const sdbusplus::message::object_path& retPath)
{
if (ec)
{
@@ -886,34 +830,37 @@ inline void
return;
}
- BMCWEB_LOG_INFO("Call to StartUpdate Success, retPath = {}", retPath.str);
- createTask(asyncResp, std::move(payload), objectPath);
+ BMCWEB_LOG_INFO("Call to StartUpdate on {} Success, retPath = {}",
+ objectPath, retPath.str);
+ createTask(asyncResp, std::move(payload), retPath);
}
-inline void startUpdate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- task::Payload payload,
- const MemoryFileDescriptor& memfd,
- const std::string& applyTime,
- const std::string& objectPath,
- const std::string& serviceName)
+inline void startUpdate(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, task::Payload payload,
+ const MemoryFileDescriptor& memfd, const std::string& applyTime,
+ const std::string& objectPath, const std::string& serviceName)
{
crow::connections::systemBus->async_method_call(
[asyncResp, payload = std::move(payload),
objectPath](const boost::system::error_code& ec1,
const sdbusplus::message::object_path& retPath) mutable {
- handleStartUpdate(asyncResp, std::move(payload), objectPath, ec1,
- retPath);
- },
+ handleStartUpdate(asyncResp, std::move(payload), objectPath, ec1,
+ retPath);
+ },
serviceName, objectPath, "xyz.openbmc_project.Software.Update",
"StartUpdate", sdbusplus::message::unix_fd(memfd.fd), applyTime);
}
-inline void getAssociatedUpdateInterface(
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, task::Payload payload,
- const MemoryFileDescriptor& memfd, const std::string& applyTime,
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreeResponse& subtree)
+inline void getSwInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ task::Payload payload, const MemoryFileDescriptor& memfd,
+ const std::string& applyTime, const std::string& target,
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse& subtree)
{
+ using SwInfoMap = std::unordered_map<
+ std::string, std::pair<sdbusplus::message::object_path, std::string>>;
+ SwInfoMap swInfoMap;
+
if (ec)
{
BMCWEB_LOG_ERROR("error_code = {}", ec);
@@ -921,35 +868,36 @@ inline void getAssociatedUpdateInterface(
messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_DEBUG("Found {} startUpdate subtree paths", subtree.size());
+ BMCWEB_LOG_DEBUG("Found {} software version paths", subtree.size());
- if (subtree.size() > 1)
+ for (const auto& entry : subtree)
{
- BMCWEB_LOG_ERROR("Found more than one startUpdate subtree paths");
- messages::internalError(asyncResp->res);
+ sdbusplus::message::object_path path(entry.first);
+ std::string swId = path.filename();
+ swInfoMap.emplace(swId, make_pair(path, entry.second[0].first));
+ }
+
+ auto swEntry = swInfoMap.find(target);
+ if (swEntry == swInfoMap.end())
+ {
+ BMCWEB_LOG_WARNING("No valid DBus path for Target URI {}", target);
+ messages::propertyValueFormatError(asyncResp->res, target, "Targets");
return;
}
- auto objectPath = subtree[0].first;
- auto serviceName = subtree[0].second[0].first;
+ BMCWEB_LOG_DEBUG("Found software version path {} serviceName {}",
+ swEntry->second.first.str, swEntry->second.second);
- BMCWEB_LOG_DEBUG("Found objectPath {} serviceName {}", objectPath,
- serviceName);
- startUpdate(asyncResp, std::move(payload), memfd, applyTime, objectPath,
- serviceName);
+ startUpdate(asyncResp, std::move(payload), memfd, applyTime,
+ swEntry->second.first.str, swEntry->second.second);
}
-inline void
- getSwInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- task::Payload payload, MemoryFileDescriptor memfd,
- const std::string& applyTime, const std::string& target,
- const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse& subtree)
+inline void handleBMCUpdate(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, task::Payload payload,
+ const MemoryFileDescriptor& memfd, const std::string& applyTime,
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperEndPoints& functionalSoftware)
{
- using SwInfoMap =
- std::unordered_map<std::string, sdbusplus::message::object_path>;
- SwInfoMap swInfoMap;
-
if (ec)
{
BMCWEB_LOG_ERROR("error_code = {}", ec);
@@ -957,47 +905,22 @@ inline void
messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_DEBUG("Found {} software version paths", subtree.size());
-
- for (const auto& objectPath : subtree)
- {
- sdbusplus::message::object_path path(objectPath);
- std::string swId = path.filename();
- swInfoMap.emplace(swId, path);
- }
-
- auto swEntry = swInfoMap.find(target);
- if (swEntry == swInfoMap.end())
+ if (functionalSoftware.size() != 1)
{
- BMCWEB_LOG_WARNING("No valid DBus path for Target URI {}", target);
- messages::propertyValueFormatError(asyncResp->res, target, "Targets");
+ BMCWEB_LOG_ERROR("Found {} functional software endpoints",
+ functionalSoftware.size());
+ messages::internalError(asyncResp->res);
return;
}
- BMCWEB_LOG_DEBUG("Found software version path {}", swEntry->second.str);
-
- sdbusplus::message::object_path swObjectPath = swEntry->second /
- "software_version";
- constexpr std::array<std::string_view, 1> interfaces = {
- "xyz.openbmc_project.Software.Update"};
- dbus::utility::getAssociatedSubTree(
- swObjectPath,
- sdbusplus::message::object_path("/xyz/openbmc_project/software"), 0,
- interfaces,
- [asyncResp, payload = std::move(payload), memfd = std::move(memfd),
- applyTime](
- const boost::system::error_code& ec1,
- const dbus::utility::MapperGetSubTreeResponse& subtree1) mutable {
- getAssociatedUpdateInterface(asyncResp, std::move(payload), memfd,
- applyTime, ec1, subtree1);
- });
+ startUpdate(asyncResp, std::move(payload), memfd, applyTime,
+ functionalSoftware[0], "xyz.openbmc_project.Software.Manager");
}
-inline void
- processUpdateRequest(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- task::Payload&& payload, std::string_view body,
- const std::string& applyTime,
- std::vector<std::string>& targets)
+inline void processUpdateRequest(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ task::Payload&& payload, std::string_view body,
+ const std::string& applyTime, std::vector<std::string>& targets)
{
MemoryFileDescriptor memfd("update-image");
if (memfd.fd == -1)
@@ -1021,24 +944,29 @@ inline void
if (!targets.empty() && targets[0] == BMCWEB_REDFISH_MANAGER_URI_NAME)
{
- startUpdate(asyncResp, std::move(payload), memfd, applyTime,
- "/xyz/openbmc_project/software/bmc",
- "xyz.openbmc_project.Software.Manager");
+ dbus::utility::getAssociationEndPoints(
+ "/xyz/openbmc_project/software/bmc/functional",
+ [asyncResp, payload = std::move(payload), memfd = std::move(memfd),
+ applyTime](
+ const boost::system::error_code& ec,
+ const dbus::utility::MapperEndPoints& objectPaths) mutable {
+ handleBMCUpdate(asyncResp, std::move(payload), memfd, applyTime,
+ ec, objectPaths);
+ });
}
else
{
constexpr std::array<std::string_view, 1> interfaces = {
"xyz.openbmc_project.Software.Version"};
- dbus::utility::getSubTreePaths(
+ dbus::utility::getSubTree(
"/xyz/openbmc_project/software", 1, interfaces,
[asyncResp, payload = std::move(payload), memfd = std::move(memfd),
- applyTime,
- targets](const boost::system::error_code& ec,
- const dbus::utility::MapperGetSubTreePathsResponse&
- subtree) mutable {
- getSwInfo(asyncResp, std::move(payload), std::move(memfd),
- applyTime, targets[0], ec, subtree);
- });
+ applyTime, targets](const boost::system::error_code& ec,
+ const dbus::utility::MapperGetSubTreeResponse&
+ subtree) mutable {
+ getSwInfo(asyncResp, std::move(payload), memfd, applyTime,
+ targets[0], ec, subtree);
+ });
}
}
@@ -1176,8 +1104,8 @@ inline void
asyncResp->res.jsonValue["FirmwareInventory"]["@odata.id"] =
"/redfish/v1/UpdateService/FirmwareInventory";
// Get the MaxImageSizeBytes
- asyncResp->res.jsonValue["MaxImageSizeBytes"] = BMCWEB_HTTP_BODY_LIMIT *
- 1024 * 1024;
+ asyncResp->res.jsonValue["MaxImageSizeBytes"] =
+ BMCWEB_HTTP_BODY_LIMIT * 1024 * 1024;
// Update Actions object.
nlohmann::json& updateSvcSimpleUpdate =
@@ -1196,8 +1124,9 @@ inline void
updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] =
std::move(allowed);
- asyncResp->res.jsonValue["HttpPushUriOptions"]["HttpPushUriApplyTime"]
- ["ApplyTime"] = "Immediate";
+ asyncResp->res
+ .jsonValue["HttpPushUriOptions"]["HttpPushUriApplyTime"]["ApplyTime"] =
+ update_service::ApplyTime::Immediate;
}
inline void handleUpdateServiceFirmwareInventoryCollectionGet(
@@ -1263,65 +1192,65 @@ inline void
[asyncResp,
swId](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- const std::string* swInvPurpose = nullptr;
- const std::string* version = nullptr;
+ const std::string* swInvPurpose = nullptr;
+ const std::string* version = nullptr;
- const bool success = sdbusplus::unpackPropertiesNoThrow(
- dbus_utils::UnpackErrorPrinter(), propertiesList, "Purpose",
- swInvPurpose, "Version", version);
+ const bool success = sdbusplus::unpackPropertiesNoThrow(
+ dbus_utils::UnpackErrorPrinter(), propertiesList, "Purpose",
+ swInvPurpose, "Version", version);
- if (!success)
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ if (!success)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- if (swInvPurpose == nullptr)
- {
- BMCWEB_LOG_DEBUG("Can't find property \"Purpose\"!");
- messages::internalError(asyncResp->res);
- return;
- }
+ if (swInvPurpose == nullptr)
+ {
+ BMCWEB_LOG_DEBUG("Can't find property \"Purpose\"!");
+ messages::internalError(asyncResp->res);
+ return;
+ }
- BMCWEB_LOG_DEBUG("swInvPurpose = {}", *swInvPurpose);
+ BMCWEB_LOG_DEBUG("swInvPurpose = {}", *swInvPurpose);
- if (version == nullptr)
- {
- BMCWEB_LOG_DEBUG("Can't find property \"Version\"!");
+ if (version == nullptr)
+ {
+ BMCWEB_LOG_DEBUG("Can't find property \"Version\"!");
- messages::internalError(asyncResp->res);
+ messages::internalError(asyncResp->res);
- return;
- }
- asyncResp->res.jsonValue["Version"] = *version;
- asyncResp->res.jsonValue["Id"] = swId;
-
- // swInvPurpose is of format:
- // xyz.openbmc_project.Software.Version.VersionPurpose.ABC
- // Translate this to "ABC image"
- size_t endDesc = swInvPurpose->rfind('.');
- if (endDesc == std::string::npos)
- {
- messages::internalError(asyncResp->res);
- return;
- }
- endDesc++;
- if (endDesc >= swInvPurpose->size())
- {
- messages::internalError(asyncResp->res);
- return;
- }
+ return;
+ }
+ asyncResp->res.jsonValue["Version"] = *version;
+ asyncResp->res.jsonValue["Id"] = swId;
+
+ // swInvPurpose is of format:
+ // xyz.openbmc_project.Software.Version.VersionPurpose.ABC
+ // Translate this to "ABC image"
+ size_t endDesc = swInvPurpose->rfind('.');
+ if (endDesc == std::string::npos)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ endDesc++;
+ if (endDesc >= swInvPurpose->size())
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
- std::string formatDesc = swInvPurpose->substr(endDesc);
- asyncResp->res.jsonValue["Description"] = formatDesc + " image";
- getRelatedItems(asyncResp, *swInvPurpose);
- });
+ std::string formatDesc = swInvPurpose->substr(endDesc);
+ asyncResp->res.jsonValue["Description"] = formatDesc + " image";
+ getRelatedItems(asyncResp, *swInvPurpose);
+ });
}
inline void handleUpdateServiceFirmwareInventoryGet(
@@ -1345,52 +1274,54 @@ inline void handleUpdateServiceFirmwareInventoryGet(
[asyncResp,
swId](const boost::system::error_code& ec,
const dbus::utility::MapperGetSubTreeResponse& subtree) {
- BMCWEB_LOG_DEBUG("doGet callback...");
- if (ec)
- {
- messages::internalError(asyncResp->res);
- return;
- }
-
- // Ensure we find our input swId, otherwise return an error
- bool found = false;
- for (const std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>&
- obj : subtree)
- {
- if (!obj.first.ends_with(*swId))
+ BMCWEB_LOG_DEBUG("doGet callback...");
+ if (ec)
{
- continue;
+ messages::internalError(asyncResp->res);
+ return;
}
- if (obj.second.empty())
+ // Ensure we find our input swId, otherwise return an error
+ bool found = false;
+ for (const std::pair<std::string,
+ std::vector<std::pair<
+ std::string, std::vector<std::string>>>>&
+ obj : subtree)
{
- continue;
- }
+ if (!obj.first.ends_with(*swId))
+ {
+ continue;
+ }
- found = true;
- sw_util::getSwStatus(asyncResp, swId, obj.second[0].first);
- getSoftwareVersion(asyncResp, obj.second[0].first, obj.first,
- *swId);
- }
- if (!found)
- {
- BMCWEB_LOG_WARNING("Input swID {} not found!", *swId);
- messages::resourceMissingAtURI(
- asyncResp->res,
- boost::urls::format(
- "/redfish/v1/UpdateService/FirmwareInventory/{}", *swId));
- return;
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#SoftwareInventory.v1_1_0.SoftwareInventory";
- asyncResp->res.jsonValue["Name"] = "Software Inventory";
- asyncResp->res.jsonValue["Status"]["HealthRollup"] = "OK";
-
- asyncResp->res.jsonValue["Updateable"] = false;
- sw_util::getSwUpdatableStatus(asyncResp, swId);
- });
+ if (obj.second.empty())
+ {
+ continue;
+ }
+
+ found = true;
+ sw_util::getSwStatus(asyncResp, swId, obj.second[0].first);
+ getSoftwareVersion(asyncResp, obj.second[0].first, obj.first,
+ *swId);
+ }
+ if (!found)
+ {
+ BMCWEB_LOG_WARNING("Input swID {} not found!", *swId);
+ messages::resourceMissingAtURI(
+ asyncResp->res,
+ boost::urls::format(
+ "/redfish/v1/UpdateService/FirmwareInventory/{}",
+ *swId));
+ return;
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#SoftwareInventory.v1_1_0.SoftwareInventory";
+ asyncResp->res.jsonValue["Name"] = "Software Inventory";
+ asyncResp->res.jsonValue["Status"]["HealthRollup"] =
+ resource::Health::OK;
+
+ asyncResp->res.jsonValue["Updateable"] = false;
+ sw_util::getSwUpdatableStatus(asyncResp, swId);
+ });
}
inline void requestRoutesUpdateService(App& app)
diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
index 37fb2045c9..a18f1d03ca 100644
--- a/redfish-core/lib/virtual_media.hpp
+++ b/redfish-core/lib/virtual_media.hpp
@@ -1,17 +1,17 @@
/*
-// Copyright (c) 2018 Intel Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+Copyright (c) 2018 Intel Corporation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
*/
#pragma once
@@ -43,9 +43,8 @@ enum class VmMode
Proxy
};
-inline VmMode
- parseObjectPathAndGetMode(const sdbusplus::message::object_path& itemPath,
- const std::string& resName)
+inline VmMode parseObjectPathAndGetMode(
+ const sdbusplus::message::object_path& itemPath, const std::string& resName)
{
std::string thisPath = itemPath.filename();
BMCWEB_LOG_DEBUG("Filename: {}, ThisPath: {}", itemPath.str, thisPath);
@@ -101,26 +100,26 @@ inline void
[service, resName, asyncResp, handler = std::move(handler)](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG("DBUS response error");
- return;
- }
+ return;
+ }
- for (const auto& item : subtree)
- {
- VmMode mode = parseObjectPathAndGetMode(item.first, resName);
- if (mode != VmMode::Invalid)
+ for (const auto& item : subtree)
{
- handler(service, resName, asyncResp, item);
- return;
+ VmMode mode = parseObjectPathAndGetMode(item.first, resName);
+ if (mode != VmMode::Invalid)
+ {
+ handler(service, resName, asyncResp, item);
+ return;
+ }
}
- }
- BMCWEB_LOG_DEBUG("Parent item not found");
- asyncResp->res.result(boost::beast::http::status::not_found);
- });
+ BMCWEB_LOG_DEBUG("Parent item not found");
+ asyncResp->res.result(boost::beast::http::status::not_found);
+ });
}
/**
@@ -257,9 +256,9 @@ inline nlohmann::json vmItemTemplate(const std::string& name,
item["WriteProtected"] = true;
item["ConnectedVia"] = virtual_media::ConnectedVia::NotConnected;
item["MediaTypes"] = nlohmann::json::array_t({"CD", "USBStick"});
- item["TransferMethod"] = "Stream";
+ item["TransferMethod"] = virtual_media::TransferMethod::Stream;
item["Oem"]["OpenBMC"]["@odata.type"] =
- "#OemVirtualMedia.v1_0_0.VirtualMedia";
+ "#OpenBMCVirtualMedia.v1_0_0.VirtualMedia";
item["Oem"]["OpenBMC"]["@odata.id"] = boost::urls::format(
"/redfish/v1/Managers/{}/VirtualMedia/{}#/Oem/OpenBMC", name, resName);
@@ -281,29 +280,29 @@ inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
[name, asyncResp{std::move(asyncResp)}](
const boost::system::error_code& ec,
const dbus::utility::ManagedObjectType& subtree) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG("DBUS response error");
- return;
- }
- nlohmann::json& members = asyncResp->res.jsonValue["Members"];
- members = nlohmann::json::array();
-
- for (const auto& object : subtree)
- {
- nlohmann::json item;
- std::string path = object.first.filename();
- if (path.empty())
+ if (ec)
{
- continue;
+ BMCWEB_LOG_DEBUG("DBUS response error");
+ return;
}
+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
+ members = nlohmann::json::array();
- item["@odata.id"] = boost::urls::format(
- "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path);
- members.emplace_back(std::move(item));
- }
- asyncResp->res.jsonValue["Members@odata.count"] = members.size();
- });
+ for (const auto& object : subtree)
+ {
+ nlohmann::json item;
+ std::string path = object.first.filename();
+ if (path.empty())
+ {
+ continue;
+ }
+
+ item["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path);
+ members.emplace_back(std::move(item));
+ }
+ asyncResp->res.jsonValue["Members@odata.count"] = members.size();
+ });
}
inline void
@@ -415,9 +414,8 @@ inline std::optional<TransferProtocol> getTransferProtocolFromParam(
* @brief Function extends URI with transfer protocol type.
*
*/
-inline std::string
- getUriWithTransferProtocol(const std::string& imageUri,
- const TransferProtocol& transferProtocol)
+inline std::string getUriWithTransferProtocol(
+ const std::string& imageUri, const TransferProtocol& transferProtocol)
{
if (transferProtocol == TransferProtocol::smb)
{
@@ -474,14 +472,14 @@ inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
// Pass secret over pipe
secretPipe->asyncWrite(
std::move(userName), std::move(password),
- [asyncResp, secretPipe](const boost::system::error_code& ec,
- std::size_t) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Failed to pass secret: {}", ec);
- messages::internalError(asyncResp->res);
- }
- });
+ [asyncResp,
+ secretPipe](const boost::system::error_code& ec, std::size_t) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Failed to pass secret: {}", ec);
+ messages::internalError(asyncResp->res);
+ }
+ });
}
dbus::utility::DbusVariantType unixFd(
@@ -491,20 +489,20 @@ inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
"/xyz/openbmc_project/VirtualMedia/Legacy");
path /= name;
crow::connections::systemBus->async_method_call(
- [asyncResp, secretPipe](const boost::system::error_code& ec,
- bool success) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- if (!success)
- {
- BMCWEB_LOG_ERROR("Service responded with error");
- messages::internalError(asyncResp->res);
- }
- },
+ [asyncResp,
+ secretPipe](const boost::system::error_code& ec, bool success) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ if (!success)
+ {
+ BMCWEB_LOG_ERROR("Service responded with error");
+ messages::internalError(asyncResp->res);
+ }
+ },
service, path.str, "xyz.openbmc_project.VirtualMedia.Legacy", "Mount",
imageUrl, rw, unixFd);
}
@@ -662,14 +660,14 @@ inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
{
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- },
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name,
"xyz.openbmc_project.VirtualMedia.Legacy", "Unmount");
}
@@ -677,14 +675,14 @@ inline void doEjectAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
{
crow::connections::systemBus->async_method_call(
[asyncResp](const boost::system::error_code& ec) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Bad D-Bus request error: {}", ec);
- messages::internalError(asyncResp->res);
- return;
- }
- },
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ },
service, "/xyz/openbmc_project/VirtualMedia/Proxy/" + name,
"xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
}
@@ -726,47 +724,51 @@ inline void handleManagersVirtualMediaActionInsertPost(
[asyncResp, action, actionParams,
resName](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& getObjectType) mutable {
- if (ec)
- {
- BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
- messages::resourceNotFound(asyncResp->res, action, resName);
-
- return;
- }
-
- std::string service = getObjectType.begin()->first;
- BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
-
- sdbusplus::message::object_path path(
- "/xyz/openbmc_project/VirtualMedia");
- dbus::utility::getManagedObjects(
- service, path,
- [service, resName, action, actionParams, asyncResp](
- const boost::system::error_code& ec2,
- const dbus::utility::ManagedObjectType& subtree) mutable {
- if (ec2)
+ if (ec)
{
- // Not possible in proxy mode
- BMCWEB_LOG_DEBUG("InsertMedia not "
- "allowed in proxy mode");
+ BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
messages::resourceNotFound(asyncResp->res, action, resName);
return;
}
- for (const auto& object : subtree)
- {
- VmMode mode = parseObjectPathAndGetMode(object.first, resName);
- if (mode == VmMode::Legacy)
- {
- validateParams(asyncResp, service, resName, actionParams);
- return;
- }
- }
- BMCWEB_LOG_DEBUG("Parent item not found");
- messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
+ std::string service = getObjectType.begin()->first;
+ BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
+
+ sdbusplus::message::object_path path(
+ "/xyz/openbmc_project/VirtualMedia");
+ dbus::utility::getManagedObjects(
+ service, path,
+ [service, resName, action, actionParams, asyncResp](
+ const boost::system::error_code& ec2,
+ const dbus::utility::ManagedObjectType& subtree) mutable {
+ if (ec2)
+ {
+ // Not possible in proxy mode
+ BMCWEB_LOG_DEBUG("InsertMedia not "
+ "allowed in proxy mode");
+ messages::resourceNotFound(asyncResp->res, action,
+ resName);
+
+ return;
+ }
+ for (const auto& object : subtree)
+ {
+ VmMode mode =
+ parseObjectPathAndGetMode(object.first, resName);
+ if (mode == VmMode::Legacy)
+ {
+ validateParams(asyncResp, service, resName,
+ actionParams);
+
+ return;
+ }
+ }
+ BMCWEB_LOG_DEBUG("Parent item not found");
+ messages::resourceNotFound(asyncResp->res, "VirtualMedia",
+ resName);
+ });
});
- });
}
inline void handleManagersVirtualMediaActionEject(
@@ -792,44 +794,48 @@ inline void handleManagersVirtualMediaActionEject(
[asyncResp, action,
resName](const boost::system::error_code& ec2,
const dbus::utility::MapperGetObject& getObjectType) {
- if (ec2)
- {
- BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec2);
- messages::internalError(asyncResp->res);
-
- return;
- }
- std::string service = getObjectType.begin()->first;
- BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
-
- sdbusplus::message::object_path path(
- "/xyz/openbmc_project/VirtualMedia");
- dbus::utility::getManagedObjects(
- service, path,
- [resName, service, action,
- asyncResp](const boost::system::error_code& ec,
- const dbus::utility::ManagedObjectType& subtree) {
- if (ec)
+ if (ec2)
{
- BMCWEB_LOG_ERROR("ObjectMapper : No Service found");
- messages::resourceNotFound(asyncResp->res, action, resName);
+ BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}",
+ ec2);
+ messages::internalError(asyncResp->res);
+
return;
}
+ std::string service = getObjectType.begin()->first;
+ BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
+
+ sdbusplus::message::object_path path(
+ "/xyz/openbmc_project/VirtualMedia");
+ dbus::utility::getManagedObjects(
+ service, path,
+ [resName, service, action,
+ asyncResp](const boost::system::error_code& ec,
+ const dbus::utility::ManagedObjectType& subtree) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("ObjectMapper : No Service found");
+ messages::resourceNotFound(asyncResp->res, action,
+ resName);
+ return;
+ }
- for (const auto& object : subtree)
- {
- VmMode mode = parseObjectPathAndGetMode(object.first, resName);
- if (mode != VmMode::Invalid)
- {
- doEjectAction(asyncResp, service, resName,
- mode == VmMode::Legacy);
- return;
- }
- }
- BMCWEB_LOG_DEBUG("Parent item not found");
- messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName);
+ for (const auto& object : subtree)
+ {
+ VmMode mode =
+ parseObjectPathAndGetMode(object.first, resName);
+ if (mode != VmMode::Invalid)
+ {
+ doEjectAction(asyncResp, service, resName,
+ mode == VmMode::Legacy);
+ return;
+ }
+ }
+ BMCWEB_LOG_DEBUG("Parent item not found");
+ messages::resourceNotFound(asyncResp->res, "VirtualMedia",
+ resName);
+ });
});
- });
}
inline void handleManagersVirtualMediaCollectionGet(
@@ -858,18 +864,18 @@ inline void handleManagersVirtualMediaCollectionGet(
"/xyz/openbmc_project/VirtualMedia", {},
[asyncResp, name](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& getObjectType) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
- messages::internalError(asyncResp->res);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
+ messages::internalError(asyncResp->res);
- return;
- }
- std::string service = getObjectType.begin()->first;
- BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
+ return;
+ }
+ std::string service = getObjectType.begin()->first;
+ BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
- getVmResourceList(asyncResp, service, name);
- });
+ getVmResourceList(asyncResp, service, name);
+ });
}
inline void
@@ -893,18 +899,18 @@ inline void
[asyncResp, name,
resName](const boost::system::error_code& ec,
const dbus::utility::MapperGetObject& getObjectType) {
- if (ec)
- {
- BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
- messages::internalError(asyncResp->res);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("ObjectMapper::GetObject call failed: {}", ec);
+ messages::internalError(asyncResp->res);
- return;
- }
- std::string service = getObjectType.begin()->first;
- BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
+ return;
+ }
+ std::string service = getObjectType.begin()->first;
+ BMCWEB_LOG_DEBUG("GetObjectType: {}", service);
- getVmData(asyncResp, service, name, resName);
- });
+ getVmData(asyncResp, service, name, resName);
+ });
}
inline void requestNBDVirtualMediaRoutes(App& app)