diff options
Diffstat (limited to 'redfish-core/lib')
31 files changed, 11586 insertions, 12249 deletions
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp index 99f126ed14..3d14015704 100644 --- a/redfish-core/lib/account_service.hpp +++ b/redfish-core/lib/account_service.hpp @@ -211,15 +211,15 @@ 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"); @@ -266,16 +266,15 @@ inline void handleRoleMapPatch( crow::connections::systemBus->async_method_call( [asyncResp, roleMapObjData, serverType, index, remoteGroup](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]["RemoteGroup"] = *remoteGroup; + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res + .jsonValue[serverType]["RemoteRoleMapping"][index] + ["RemoteGroup"] = *remoteGroup; }, ldapDbusService, roleMapObjData[index].first, propertyInterface, "Set", @@ -291,16 +290,15 @@ inline void handleRoleMapPatch( crow::connections::systemBus->async_method_call( [asyncResp, roleMapObjData, serverType, index, localRole](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]["LocalRole"] = *localRole; + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res + .jsonValue[serverType]["RemoteRoleMapping"][index] + ["LocalRole"] = *localRole; }, ldapDbusService, roleMapObjData[index].first, propertyInterface, "Set", @@ -347,19 +345,19 @@ 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.push_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.push_back(std::move(roleMapEntry)); }, ldapDbusService, dbusObjectPath, ldapPrivMapperInterface, "Create", *remoteGroup, @@ -384,166 +382,155 @@ inline void getLDAPConfigData(const std::string& ldapType, crow::connections::systemBus->async_method_call( [callback, ldapType](const boost::system::error_code ec, const dbus::utility::MapperGetObject& resp) { - if (ec || resp.empty()) + if (ec || resp.empty()) + { + BMCWEB_LOG_ERROR + << "DBUS response error during getting of service name: " << ec; + LDAPConfigData empty{}; + callback(false, empty, ldapType); + return; + } + std::string service = resp.begin()->first; + crow::connections::systemBus->async_method_call( + [callback, + ldapType](const boost::system::error_code errorCode, + const dbus::utility::ManagedObjectType& ldapObjects) { + LDAPConfigData confData{}; + if (errorCode) { - BMCWEB_LOG_ERROR - << "DBUS response error during getting of service name: " - << ec; - LDAPConfigData empty{}; - callback(false, empty, ldapType); + callback(false, confData, ldapType); + BMCWEB_LOG_ERROR << "D-Bus responses error: " << errorCode; return; } - std::string service = resp.begin()->first; - crow::connections::systemBus->async_method_call( - [callback, ldapType]( - const boost::system::error_code errorCode, - const dbus::utility::ManagedObjectType& ldapObjects) { - LDAPConfigData confData{}; - if (errorCode) - { - callback(false, confData, ldapType); - BMCWEB_LOG_ERROR << "D-Bus responses error: " - << errorCode; - return; - } - std::string ldapDbusType; - std::string searchString; + 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; - } + 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 ldapEnableInterfaceStr = ldapEnableInterface; + std::string ldapConfigInterfaceStr = ldapConfigInterface; - for (const auto& object : ldapObjects) + 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) { - // let's find the object whose ldap type is equal to the - // given type - if (object.first.str.find(searchString) == - std::string::npos) + // rest of the properties are string. + for (const auto& property : interface.second) { - continue; + if (property.first == "Enabled") + { + const bool* value = + std::get_if<bool>(&property.second); + if (value == nullptr) + { + continue; + } + confData.serviceEnabled = *value; + break; + } } + } + else if (interface.first == ldapConfigInterfaceStr) + { - for (const auto& interface : object.second) + for (const auto& property : interface.second) { - if (interface.first == ldapEnableInterfaceStr) + const std::string* strValue = + std::get_if<std::string>(&property.second); + if (strValue == nullptr) { - // 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; - } - } + continue; } - else if (interface.first == ldapConfigInterfaceStr) + if (property.first == "LDAPServerURI") { - - 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; - } - } + confData.uri = *strValue; } - else if ( - interface.first == - "xyz.openbmc_project.User.PrivilegeMapperEntry") + else if (property.first == "LDAPBindDN") { - 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.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 (interface.first == + "xyz.openbmc_project.User.PrivilegeMapperEntry") + { + LDAPRoleMapData roleMapData{}; + for (const auto& property : interface.second) + { + const std::string* strValue = + std::get_if<std::string>(&property.second); - confData.groupRoleList.emplace_back( - object.first.str, roleMapData); + 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); } - callback(true, confData, ldapType); - }, - service, ldapRootObject, dbusObjManagerIntf, - "GetManagedObjects"); + } + } + callback(true, confData, ldapType); + }, + service, ldapRootObject, dbusObjManagerIntf, "GetManagedObjects"); }, mapperBusName, mapperObjectPath, mapperIntf, "GetObject", ldapConfigObjectName, interfaces); @@ -632,25 +619,23 @@ inline void handleServiceAddressPatch( crow::connections::systemBus->async_method_call( [asyncResp, ldapServerElementName, serviceAddressList](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "Error Occurred in updating the service address"; - messages::internalError(asyncResp->res); - return; - } - std::vector<std::string> modifiedserviceAddressList = { - serviceAddressList.front()}; - asyncResp->res - .jsonValue[ldapServerElementName]["ServiceAddresses"] = - modifiedserviceAddressList; - if ((serviceAddressList).size() > 1) - { - messages::propertyValueModified(asyncResp->res, - "ServiceAddresses", - serviceAddressList.front()); - } - BMCWEB_LOG_DEBUG << "Updated the service address"; + if (ec) + { + BMCWEB_LOG_DEBUG + << "Error Occurred in updating the service address"; + messages::internalError(asyncResp->res); + return; + } + std::vector<std::string> modifiedserviceAddressList = { + serviceAddressList.front()}; + asyncResp->res.jsonValue[ldapServerElementName]["ServiceAddresses"] = + modifiedserviceAddressList; + if ((serviceAddressList).size() > 1) + { + messages::propertyValueModified(asyncResp->res, "ServiceAddresses", + serviceAddressList.front()); + } + BMCWEB_LOG_DEBUG << "Updated the service address"; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapConfigInterface, "LDAPServerURI", @@ -674,15 +659,16 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, username, ldapServerElementName](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "Error occurred in updating the username"; - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue[ldapServerElementName]["Authentication"] - ["Username"] = username; - BMCWEB_LOG_DEBUG << "Updated the username"; + if (ec) + { + BMCWEB_LOG_DEBUG << "Error occurred in updating the username"; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res + .jsonValue[ldapServerElementName]["Authentication"]["Username"] = + username; + BMCWEB_LOG_DEBUG << "Updated the username"; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapConfigInterface, "LDAPBindDN", @@ -706,15 +692,16 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, password, ldapServerElementName](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "Error occurred in updating the password"; - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue[ldapServerElementName]["Authentication"] - ["Password"] = ""; - BMCWEB_LOG_DEBUG << "Updated the password"; + if (ec) + { + BMCWEB_LOG_DEBUG << "Error occurred in updating the password"; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res + .jsonValue[ldapServerElementName]["Authentication"]["Password"] = + ""; + BMCWEB_LOG_DEBUG << "Updated the password"; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapConfigInterface, "LDAPBindDNPassword", @@ -739,25 +726,23 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, baseDNList, ldapServerElementName](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "Error Occurred in Updating the base DN"; - messages::internalError(asyncResp->res); - return; - } - auto& serverTypeJson = - asyncResp->res.jsonValue[ldapServerElementName]; - auto& searchSettingsJson = - serverTypeJson["LDAPService"]["SearchSettings"]; - std::vector<std::string> modifiedBaseDNList = {baseDNList.front()}; - searchSettingsJson["BaseDistinguishedNames"] = modifiedBaseDNList; - if (baseDNList.size() > 1) - { - messages::propertyValueModified(asyncResp->res, - "BaseDistinguishedNames", - baseDNList.front()); - } - BMCWEB_LOG_DEBUG << "Updated the base DN"; + if (ec) + { + BMCWEB_LOG_DEBUG << "Error Occurred in Updating the base DN"; + messages::internalError(asyncResp->res); + return; + } + auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName]; + auto& searchSettingsJson = + serverTypeJson["LDAPService"]["SearchSettings"]; + std::vector<std::string> modifiedBaseDNList = {baseDNList.front()}; + searchSettingsJson["BaseDistinguishedNames"] = modifiedBaseDNList; + if (baseDNList.size() > 1) + { + messages::propertyValueModified( + asyncResp->res, "BaseDistinguishedNames", baseDNList.front()); + } + BMCWEB_LOG_DEBUG << "Updated the base DN"; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapConfigInterface, "LDAPBaseDN", @@ -781,19 +766,18 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, userNameAttribute, ldapServerElementName](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "Error Occurred in Updating the " - "username attribute"; - messages::internalError(asyncResp->res); - return; - } - auto& serverTypeJson = - asyncResp->res.jsonValue[ldapServerElementName]; - auto& searchSettingsJson = - serverTypeJson["LDAPService"]["SearchSettings"]; - searchSettingsJson["UsernameAttribute"] = userNameAttribute; - BMCWEB_LOG_DEBUG << "Updated the user name attr."; + if (ec) + { + BMCWEB_LOG_DEBUG << "Error Occurred in Updating the " + "username attribute"; + messages::internalError(asyncResp->res); + return; + } + auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName]; + auto& searchSettingsJson = + serverTypeJson["LDAPService"]["SearchSettings"]; + searchSettingsJson["UsernameAttribute"] = userNameAttribute; + BMCWEB_LOG_DEBUG << "Updated the user name attr."; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapConfigInterface, "UserNameAttribute", @@ -817,19 +801,18 @@ inline void handleGroupNameAttrPatch( crow::connections::systemBus->async_method_call( [asyncResp, groupsAttribute, ldapServerElementName](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "Error Occurred in Updating the " - "groupname attribute"; - messages::internalError(asyncResp->res); - return; - } - auto& serverTypeJson = - asyncResp->res.jsonValue[ldapServerElementName]; - auto& searchSettingsJson = - serverTypeJson["LDAPService"]["SearchSettings"]; - searchSettingsJson["GroupsAttribute"] = groupsAttribute; - BMCWEB_LOG_DEBUG << "Updated the groupname attr"; + if (ec) + { + BMCWEB_LOG_DEBUG << "Error Occurred in Updating the " + "groupname attribute"; + messages::internalError(asyncResp->res); + return; + } + auto& serverTypeJson = asyncResp->res.jsonValue[ldapServerElementName]; + auto& searchSettingsJson = + serverTypeJson["LDAPService"]["SearchSettings"]; + searchSettingsJson["GroupsAttribute"] = groupsAttribute; + BMCWEB_LOG_DEBUG << "Updated the groupname attr"; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapConfigInterface, "GroupNameAttribute", @@ -852,16 +835,15 @@ inline void handleServiceEnablePatch( crow::connections::systemBus->async_method_call( [asyncResp, serviceEnabled, ldapServerElementName](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "Error Occurred in Updating the service enable"; - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue[ldapServerElementName]["ServiceEnabled"] = - serviceEnabled; - BMCWEB_LOG_DEBUG << "Updated Service enable = " << serviceEnabled; + if (ec) + { + BMCWEB_LOG_DEBUG << "Error Occurred in Updating the service enable"; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue[ldapServerElementName]["ServiceEnabled"] = + serviceEnabled; + BMCWEB_LOG_DEBUG << "Updated Service enable = " << serviceEnabled; }, ldapDbusService, ldapConfigObject, propertyInterface, "Set", ldapEnableInterface, "Enabled", @@ -1048,13 +1030,12 @@ inline void handleLDAPPatch(nlohmann::json& input, // Get the existing resource first then keep modifying // whenever any property gets updated. - getLDAPConfigData(serverType, [asyncResp, userName, password, baseDNList, - userNameAttribute, groupsAttribute, - serviceAddressList, serviceEnabled, - dbusObjectPath, remoteRoleMapData]( - bool success, - const LDAPConfigData& confData, - const std::string& serverT) { + getLDAPConfigData( + serverType, + [asyncResp, userName, password, baseDNList, userNameAttribute, + groupsAttribute, serviceAddressList, serviceEnabled, dbusObjectPath, + remoteRoleMapData](bool success, const LDAPConfigData& confData, + const std::string& serverT) { if (!success) { messages::internalError(asyncResp->res); @@ -1121,7 +1102,7 @@ inline void handleLDAPPatch(nlohmann::json& input, handleRoleMapPatch(asyncResp, confData.groupRoleList, serverT, *remoteRoleMapData); } - }); + }); } inline void updateUserProperties(std::shared_ptr<bmcweb::AsyncResp> asyncResp, @@ -1140,120 +1121,120 @@ inline void updateUserProperties(std::shared_ptr<bmcweb::AsyncResp> asyncResp, [dbusObjectPath, username, password(std::move(password)), roleId(std::move(roleId)), enabled, locked, asyncResp{std::move(asyncResp)}](int rc) { - if (rc <= 0) + if (rc <= 0) + { + messages::resourceNotFound(asyncResp->res, + "#ManagerAccount.v1_4_0.ManagerAccount", + username); + return; + } + + if (password) + { + int retval = pamUpdatePassword(username, *password); + + if (retval == PAM_USER_UNKNOWN) { messages::resourceNotFound( asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", username); + } + else if (retval == PAM_AUTHTOK_ERR) + { + // If password is invalid + messages::propertyValueFormatError(asyncResp->res, *password, + "Password"); + BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; + } + else if (retval != PAM_SUCCESS) + { + messages::internalError(asyncResp->res); return; } - - if (password) + else { - int retval = pamUpdatePassword(username, *password); + messages::success(asyncResp->res); + } + } - if (retval == PAM_USER_UNKNOWN) - { - messages::resourceNotFound( - asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", - username); - } - else if (retval == PAM_AUTHTOK_ERR) - { - // If password is invalid - messages::propertyValueFormatError(asyncResp->res, - *password, "Password"); - BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; - } - else if (retval != PAM_SUCCESS) + if (enabled) + { + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; messages::internalError(asyncResp->res); return; } - else - { - messages::success(asyncResp->res); - } - } + messages::success(asyncResp->res); + return; + }, + "xyz.openbmc_project.User.Manager", dbusObjectPath, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.User.Attributes", "UserEnabled", + dbus::utility::DbusVariantType{*enabled}); + } - if (enabled) + if (roleId) + { + std::string priv = getPrivilegeFromRoleId(*roleId); + if (priv.empty()) { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); - return; - }, - "xyz.openbmc_project.User.Manager", dbusObjectPath, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.User.Attributes", "UserEnabled", - dbus::utility::DbusVariantType{*enabled}); + messages::propertyValueNotInList(asyncResp->res, *roleId, + "RoleId"); + return; } - - if (roleId) + if (priv == "priv-noaccess") { - std::string priv = getPrivilegeFromRoleId(*roleId); - if (priv.empty()) + priv = ""; + } + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) { - messages::propertyValueNotInList(asyncResp->res, *roleId, - "RoleId"); + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); return; } - if (priv == "priv-noaccess") - { - priv = ""; - } + messages::success(asyncResp->res); + }, + "xyz.openbmc_project.User.Manager", dbusObjectPath, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.User.Attributes", "UserPrivilege", + dbus::utility::DbusVariantType{priv}); + } - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); - }, - "xyz.openbmc_project.User.Manager", dbusObjectPath, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.User.Attributes", "UserPrivilege", - dbus::utility::DbusVariantType{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) + { + messages::propertyValueNotInList(asyncResp->res, "true", + "Locked"); + return; } - 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) + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) { - messages::propertyValueNotInList(asyncResp->res, "true", - "Locked"); + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); return; } - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); - return; - }, - "xyz.openbmc_project.User.Manager", dbusObjectPath, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.User.Attributes", - "UserLockedForFailedAttempt", - dbus::utility::DbusVariantType{*locked}); - } + messages::success(asyncResp->res); + return; + }, + "xyz.openbmc_project.User.Manager", dbusObjectPath, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.User.Attributes", + "UserLockedForFailedAttempt", + dbus::utility::DbusVariantType{*locked}); + } }); } @@ -1262,123 +1243,121 @@ inline void requestAccountServiceRoutes(App& app) BMCWEB_ROUTE(app, "/redfish/v1/AccountService/") .privileges(redfish::privileges::getAccountService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) -> void { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app]( + const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -> void { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + const persistent_data::AuthConfigMethods& authMethodsConfig = + persistent_data::SessionStore::getInstance() + .getAuthMethodsConfig(); + + nlohmann::json& json = asyncResp->res.jsonValue; + json["@odata.id"] = "/redfish/v1/AccountService"; + json["@odata.type"] = "#AccountService." + "v1_10_0.AccountService"; + json["Id"] = "AccountService"; + json["Name"] = "Account Service"; + json["Description"] = "Account Service"; + json["ServiceEnabled"] = true; + json["MaxPasswordLength"] = 20; + json["Accounts"]["@odata.id"] = + "/redfish/v1/AccountService/Accounts"; + json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles"; + json["Oem"]["OpenBMC"]["@odata.type"] = + "#OemAccountService.v1_0_0.AccountService"; + json["Oem"]["OpenBMC"]["@odata.id"] = + "/redfish/v1/AccountService#/Oem/OpenBMC"; + json["Oem"]["OpenBMC"]["AuthMethods"]["BasicAuth"] = + authMethodsConfig.basic; + json["Oem"]["OpenBMC"]["AuthMethods"]["SessionToken"] = + authMethodsConfig.sessionToken; + json["Oem"]["OpenBMC"]["AuthMethods"]["XToken"] = + authMethodsConfig.xtoken; + json["Oem"]["OpenBMC"]["AuthMethods"]["Cookie"] = + authMethodsConfig.cookie; + json["Oem"]["OpenBMC"]["AuthMethods"]["TLS"] = + authMethodsConfig.tls; + + // /redfish/v1/AccountService/LDAP/Certificates is something + // only ConfigureManager can access then only display when the + // user has permissions ConfigureManager + Privileges effectiveUserPrivileges = + redfish::getUserPrivileges(req.userRole); + + if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, + effectiveUserPrivileges)) + { + asyncResp->res + .jsonValue["LDAP"]["Certificates"]["@odata.id"] = + "/redfish/v1/AccountService/LDAP/Certificates"; + } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const dbus::utility::DBusPropertiesMap& + propertiesList) { + if (ec) { + messages::internalError(asyncResp->res); return; } - const persistent_data::AuthConfigMethods& authMethodsConfig = - persistent_data::SessionStore::getInstance() - .getAuthMethodsConfig(); - - nlohmann::json& json = asyncResp->res.jsonValue; - json["@odata.id"] = "/redfish/v1/AccountService"; - json["@odata.type"] = "#AccountService." - "v1_10_0.AccountService"; - json["Id"] = "AccountService"; - json["Name"] = "Account Service"; - json["Description"] = "Account Service"; - json["ServiceEnabled"] = true; - json["MaxPasswordLength"] = 20; - json["Accounts"]["@odata.id"] = - "/redfish/v1/AccountService/Accounts"; - json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles"; - json["Oem"]["OpenBMC"]["@odata.type"] = - "#OemAccountService.v1_0_0.AccountService"; - json["Oem"]["OpenBMC"]["@odata.id"] = - "/redfish/v1/AccountService#/Oem/OpenBMC"; - json["Oem"]["OpenBMC"]["AuthMethods"]["BasicAuth"] = - authMethodsConfig.basic; - json["Oem"]["OpenBMC"]["AuthMethods"]["SessionToken"] = - authMethodsConfig.sessionToken; - json["Oem"]["OpenBMC"]["AuthMethods"]["XToken"] = - authMethodsConfig.xtoken; - json["Oem"]["OpenBMC"]["AuthMethods"]["Cookie"] = - authMethodsConfig.cookie; - json["Oem"]["OpenBMC"]["AuthMethods"]["TLS"] = - authMethodsConfig.tls; - - // /redfish/v1/AccountService/LDAP/Certificates is something only - // ConfigureManager can access then only display when the user has - // permissions ConfigureManager - Privileges effectiveUserPrivileges = - redfish::getUserPrivileges(req.userRole); - - if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, - effectiveUserPrivileges)) + BMCWEB_LOG_DEBUG << "Got " << propertiesList.size() + << "properties for AccountService"; + for (const std::pair<std::string, dbus::utility::DbusVariantType>& + property : propertiesList) { - asyncResp->res.jsonValue["LDAP"]["Certificates"]["@odata.id"] = - "/redfish/v1/AccountService/LDAP/Certificates"; - } - crow::connections::systemBus->async_method_call( - [asyncResp]( - const boost::system::error_code ec, - const dbus::utility::DBusPropertiesMap& propertiesList) { - if (ec) + if (property.first == "MinPasswordLength") + { + const uint8_t* value = + std::get_if<uint8_t>(&property.second); + if (value != nullptr) { - messages::internalError(asyncResp->res); - return; + asyncResp->res.jsonValue["MinPasswordLength"] = *value; } - BMCWEB_LOG_DEBUG << "Got " << propertiesList.size() - << "properties for AccountService"; - for (const std::pair<std::string, - dbus::utility::DbusVariantType>& - property : propertiesList) + } + if (property.first == "AccountUnlockTimeout") + { + const uint32_t* value = + std::get_if<uint32_t>(&property.second); + if (value != nullptr) { - if (property.first == "MinPasswordLength") - { - const uint8_t* value = - std::get_if<uint8_t>(&property.second); - if (value != nullptr) - { - asyncResp->res.jsonValue["MinPasswordLength"] = - *value; - } - } - if (property.first == "AccountUnlockTimeout") - { - const uint32_t* value = - std::get_if<uint32_t>(&property.second); - if (value != nullptr) - { - asyncResp->res - .jsonValue["AccountLockoutDuration"] = - *value; - } - } - if (property.first == "MaxLoginAttemptBeforeLockout") - { - const uint16_t* value = - std::get_if<uint16_t>(&property.second); - if (value != nullptr) - { - asyncResp->res - .jsonValue["AccountLockoutThreshold"] = - *value; - } - } + asyncResp->res.jsonValue["AccountLockoutDuration"] = + *value; } - }, - "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.User.AccountPolicy"); - - auto callback = [asyncResp](bool success, LDAPConfigData& confData, - const std::string& ldapType) { - if (!success) + } + if (property.first == "MaxLoginAttemptBeforeLockout") { - return; + const uint16_t* value = + std::get_if<uint16_t>(&property.second); + if (value != nullptr) + { + asyncResp->res.jsonValue["AccountLockoutThreshold"] = + *value; + } } - parseLDAPConfigData(asyncResp->res.jsonValue, confData, - ldapType); - }; + } + }, + "xyz.openbmc_project.User.Manager", + "/xyz/openbmc_project/user", + "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.User.AccountPolicy"); - getLDAPConfigData("LDAP", callback); - getLDAPConfigData("ActiveDirectory", callback); - }); + auto callback = + [asyncResp](bool success, LDAPConfigData& confData, + const std::string& ldapType) { + if (!success) + { + return; + } + parseLDAPConfigData(asyncResp->res.jsonValue, confData, ldapType); + }; + + getLDAPConfigData("LDAP", callback); + getLDAPConfigData("ActiveDirectory", callback); + }); BMCWEB_ROUTE(app, "/redfish/v1/AccountService/") .privileges(redfish::privileges::patchAccountService) @@ -1414,12 +1393,12 @@ inline void requestAccountServiceRoutes(App& app) { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); }, "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", @@ -1468,12 +1447,12 @@ inline void requestAccountServiceRoutes(App& app) { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); }, "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", @@ -1486,12 +1465,12 @@ inline void requestAccountServiceRoutes(App& app) { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); }, "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", @@ -1533,52 +1512,48 @@ inline void requestAccountServiceRoutes(App& app) [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()) - { - messages::internalError(asyncResp->res); - BMCWEB_LOG_ERROR << "Invalid firmware ID"; + for (const auto& userpath : users) + { + 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"] = - "/redfish/v1/AccountService/Accounts/" + - user; - memberArray.push_back(std::move(member)); - } - } - asyncResp->res.jsonValue["Members@odata.count"] = - memberArray.size(); + // 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"] = + "/redfish/v1/AccountService/Accounts/" + user; + memberArray.push_back(std::move(member)); + } + } + asyncResp->res.jsonValue["Members@odata.count"] = + memberArray.size(); }, "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", @@ -1587,300 +1562,282 @@ inline void requestAccountServiceRoutes(App& app) BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/") .privileges(redfish::privileges::postManagerAccountCollection) - .methods( - boost::beast::http::verb::post)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) -> void { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::string username; - std::string password; - std::optional<std::string> roleId("User"); - std::optional<bool> enabled = true; - if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", - username, "Password", password, - "RoleId", roleId, "Enabled", enabled)) + .methods(boost::beast::http::verb::post)( + [&app]( + const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) -> void { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string username; + std::string password; + std::optional<std::string> roleId("User"); + std::optional<bool> enabled = true; + if (!json_util::readJsonPatch( + req, asyncResp->res, "UserName", username, "Password", + password, "RoleId", roleId, "Enabled", enabled)) + { + return; + } + + std::string priv = getPrivilegeFromRoleId(*roleId); + if (priv.empty()) + { + messages::propertyValueNotInList(asyncResp->res, *roleId, + "RoleId"); + return; + } + // TODO: Following override will be reverted once support in + // phosphor-user-manager is added. In order to avoid dependency + // issues, this is added in bmcweb, which will removed, once + // phosphor-user-manager supports priv-noaccess. + if (priv == "priv-noaccess") + { + roleId = ""; + } + else + { + roleId = priv; + } + + // Reading AllGroups property + sdbusplus::asio::getProperty<std::vector<std::string>>( + *crow::connections::systemBus, + "xyz.openbmc_project.User.Manager", + "/xyz/openbmc_project/user", + "xyz.openbmc_project.User.Manager", "AllGroups", + [asyncResp, username, password{std::move(password)}, roleId, + enabled](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; } - std::string priv = getPrivilegeFromRoleId(*roleId); - if (priv.empty()) + if (allGroupsList.empty()) { - messages::propertyValueNotInList(asyncResp->res, *roleId, - "RoleId"); + messages::internalError(asyncResp->res); return; } - // TODO: Following override will be reverted once support in - // phosphor-user-manager is added. In order to avoid dependency - // issues, this is added in bmcweb, which will removed, once - // phosphor-user-manager supports priv-noaccess. - if (priv == "priv-noaccess") - { - roleId = ""; - } - else - { - roleId = priv; - } - // Reading AllGroups property - sdbusplus::asio::getProperty<std::vector<std::string>>( - *crow::connections::systemBus, - "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", - "xyz.openbmc_project.User.Manager", "AllGroups", - [asyncResp, username, password{std::move(password)}, roleId, - enabled](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; - } + crow::connections::systemBus->async_method_call( + [asyncResp, username, + password](const boost::system::error_code ec2, + sdbusplus::message::message& m) { + if (ec2) + { + userErrorMessageHandler(m.get_error(), asyncResp, username, + ""); + return; + } - if (allGroupsList.empty()) - { - messages::internalError(asyncResp->res); - return; - } + if (pamUpdatePassword(username, password) != PAM_SUCCESS) + { + // At this point we have a user that's been + // created, but the password set + // failed.Something is wrong, so delete the user + // that we've already created + sdbusplus::message::object_path tempObjPath( + rootUserDbusPath); + tempObjPath /= username; + const std::string userPath(tempObjPath); crow::connections::systemBus->async_method_call( - [asyncResp, username, - password](const boost::system::error_code ec2, - sdbusplus::message::message& m) { - if (ec2) - { - userErrorMessageHandler( - m.get_error(), asyncResp, username, ""); - return; - } - - if (pamUpdatePassword(username, password) != - PAM_SUCCESS) - { - // At this point we have a user that's been - // created, but the password set - // failed.Something is wrong, so delete the user - // that we've already created - sdbusplus::message::object_path tempObjPath( - rootUserDbusPath); - tempObjPath /= username; - const std::string userPath(tempObjPath); - - crow::connections::systemBus->async_method_call( - [asyncResp, password]( - const boost::system::error_code ec3) { - if (ec3) - { - messages::internalError( - asyncResp->res); - return; - } - - // If password is invalid - messages::propertyValueFormatError( - asyncResp->res, password, - "Password"); - }, - "xyz.openbmc_project.User.Manager", - userPath, - "xyz.openbmc_project.Object.Delete", - "Delete"); - - BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; - return; - } + [asyncResp, + password](const boost::system::error_code ec3) { + if (ec3) + { + messages::internalError(asyncResp->res); + return; + } - messages::created(asyncResp->res); - asyncResp->res.addHeader( - "Location", - "/redfish/v1/AccountService/Accounts/" + - username); + // If password is invalid + messages::propertyValueFormatError( + asyncResp->res, password, "Password"); }, - "xyz.openbmc_project.User.Manager", - "/xyz/openbmc_project/user", - "xyz.openbmc_project.User.Manager", "CreateUser", - username, allGroupsList, *roleId, *enabled); - }); - }); + "xyz.openbmc_project.User.Manager", userPath, + "xyz.openbmc_project.Object.Delete", "Delete"); + + BMCWEB_LOG_ERROR << "pamUpdatePassword Failed"; + return; + } + + messages::created(asyncResp->res); + asyncResp->res.addHeader( + "Location", + "/redfish/v1/AccountService/Accounts/" + username); + }, + "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", + "xyz.openbmc_project.User.Manager", "CreateUser", username, + allGroupsList, *roleId, *enabled); + }); + }); BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/") .privileges(redfish::privileges::getManagerAccount) - .methods( - boost::beast::http::verb:: - get)([&app]([[maybe_unused]] const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& accountName) -> void { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } + .methods(boost::beast::http::verb::get)( + [&app]([[maybe_unused]] const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& accountName) -> void { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } #ifdef BMCWEB_INSECURE_DISABLE_AUTHX - // If authentication is disabled, there are no user accounts - messages::resourceNotFound(asyncResp->res, - "#ManagerAccount.v1_4_0.ManagerAccount", - accountName); - return; + // If authentication is disabled, there are no user accounts + messages::resourceNotFound( + asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", + accountName); + return; #endif // BMCWEB_INSECURE_DISABLE_AUTHX - if (req.session == nullptr) - { - messages::internalError(asyncResp->res); - return; - } - if (req.session->username != accountName) - { - // At this point we've determined that the user is trying to - // modify a user that isn't them. We need to verify that they - // have permissions to modify other users, so re-run the auth - // check with the same permissions, minus ConfigureSelf. - Privileges effectiveUserPrivileges = - redfish::getUserPrivileges(req.userRole); - Privileges requiredPermissionsToChangeNonSelf = { - "ConfigureUsers", "ConfigureManager"}; - if (!effectiveUserPrivileges.isSupersetOf( - requiredPermissionsToChangeNonSelf)) + if (req.session == nullptr) { - BMCWEB_LOG_DEBUG << "GET Account denied access"; - messages::insufficientPrivilege(asyncResp->res); + messages::internalError(asyncResp->res); return; } - } - - crow::connections::systemBus->async_method_call( - [asyncResp, - accountName](const boost::system::error_code ec, - const dbus::utility::ManagedObjectType& users) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - const auto userIt = std::find_if( - users.begin(), users.end(), - [accountName]( - const std::pair<sdbusplus::message::object_path, - dbus::utility::DBusInteracesMap>& - user) { - return accountName == user.first.filename(); - }); - - if (userIt == users.end()) + if (req.session->username != accountName) + { + // At this point we've determined that the user is trying to + // modify a user that isn't them. We need to verify that + // they have permissions to modify other users, so re-run + // the auth check with the same permissions, minus + // ConfigureSelf. + Privileges effectiveUserPrivileges = + redfish::getUserPrivileges(req.userRole); + Privileges requiredPermissionsToChangeNonSelf = { + "ConfigureUsers", "ConfigureManager"}; + if (!effectiveUserPrivileges.isSupersetOf( + requiredPermissionsToChangeNonSelf)) { - messages::resourceNotFound( - asyncResp->res, "ManagerAccount", accountName); + BMCWEB_LOG_DEBUG << "GET Account denied access"; + messages::insufficientPrivilege(asyncResp->res); return; } + } + + crow::connections::systemBus->async_method_call( + [asyncResp, accountName]( + const boost::system::error_code ec, + const dbus::utility::ManagedObjectType& users) { + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + const auto userIt = std::find_if( + users.begin(), users.end(), + [accountName]( + const std::pair<sdbusplus::message::object_path, + dbus::utility::DBusInteracesMap>& user) { + return accountName == user.first.filename(); + }); - asyncResp->res.jsonValue["@odata.type"] = - "#ManagerAccount.v1_4_0.ManagerAccount"; - asyncResp->res.jsonValue["Name"] = "User Account"; - asyncResp->res.jsonValue["Description"] = "User Account"; - asyncResp->res.jsonValue["Password"] = nullptr; - asyncResp->res.jsonValue["AccountTypes"] = {"Redfish"}; + if (userIt == users.end()) + { + messages::resourceNotFound(asyncResp->res, "ManagerAccount", + accountName); + return; + } + + asyncResp->res.jsonValue["@odata.type"] = + "#ManagerAccount.v1_4_0.ManagerAccount"; + asyncResp->res.jsonValue["Name"] = "User Account"; + asyncResp->res.jsonValue["Description"] = "User Account"; + asyncResp->res.jsonValue["Password"] = nullptr; + asyncResp->res.jsonValue["AccountTypes"] = {"Redfish"}; - for (const auto& interface : userIt->second) + for (const auto& interface : userIt->second) + { + if (interface.first == "xyz.openbmc_project.User.Attributes") + { + for (const auto& property : interface.second) { - if (interface.first == - "xyz.openbmc_project.User.Attributes") + if (property.first == "UserEnabled") { - for (const auto& property : interface.second) + const bool* userEnabled = + std::get_if<bool>(&property.second); + if (userEnabled == nullptr) { - 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") - { - 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; - asyncResp->res.jsonValue - ["Locked@Redfish.AllowableValues"] = { - "false"}; // can only unlock accounts - } - else if (property.first == "UserPrivilege") - { - 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"] = - "/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; - } - asyncResp->res - .jsonValue["PasswordChangeRequired"] = - *userPasswordExpired; - } + BMCWEB_LOG_ERROR << "UserEnabled wasn't a bool"; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue["Enabled"] = *userEnabled; + } + else if (property.first == "UserLockedForFailedAttempt") + { + 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; + asyncResp->res + .jsonValue["Locked@Redfish.AllowableValues"] = { + "false"}; // can only unlock accounts + } + else if (property.first == "UserPrivilege") + { + 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"] = + "/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; + } + asyncResp->res.jsonValue["PasswordChangeRequired"] = + *userPasswordExpired; } } + } + } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/AccountService/Accounts/" + accountName; - asyncResp->res.jsonValue["Id"] = accountName; - asyncResp->res.jsonValue["UserName"] = accountName; - }, - "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", - "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); - }); + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/AccountService/Accounts/" + accountName; + asyncResp->res.jsonValue["Id"] = accountName; + asyncResp->res.jsonValue["UserName"] = accountName; + }, + "xyz.openbmc_project.User.Manager", + "/xyz/openbmc_project/user", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + }); BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/") // TODO this privilege should be using the generated endpoints, but @@ -1965,15 +1922,15 @@ inline void requestAccountServiceRoutes(App& app) newUser{std::string(*newUserName)}, locked](const boost::system::error_code ec, sdbusplus::message::message& 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); + updateUserProperties(asyncResp, newUser, password, enabled, roleId, + locked); }, "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user", @@ -2006,16 +1963,15 @@ inline void requestAccountServiceRoutes(App& app) crow::connections::systemBus->async_method_call( [asyncResp, username](const boost::system::error_code ec) { - if (ec) - { - messages::resourceNotFound( - asyncResp->res, - "#ManagerAccount.v1_4_0.ManagerAccount", - username); - return; - } + if (ec) + { + messages::resourceNotFound( + asyncResp->res, "#ManagerAccount.v1_4_0.ManagerAccount", + username); + return; + } - messages::accountRemoved(asyncResp->res); + messages::accountRemoved(asyncResp->res); }, "xyz.openbmc_project.User.Manager", userPath, "xyz.openbmc_project.Object.Delete", "Delete"); diff --git a/redfish-core/lib/bios.hpp b/redfish-core/lib/bios.hpp index 084c846891..59cb2b30c2 100644 --- a/redfish-core/lib/bios.hpp +++ b/redfish-core/lib/bios.hpp @@ -56,12 +56,12 @@ 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 6ab87a8b31..f9a48b4071 100644 --- a/redfish-core/lib/cable.hpp +++ b/redfish-core/lib/cable.hpp @@ -87,7 +87,7 @@ inline void [asyncResp]( const boost::system::error_code ec, const dbus::utility::DBusPropertiesMap& properties) { - fillCableProperties(asyncResp->res, ec, properties); + fillCableProperties(asyncResp->res, ec, properties); }, service, cableObjectPath, "org.freedesktop.DBus.Properties", "GetAll", interface); @@ -106,61 +106,57 @@ 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->res)) + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "Cable Id: " << cableId; + auto respHandler = + [asyncResp, + cableId](const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec.value() == EBADR) + { + messages::resourceNotFound(asyncResp->res, + "#Cable.v1_0_0.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) { - return; + continue; } - BMCWEB_LOG_DEBUG << "Cable Id: " << cableId; - auto respHandler = - [asyncResp, - cableId](const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& - subtree) { - if (ec.value() == EBADR) - { - messages::resourceNotFound( - asyncResp->res, "#Cable.v1_0_0.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) - { - continue; - } - - asyncResp->res.jsonValue["@odata.type"] = - "#Cable.v1_0_0.Cable"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Cables/" + cableId; - asyncResp->res.jsonValue["Id"] = cableId; - asyncResp->res.jsonValue["Name"] = "Cable"; - - getCableProperties(asyncResp, objectPath, - serviceMap); - return; - } - messages::resourceNotFound(asyncResp->res, "Cable", - cableId); - }; - - crow::connections::systemBus->async_method_call( - respHandler, "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", 0, - std::array<const char*, 1>{ - "xyz.openbmc_project.Inventory.Item.Cable"}); - }); + + asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Cables/" + cableId; + asyncResp->res.jsonValue["Id"] = cableId; + asyncResp->res.jsonValue["Name"] = "Cable"; + + getCableProperties(asyncResp, objectPath, serviceMap); + return; + } + messages::resourceNotFound(asyncResp->res, "Cable", cableId); + }; + + crow::connections::systemBus->async_method_call( + respHandler, "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", 0, + std::array<const char*, 1>{ + "xyz.openbmc_project.Inventory.Item.Cable"}); + }); } /** @@ -173,21 +169,20 @@ 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->res)) - { - 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"; - - collection_util::getCollectionMembers( - asyncResp, "/redfish/v1/Cables", - {"xyz.openbmc_project.Inventory.Item.Cable"}); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"; + + collection_util::getCollectionMembers( + asyncResp, "/redfish/v1/Cables", + {"xyz.openbmc_project.Inventory.Item.Cable"}); + }); } } // namespace redfish diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp index 4ac3762d0f..efd18ea1d7 100644 --- a/redfish-core/lib/certificate_service.hpp +++ b/redfish-core/lib/certificate_service.hpp @@ -46,44 +46,42 @@ inline void requestRoutesCertificateService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") .privileges(redfish::privileges::getCertificateService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - 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->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#CertificateService.v1_0_0.CertificateService"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/CertificateService"; - asyncResp->res.jsonValue["Id"] = "CertificateService"; - asyncResp->res.jsonValue["Name"] = "Certificate Service"; - asyncResp->res.jsonValue["Description"] = - "Actions available to manage certificates"; - // /redfish/v1/CertificateService/CertificateLocations is something - // only ConfigureManager can access then only display when the user - // has permissions ConfigureManager - Privileges effectiveUserPrivileges = - redfish::getUserPrivileges(req.userRole); - if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, - effectiveUserPrivileges)) - { - asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = - "/redfish/v1/CertificateService/CertificateLocations"; - } - asyncResp->res - .jsonValue["Actions"] - ["#CertificateService.ReplaceCertificate"] = { - {"target", - "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, - {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; - asyncResp->res - .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { - {"target", - "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; + asyncResp->res.jsonValue["@odata.type"] = + "#CertificateService.v1_0_0.CertificateService"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/CertificateService"; + asyncResp->res.jsonValue["Id"] = "CertificateService"; + asyncResp->res.jsonValue["Name"] = "Certificate Service"; + asyncResp->res.jsonValue["Description"] = + "Actions available to manage certificates"; + // /redfish/v1/CertificateService/CertificateLocations is something + // only ConfigureManager can access then only display when the user + // has permissions ConfigureManager + Privileges effectiveUserPrivileges = + redfish::getUserPrivileges(req.userRole); + if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, + effectiveUserPrivileges)) + { + asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = + "/redfish/v1/CertificateService/CertificateLocations"; + } + asyncResp->res + .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { + {"target", + "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, + {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; + asyncResp->res + .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { + {"target", + "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; }); } // requestRoutesCertificateService @@ -222,21 +220,21 @@ static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 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; + 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"); } @@ -250,251 +248,243 @@ inline void requestRoutesCertificateActionGenerateCSR(App& app) app, "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") .privileges(redfish::privileges::postCertificateService) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + static const int rsaKeyBitLength = 2048; + + // Required parameters + std::string city; + std::string commonName; + std::string country; + std::string organization; + std::string organizationalUnit; + std::string state; + nlohmann::json certificateCollection; + + // Optional parameters + std::optional<std::vector<std::string>> optAlternativeNames = + std::vector<std::string>(); + std::optional<std::string> optContactPerson = ""; + std::optional<std::string> optChallengePassword = ""; + std::optional<std::string> optEmail = ""; + std::optional<std::string> optGivenName = ""; + std::optional<std::string> optInitials = ""; + std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; + std::optional<std::string> optKeyCurveId = "secp384r1"; + std::optional<std::string> optKeyPairAlgorithm = "EC"; + std::optional<std::vector<std::string>> optKeyUsage = + std::vector<std::string>(); + std::optional<std::string> optSurname = ""; + std::optional<std::string> optUnstructuredName = ""; + if (!json_util::readJsonAction( + req, asyncResp->res, "City", city, "CommonName", commonName, + "ContactPerson", optContactPerson, "Country", country, + "Organization", organization, "OrganizationalUnit", + organizationalUnit, "State", state, "CertificateCollection", + certificateCollection, "AlternativeNames", optAlternativeNames, + "ChallengePassword", optChallengePassword, "Email", optEmail, + "GivenName", optGivenName, "Initials", optInitials, + "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, + "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", + optKeyUsage, "Surname", optSurname, "UnstructuredName", + optUnstructuredName)) + { + return; + } + + // bmcweb has no way to store or decode a private key challenge + // password, which will likely cause bmcweb to crash on startup + // if this is not set on a post so not allowing the user to set + // value + if (!optChallengePassword->empty()) + { + messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", + "ChallengePassword"); + return; + } + + std::string certURI; + if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, + "@odata.id", certURI)) + { + return; + } + + std::string objectPath; + std::string service; + if (boost::starts_with( + certURI, + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) + { + objectPath = certs::httpsObjectPath; + service = certs::httpsServiceName; + } + else if (boost::starts_with( + certURI, "/redfish/v1/AccountService/LDAP/Certificates")) + { + objectPath = certs::ldapObjectPath; + service = certs::ldapServiceName; + } + else + { + messages::actionParameterNotSupported( + asyncResp->res, "CertificateCollection", "GenerateCSR"); + return; + } + + // supporting only EC and RSA algorithm + if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") + { + messages::actionParameterNotSupported( + asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); + return; + } + + // supporting only 2048 key bit length for RSA algorithm due to + // time consumed in generating private key + if (*optKeyPairAlgorithm == "RSA" && + *optKeyBitLength != rsaKeyBitLength) + { + messages::propertyValueNotInList(asyncResp->res, + std::to_string(*optKeyBitLength), + "KeyBitLength"); + return; + } + + // validate KeyUsage supporting only 1 type based on URL + if (boost::starts_with( + certURI, + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) + { + if (optKeyUsage->empty()) { - return; + optKeyUsage->push_back("ServerAuthentication"); } - static const int rsaKeyBitLength = 2048; - - // Required parameters - std::string city; - std::string commonName; - std::string country; - std::string organization; - std::string organizationalUnit; - std::string state; - nlohmann::json certificateCollection; - - // Optional parameters - std::optional<std::vector<std::string>> optAlternativeNames = - std::vector<std::string>(); - std::optional<std::string> optContactPerson = ""; - std::optional<std::string> optChallengePassword = ""; - std::optional<std::string> optEmail = ""; - std::optional<std::string> optGivenName = ""; - std::optional<std::string> optInitials = ""; - std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; - std::optional<std::string> optKeyCurveId = "secp384r1"; - std::optional<std::string> optKeyPairAlgorithm = "EC"; - std::optional<std::vector<std::string>> optKeyUsage = - std::vector<std::string>(); - std::optional<std::string> optSurname = ""; - std::optional<std::string> optUnstructuredName = ""; - if (!json_util::readJsonAction( - req, asyncResp->res, "City", city, "CommonName", commonName, - "ContactPerson", optContactPerson, "Country", country, - "Organization", organization, "OrganizationalUnit", - organizationalUnit, "State", state, "CertificateCollection", - certificateCollection, "AlternativeNames", - optAlternativeNames, "ChallengePassword", - optChallengePassword, "Email", optEmail, "GivenName", - optGivenName, "Initials", optInitials, "KeyBitLength", - optKeyBitLength, "KeyCurveId", optKeyCurveId, - "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", - optKeyUsage, "Surname", optSurname, "UnstructuredName", - optUnstructuredName)) + else if (optKeyUsage->size() == 1) { - return; + if ((*optKeyUsage)[0] != "ServerAuthentication") + { + messages::propertyValueNotInList( + asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); + return; + } } - - // bmcweb has no way to store or decode a private key challenge - // password, which will likely cause bmcweb to crash on startup - // if this is not set on a post so not allowing the user to set - // value - if (!optChallengePassword->empty()) + else { messages::actionParameterNotSupported( - asyncResp->res, "GenerateCSR", "ChallengePassword"); + asyncResp->res, "KeyUsage", "GenerateCSR"); return; } - - std::string certURI; - if (!redfish::json_util::readJson(certificateCollection, - asyncResp->res, "@odata.id", - certURI)) - { - return; - } - - std::string objectPath; - std::string service; - if (boost::starts_with( - certURI, - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) + } + else if (boost::starts_with( + certURI, "/redfish/v1/AccountService/LDAP/Certificates")) + { + if (optKeyUsage->empty()) { - objectPath = certs::httpsObjectPath; - service = certs::httpsServiceName; + optKeyUsage->push_back("ClientAuthentication"); } - else if (boost::starts_with( - certURI, - "/redfish/v1/AccountService/LDAP/Certificates")) + else if (optKeyUsage->size() == 1) { - objectPath = certs::ldapObjectPath; - service = certs::ldapServiceName; + if ((*optKeyUsage)[0] != "ClientAuthentication") + { + messages::propertyValueNotInList( + asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); + return; + } } else { messages::actionParameterNotSupported( - asyncResp->res, "CertificateCollection", "GenerateCSR"); + asyncResp->res, "KeyUsage", "GenerateCSR"); return; } + } + + // Only allow one CSR matcher at a time so setting retry + // time-out and timer expiry to 10 seconds for now. + static const int timeOut = 10; + if (csrMatcher) + { + messages::serviceTemporarilyUnavailable(asyncResp->res, + std::to_string(timeOut)); + return; + } - // supporting only EC and RSA algorithm - if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") + // Make this static so it survives outside this method + static boost::asio::steady_timer timeout(*req.ioService); + timeout.expires_after(std::chrono::seconds(timeOut)); + timeout.async_wait([asyncResp](const boost::system::error_code& ec) { + csrMatcher = nullptr; + if (ec) { - messages::actionParameterNotSupported( - asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); + // operation_aborted is expected if timer is canceled + // before completion. + if (ec != boost::asio::error::operation_aborted) + { + BMCWEB_LOG_ERROR << "Async_wait failed " << ec; + } return; } + BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; + messages::internalError(asyncResp->res); + }); - // supporting only 2048 key bit length for RSA algorithm due to - // time consumed in generating private key - if (*optKeyPairAlgorithm == "RSA" && - *optKeyBitLength != rsaKeyBitLength) + // create a matcher to wait on CSR object + BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; + std::string match("type='signal'," + "interface='org.freedesktop.DBus.ObjectManager'," + "path='" + + objectPath + + "'," + "member='InterfacesAdded'"); + csrMatcher = std::make_unique<sdbusplus::bus::match::match>( + *crow::connections::systemBus, match, + [asyncResp, service, objectPath, + certURI](sdbusplus::message::message& m) { + timeout.cancel(); + if (m.is_method_error()) { - messages::propertyValueNotInList( - asyncResp->res, std::to_string(*optKeyBitLength), - "KeyBitLength"); + BMCWEB_LOG_ERROR << "Dbus method error!!!"; + messages::internalError(asyncResp->res); return; } - // validate KeyUsage supporting only 1 type based on URL - if (boost::starts_with( - certURI, - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) - { - if (optKeyUsage->empty()) - { - optKeyUsage->push_back("ServerAuthentication"); - } - else if (optKeyUsage->size() == 1) - { - if ((*optKeyUsage)[0] != "ServerAuthentication") - { - messages::propertyValueNotInList( - asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); - return; - } - } - else - { - messages::actionParameterNotSupported( - asyncResp->res, "KeyUsage", "GenerateCSR"); - return; - } - } - else if (boost::starts_with( - certURI, - "/redfish/v1/AccountService/LDAP/Certificates")) + dbus::utility::DBusInteracesMap interfacesProperties; + + sdbusplus::message::object_path csrObjectPath; + m.read(csrObjectPath, interfacesProperties); + BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; + for (auto& interface : interfacesProperties) { - if (optKeyUsage->empty()) + if (interface.first == "xyz.openbmc_project.Certs.CSR") { - optKeyUsage->push_back("ClientAuthentication"); - } - else if (optKeyUsage->size() == 1) - { - if ((*optKeyUsage)[0] != "ClientAuthentication") - { - messages::propertyValueNotInList( - asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); - return; - } - } - else - { - messages::actionParameterNotSupported( - asyncResp->res, "KeyUsage", "GenerateCSR"); - return; + getCSR(asyncResp, certURI, service, objectPath, + csrObjectPath.str); + break; } } - - // Only allow one CSR matcher at a time so setting retry - // time-out and timer expiry to 10 seconds for now. - static const int timeOut = 10; - if (csrMatcher) + }); + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const std::string&) { + if (ec) { - messages::serviceTemporarilyUnavailable( - asyncResp->res, std::to_string(timeOut)); + BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); + messages::internalError(asyncResp->res); return; } - - // Make this static so it survives outside this method - static boost::asio::steady_timer timeout(*req.ioService); - timeout.expires_after(std::chrono::seconds(timeOut)); - timeout.async_wait( - [asyncResp](const boost::system::error_code& ec) { - csrMatcher = nullptr; - if (ec) - { - // operation_aborted is expected if timer is canceled - // before completion. - if (ec != boost::asio::error::operation_aborted) - { - BMCWEB_LOG_ERROR << "Async_wait failed " << ec; - } - return; - } - BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; - messages::internalError(asyncResp->res); - }); - - // create a matcher to wait on CSR object - BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; - std::string match("type='signal'," - "interface='org.freedesktop.DBus.ObjectManager'," - "path='" + - objectPath + - "'," - "member='InterfacesAdded'"); - csrMatcher = std::make_unique<sdbusplus::bus::match::match>( - *crow::connections::systemBus, match, - [asyncResp, service, objectPath, - certURI](sdbusplus::message::message& m) { - timeout.cancel(); - if (m.is_method_error()) - { - BMCWEB_LOG_ERROR << "Dbus method error!!!"; - messages::internalError(asyncResp->res); - return; - } - - dbus::utility::DBusInteracesMap interfacesProperties; - - sdbusplus::message::object_path csrObjectPath; - m.read(csrObjectPath, interfacesProperties); - BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; - for (auto& interface : interfacesProperties) - { - 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; - } - }, - service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", - "GenerateCSR", *optAlternativeNames, *optChallengePassword, - city, commonName, *optContactPerson, country, *optEmail, - *optGivenName, *optInitials, *optKeyBitLength, *optKeyCurveId, - *optKeyPairAlgorithm, *optKeyUsage, organization, - organizationalUnit, state, *optSurname, *optUnstructuredName); + }, + service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", + "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, + commonName, *optContactPerson, country, *optEmail, *optGivenName, + *optInitials, *optKeyBitLength, *optKeyCurveId, + *optKeyPairAlgorithm, *optKeyUsage, organization, + organizationalUnit, state, *optSurname, *optUnstructuredName); }); } // requestRoutesCertificateActionGenerateCSR @@ -586,88 +576,85 @@ 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, name, - std::to_string(certId)); - return; - } - asyncResp->res.jsonValue["@odata.id"] = certURL; - asyncResp->res.jsonValue["@odata.type"] = - "#Certificate.v1_0_0.Certificate"; - asyncResp->res.jsonValue["Id"] = std::to_string(certId); - asyncResp->res.jsonValue["Name"] = name; - asyncResp->res.jsonValue["Description"] = name; - for (const auto& property : properties) + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::resourceNotFound(asyncResp->res, name, + std::to_string(certId)); + return; + } + asyncResp->res.jsonValue["@odata.id"] = certURL; + asyncResp->res.jsonValue["@odata.type"] = + "#Certificate.v1_0_0.Certificate"; + asyncResp->res.jsonValue["Id"] = std::to_string(certId); + asyncResp->res.jsonValue["Name"] = name; + asyncResp->res.jsonValue["Description"] = name; + for (const auto& property : properties) + { + if (property.first == "CertificateString") { - if (property.first == "CertificateString") + asyncResp->res.jsonValue["CertificateString"] = ""; + const std::string* value = + std::get_if<std::string>(&property.second); + if (value != nullptr) { - asyncResp->res.jsonValue["CertificateString"] = ""; - const std::string* value = - std::get_if<std::string>(&property.second); - if (value != nullptr) - { - asyncResp->res.jsonValue["CertificateString"] = *value; - } + asyncResp->res.jsonValue["CertificateString"] = *value; } - else if (property.first == "KeyUsage") + } + else if (property.first == "KeyUsage") + { + nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"]; + keyUsage = nlohmann::json::array(); + const std::vector<std::string>* value = + std::get_if<std::vector<std::string>>(&property.second); + if (value != nullptr) { - nlohmann::json& keyUsage = - asyncResp->res.jsonValue["KeyUsage"]; - keyUsage = nlohmann::json::array(); - const std::vector<std::string>* value = - std::get_if<std::vector<std::string>>(&property.second); - if (value != nullptr) + for (const std::string& usage : *value) { - for (const std::string& usage : *value) - { - keyUsage.push_back(usage); - } + keyUsage.push_back(usage); } } - else if (property.first == "Issuer") + } + else if (property.first == "Issuer") + { + const std::string* value = + std::get_if<std::string>(&property.second); + if (value != nullptr) { - const std::string* value = - std::get_if<std::string>(&property.second); - if (value != nullptr) - { - updateCertIssuerOrSubject( - asyncResp->res.jsonValue["Issuer"], *value); - } + updateCertIssuerOrSubject( + asyncResp->res.jsonValue["Issuer"], *value); } - else if (property.first == "Subject") + } + else if (property.first == "Subject") + { + const std::string* value = + std::get_if<std::string>(&property.second); + if (value != nullptr) { - const std::string* value = - std::get_if<std::string>(&property.second); - if (value != nullptr) - { - updateCertIssuerOrSubject( - asyncResp->res.jsonValue["Subject"], *value); - } + updateCertIssuerOrSubject( + asyncResp->res.jsonValue["Subject"], *value); } - else if (property.first == "ValidNotAfter") + } + else if (property.first == "ValidNotAfter") + { + const uint64_t* value = std::get_if<uint64_t>(&property.second); + if (value != nullptr) { - const uint64_t* value = - std::get_if<uint64_t>(&property.second); - if (value != nullptr) - { - asyncResp->res.jsonValue["ValidNotAfter"] = - crow::utility::getDateTimeUint(*value); - } + asyncResp->res.jsonValue["ValidNotAfter"] = + crow::utility::getDateTimeUint(*value); } - else if (property.first == "ValidNotBefore") + } + else if (property.first == "ValidNotBefore") + { + const uint64_t* value = std::get_if<uint64_t>(&property.second); + if (value != nullptr) { - const uint64_t* value = - std::get_if<uint64_t>(&property.second); - if (value != nullptr) - { - asyncResp->res.jsonValue["ValidNotBefore"] = - crow::utility::getDateTimeUint(*value); - } + asyncResp->res.jsonValue["ValidNotBefore"] = + crow::utility::getDateTimeUint(*value); } } - asyncResp->res.addHeader("Location", certURL); + } + asyncResp->res.addHeader("Location", certURL); }, service, objectPath, certs::dbusPropIntf, "GetAll", certs::certPropIntf); @@ -682,121 +669,118 @@ inline void requestRoutesCertificateActionsReplaceCertificate(App& app) app, "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") .privileges(redfish::privileges::postCertificateService) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::string certificate; - nlohmann::json certificateUri; - std::optional<std::string> certificateType = "PEM"; - - if (!json_util::readJsonAction(req, asyncResp->res, - "CertificateString", certificate, - "CertificateUri", certificateUri, - "CertificateType", certificateType)) - { - BMCWEB_LOG_ERROR << "Required parameters are missing"; - messages::internalError(asyncResp->res); - return; - } + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string certificate; + nlohmann::json certificateUri; + std::optional<std::string> certificateType = "PEM"; + + if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString", + certificate, "CertificateUri", + certificateUri, "CertificateType", + certificateType)) + { + BMCWEB_LOG_ERROR << "Required parameters are missing"; + messages::internalError(asyncResp->res); + return; + } - if (!certificateType) - { - // should never happen, but it never hurts to be paranoid. - return; - } - if (certificateType != "PEM") - { - messages::actionParameterNotSupported( - asyncResp->res, "CertificateType", "ReplaceCertificate"); - return; - } + if (!certificateType) + { + // should never happen, but it never hurts to be paranoid. + return; + } + if (certificateType != "PEM") + { + messages::actionParameterNotSupported( + asyncResp->res, "CertificateType", "ReplaceCertificate"); + return; + } - std::string certURI; - if (!redfish::json_util::readJson(certificateUri, asyncResp->res, - "@odata.id", certURI)) - { - messages::actionParameterMissing( - asyncResp->res, "ReplaceCertificate", "CertificateUri"); - return; - } + std::string certURI; + if (!redfish::json_util::readJson(certificateUri, asyncResp->res, + "@odata.id", certURI)) + { + messages::actionParameterMissing( + asyncResp->res, "ReplaceCertificate", "CertificateUri"); + return; + } - BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; - long id = getIDFromURL(certURI); - if (id < 0) - { - messages::actionParameterValueFormatError( - asyncResp->res, certURI, "CertificateUri", - "ReplaceCertificate"); - return; - } - std::string objectPath; - std::string name; - std::string service; - if (boost::starts_with( - certURI, - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) - { - objectPath = std::string(certs::httpsObjectPath) + "/" + - std::to_string(id); - name = "HTTPS certificate"; - service = certs::httpsServiceName; - } - else if (boost::starts_with( - certURI, - "/redfish/v1/AccountService/LDAP/Certificates/")) - { - objectPath = std::string(certs::ldapObjectPath) + "/" + - std::to_string(id); - name = "LDAP certificate"; - service = certs::ldapServiceName; - } - else if (boost::starts_with( - certURI, - "/redfish/v1/Managers/bmc/Truststore/Certificates/")) - { - objectPath = std::string(certs::authorityObjectPath) + "/" + - std::to_string(id); - name = "TrustStore certificate"; - service = certs::authorityServiceName; - } - else + BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; + long id = getIDFromURL(certURI); + if (id < 0) + { + messages::actionParameterValueFormatError(asyncResp->res, certURI, + "CertificateUri", + "ReplaceCertificate"); + return; + } + std::string objectPath; + std::string name; + std::string service; + if (boost::starts_with( + certURI, + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) + { + objectPath = + std::string(certs::httpsObjectPath) + "/" + std::to_string(id); + name = "HTTPS certificate"; + service = certs::httpsServiceName; + } + else if (boost::starts_with( + certURI, "/redfish/v1/AccountService/LDAP/Certificates/")) + { + objectPath = + std::string(certs::ldapObjectPath) + "/" + std::to_string(id); + name = "LDAP certificate"; + service = certs::ldapServiceName; + } + else if (boost::starts_with( + certURI, + "/redfish/v1/Managers/bmc/Truststore/Certificates/")) + { + objectPath = std::string(certs::authorityObjectPath) + "/" + + std::to_string(id); + name = "TrustStore certificate"; + service = certs::authorityServiceName; + } + else + { + messages::actionParameterNotSupported( + asyncResp->res, "CertificateUri", "ReplaceCertificate"); + return; + } + + std::shared_ptr<CertificateFile> certFile = + std::make_shared<CertificateFile>(certificate); + crow::connections::systemBus->async_method_call( + [asyncResp, certFile, objectPath, service, certURI, id, + name](const boost::system::error_code ec) { + if (ec) { - messages::actionParameterNotSupported( - asyncResp->res, "CertificateUri", "ReplaceCertificate"); + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + if (ec.value() == + boost::system::linux_error::bad_request_descriptor) + { + messages::resourceNotFound(asyncResp->res, name, + std::to_string(id)); + return; + } + messages::internalError(asyncResp->res); return; } - - std::shared_ptr<CertificateFile> certFile = - std::make_shared<CertificateFile>(certificate); - crow::connections::systemBus->async_method_call( - [asyncResp, certFile, objectPath, service, certURI, 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) - { - messages::resourceNotFound(asyncResp->res, name, - std::to_string(id)); - return; - } - messages::internalError(asyncResp->res); - return; - } - getCertificateProperties(asyncResp, objectPath, service, id, - certURI, name); - BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" - << certFile->getCertFilePath(); - }, - service, objectPath, certs::certReplaceIntf, "Replace", - certFile->getCertFilePath()); + getCertificateProperties(asyncResp, objectPath, service, id, + certURI, name); + BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" + << certFile->getCertFilePath(); + }, + service, objectPath, certs::certReplaceIntf, "Replace", + certFile->getCertFilePath()); }); } // requestRoutesCertificateActionsReplaceCertificate @@ -849,112 +833,105 @@ inline void requestRoutesHTTPSCertificateCollection(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") .privileges(redfish::privileges::getCertificateCollection) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"; + asyncResp->res.jsonValue["@odata.type"] = + "#CertificateCollection.CertificateCollection"; + asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection"; + asyncResp->res.jsonValue["Description"] = + "A Collection of HTTPS certificate instances"; + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const dbus::utility::ManagedObjectType& certs) { + if (ec) { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); return; } - - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"; - asyncResp->res.jsonValue["@odata.type"] = - "#CertificateCollection.CertificateCollection"; - asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection"; - asyncResp->res.jsonValue["Description"] = - "A Collection of HTTPS certificate instances"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, - const dbus::utility::ManagedObjectType& certs) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - nlohmann::json& members = - asyncResp->res.jsonValue["Members"]; - members = nlohmann::json::array(); - for (const auto& cert : certs) - { - long id = getIDFromURL(cert.first.str); - if (id >= 0) - { - nlohmann::json::object_t member; - member["@odata.id"] = - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + - std::to_string(id); - members.push_back(std::move(member)); - } - } - asyncResp->res.jsonValue["Members@odata.count"] = - members.size(); - }, - certs::httpsServiceName, certs::httpsObjectPath, - certs::dbusObjManagerIntf, "GetManagedObjects"); + nlohmann::json& members = asyncResp->res.jsonValue["Members"]; + members = nlohmann::json::array(); + for (const auto& cert : certs) + { + long id = getIDFromURL(cert.first.str); + if (id >= 0) + { + nlohmann::json::object_t member; + member["@odata.id"] = + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + + std::to_string(id); + members.push_back(std::move(member)); + } + } + asyncResp->res.jsonValue["Members@odata.count"] = members.size(); + }, + certs::httpsServiceName, certs::httpsObjectPath, + certs::dbusObjManagerIntf, "GetManagedObjects"); }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") .privileges(redfish::privileges::postCertificateCollection) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; + + asyncResp->res.jsonValue["Name"] = "HTTPS Certificate"; + asyncResp->res.jsonValue["Description"] = "HTTPS Certificate"; + + std::string certFileBody = getCertificateFromReqBody(asyncResp, req); - asyncResp->res.jsonValue["Name"] = "HTTPS Certificate"; - asyncResp->res.jsonValue["Description"] = "HTTPS Certificate"; + if (certFileBody.empty()) + { + BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; + messages::unrecognizedRequestBody(asyncResp->res); + return; + } - std::string certFileBody = - getCertificateFromReqBody(asyncResp, req); + std::shared_ptr<CertificateFile> certFile = + std::make_shared<CertificateFile>(certFileBody); - if (certFileBody.empty()) + crow::connections::systemBus->async_method_call( + [asyncResp, certFile](const boost::system::error_code ec, + const std::string& objectPath) { + if (ec) { - BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; - messages::unrecognizedRequestBody(asyncResp->res); + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); return; } - - std::shared_ptr<CertificateFile> certFile = - std::make_shared<CertificateFile>(certFileBody); - - 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; - } - long certId = getIDFromURL(objectPath); - if (certId < 0) - { - BMCWEB_LOG_ERROR << "Invalid objectPath value" - << objectPath; - messages::internalError(asyncResp->res); - return; - } - std::string certURL = - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + - std::to_string(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()); + long certId = getIDFromURL(objectPath); + if (certId < 0) + { + BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; + messages::internalError(asyncResp->res); + return; + } + std::string certURL = + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + + std::to_string(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()); }); } // requestRoutesHTTPSCertificateCollection @@ -977,27 +954,26 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, certURL](const boost::system::error_code ec, const dbus::utility::ManagedObjectType& certs) { - if (ec) - { - BMCWEB_LOG_WARNING - << "Certificate collection query failed: " << ec - << ", skipping " << certURL; - return; - } - nlohmann::json& links = - asyncResp->res.jsonValue["Links"]["Certificates"]; - for (const auto& cert : certs) + if (ec) + { + BMCWEB_LOG_WARNING << "Certificate collection query failed: " << ec + << ", skipping " << certURL; + return; + } + nlohmann::json& links = + asyncResp->res.jsonValue["Links"]["Certificates"]; + for (const auto& cert : certs) + { + long id = getIDFromURL(cert.first.str); + if (id >= 0) { - long id = getIDFromURL(cert.first.str); - if (id >= 0) - { - nlohmann::json::object_t link; - link["@odata.id"] = certURL + std::to_string(id); - links.push_back(std::move(link)); - } + nlohmann::json::object_t link; + link["@odata.id"] = certURL + std::to_string(id); + links.push_back(std::move(link)); } - asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = - links.size(); + } + asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = + links.size(); }, service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); } @@ -1010,37 +986,36 @@ inline void requestRoutesCertificateLocations(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") .privileges(redfish::privileges::getCertificateLocations) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/CertificateService/CertificateLocations"; - asyncResp->res.jsonValue["@odata.type"] = - "#CertificateLocations.v1_0_0.CertificateLocations"; - asyncResp->res.jsonValue["Name"] = "Certificate Locations"; - asyncResp->res.jsonValue["Id"] = "CertificateLocations"; - asyncResp->res.jsonValue["Description"] = - "Defines a resource that an administrator can use in order to " - "locate all certificates installed on a given service"; - - nlohmann::json& links = - asyncResp->res.jsonValue["Links"]["Certificates"]; - links = nlohmann::json::array(); - getCertificateLocations( - asyncResp, - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", - certs::httpsObjectPath, certs::httpsServiceName); - getCertificateLocations( - asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/", - certs::ldapObjectPath, certs::ldapServiceName); - getCertificateLocations( - asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", - certs::authorityObjectPath, certs::authorityServiceName); + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/CertificateService/CertificateLocations"; + asyncResp->res.jsonValue["@odata.type"] = + "#CertificateLocations.v1_0_0.CertificateLocations"; + asyncResp->res.jsonValue["Name"] = "Certificate Locations"; + asyncResp->res.jsonValue["Id"] = "CertificateLocations"; + asyncResp->res.jsonValue["Description"] = + "Defines a resource that an administrator can use in order to " + "locate all certificates installed on a given service"; + + nlohmann::json& links = + asyncResp->res.jsonValue["Links"]["Certificates"]; + links = nlohmann::json::array(); + getCertificateLocations( + asyncResp, + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", + certs::httpsObjectPath, certs::httpsServiceName); + getCertificateLocations(asyncResp, + "/redfish/v1/AccountService/LDAP/Certificates/", + certs::ldapObjectPath, certs::ldapServiceName); + getCertificateLocations( + asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", + certs::authorityObjectPath, certs::authorityServiceName); }); } // requestRoutesCertificateLocations @@ -1052,54 +1027,51 @@ inline void requestRoutesLDAPCertificateCollection(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") .privileges(redfish::privileges::getCertificateCollection) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/AccountService/LDAP/Certificates"; + asyncResp->res.jsonValue["@odata.type"] = + "#CertificateCollection.CertificateCollection"; + asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection"; + asyncResp->res.jsonValue["Description"] = + "A Collection of LDAP certificate instances"; + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const dbus::utility::ManagedObjectType& certs) { + nlohmann::json& members = asyncResp->res.jsonValue["Members"]; + nlohmann::json& count = + asyncResp->res.jsonValue["Members@odata.count"]; + members = nlohmann::json::array(); + count = 0; + if (ec) { + BMCWEB_LOG_WARNING << "LDAP certificate query failed: " << ec; return; } - - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/AccountService/LDAP/Certificates"; - asyncResp->res.jsonValue["@odata.type"] = - "#CertificateCollection.CertificateCollection"; - asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection"; - asyncResp->res.jsonValue["Description"] = - "A Collection of LDAP certificate instances"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, - const dbus::utility::ManagedObjectType& certs) { - nlohmann::json& members = - asyncResp->res.jsonValue["Members"]; - nlohmann::json& count = - asyncResp->res.jsonValue["Members@odata.count"]; - members = nlohmann::json::array(); - count = 0; - if (ec) - { - BMCWEB_LOG_WARNING << "LDAP certificate query failed: " - << ec; - return; - } - for (const auto& cert : certs) - { - long id = getIDFromURL(cert.first.str); - if (id >= 0) - { - nlohmann::json::object_t member; - member["@odata.id"] = - "/redfish/v1/AccountService/LDAP/Certificates/" + - std::to_string(id); - members.push_back(std::move(member)); - } - } - count = members.size(); - }, - certs::ldapServiceName, certs::ldapObjectPath, - certs::dbusObjManagerIntf, "GetManagedObjects"); + for (const auto& cert : certs) + { + long id = getIDFromURL(cert.first.str); + if (id >= 0) + { + nlohmann::json::object_t member; + member["@odata.id"] = + "/redfish/v1/AccountService/LDAP/Certificates/" + + std::to_string(id); + members.push_back(std::move(member)); + } + } + count = members.size(); + }, + certs::ldapServiceName, certs::ldapObjectPath, + certs::dbusObjManagerIntf, "GetManagedObjects"); }); BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") @@ -1107,54 +1079,50 @@ inline void requestRoutesLDAPCertificateCollection(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->res)) - { - return; - } - std::string certFileBody = - getCertificateFromReqBody(asyncResp, req); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string certFileBody = getCertificateFromReqBody(asyncResp, req); - if (certFileBody.empty()) - { - BMCWEB_LOG_ERROR - << "Cannot get certificate from request body."; - messages::unrecognizedRequestBody(asyncResp->res); - return; - } + if (certFileBody.empty()) + { + BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; + messages::unrecognizedRequestBody(asyncResp->res); + return; + } - std::shared_ptr<CertificateFile> certFile = - std::make_shared<CertificateFile>(certFileBody); - - 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; - } - long certId = getIDFromURL(objectPath); - if (certId < 0) - { - BMCWEB_LOG_ERROR << "Invalid objectPath value" - << objectPath; - messages::internalError(asyncResp->res); - return; - } - std::string certURL = - "/redfish/v1/AccountService/LDAP/Certificates/" + - std::to_string(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()); - }); + std::shared_ptr<CertificateFile> certFile = + std::make_shared<CertificateFile>(certFileBody); + + 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; + } + long certId = getIDFromURL(objectPath); + if (certId < 0) + { + BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; + messages::internalError(asyncResp->res); + return; + } + std::string certURL = + "/redfish/v1/AccountService/LDAP/Certificates/" + + std::to_string(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()); + }); } // requestRoutesLDAPCertificateCollection /** @@ -1169,29 +1137,26 @@ inline void requestRoutesLDAPCertificate(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string&) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - long id = getIDFromURL(req.url); - if (id < 0) - { - BMCWEB_LOG_ERROR << "Invalid url value" << req.url; - messages::internalError(asyncResp->res); - return; - } - BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" - << std::to_string(id); - std::string certURL = - "/redfish/v1/AccountService/LDAP/Certificates/" + - std::to_string(id); - std::string objectPath = certs::ldapObjectPath; - objectPath += "/"; - objectPath += std::to_string(id); - getCertificateProperties(asyncResp, objectPath, - certs::ldapServiceName, id, certURL, - "LDAP Certificate"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + long id = getIDFromURL(req.url); + if (id < 0) + { + BMCWEB_LOG_ERROR << "Invalid url value" << req.url; + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); + std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + + std::to_string(id); + std::string objectPath = certs::ldapObjectPath; + objectPath += "/"; + objectPath += std::to_string(id); + getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, + id, certURL, "LDAP Certificate"); + }); } // requestRoutesLDAPCertificate /** * Collection of TrustStoreCertificate certificates @@ -1200,107 +1165,99 @@ inline void requestRoutesTrustStoreCertificateCollection(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") .privileges(redfish::privileges::getCertificate) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/Truststore/Certificates/"; + asyncResp->res.jsonValue["@odata.type"] = + "#CertificateCollection.CertificateCollection"; + asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection"; + asyncResp->res.jsonValue["Description"] = + "A Collection of TrustStore certificate instances"; + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const dbus::utility::ManagedObjectType& certs) { + if (ec) { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); return; } - - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/Truststore/Certificates/"; - asyncResp->res.jsonValue["@odata.type"] = - "#CertificateCollection.CertificateCollection"; - asyncResp->res.jsonValue["Name"] = - "TrustStore Certificates Collection"; - asyncResp->res.jsonValue["Description"] = - "A Collection of TrustStore certificate instances"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, - const dbus::utility::ManagedObjectType& certs) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - nlohmann::json& members = - asyncResp->res.jsonValue["Members"]; - members = nlohmann::json::array(); - for (const auto& cert : certs) - { - long id = getIDFromURL(cert.first.str); - if (id >= 0) - { - nlohmann::json::object_t member; - member["@odata.id"] = - "/redfish/v1/Managers/bmc/Truststore/Certificates/" + - std::to_string(id); - members.push_back(std::move(member)); - } - } - asyncResp->res.jsonValue["Members@odata.count"] = - members.size(); - }, - certs::authorityServiceName, certs::authorityObjectPath, - certs::dbusObjManagerIntf, "GetManagedObjects"); + nlohmann::json& members = asyncResp->res.jsonValue["Members"]; + members = nlohmann::json::array(); + for (const auto& cert : certs) + { + long id = getIDFromURL(cert.first.str); + if (id >= 0) + { + nlohmann::json::object_t member; + member["@odata.id"] = + "/redfish/v1/Managers/bmc/Truststore/Certificates/" + + std::to_string(id); + members.push_back(std::move(member)); + } + } + asyncResp->res.jsonValue["Members@odata.count"] = members.size(); + }, + certs::authorityServiceName, certs::authorityObjectPath, + certs::dbusObjManagerIntf, "GetManagedObjects"); }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") .privileges(redfish::privileges::postCertificateCollection) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string certFileBody = getCertificateFromReqBody(asyncResp, req); + + if (certFileBody.empty()) + { + BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; + messages::unrecognizedRequestBody(asyncResp->res); + return; + } + + std::shared_ptr<CertificateFile> certFile = + std::make_shared<CertificateFile>(certFileBody); + 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; } - std::string certFileBody = - getCertificateFromReqBody(asyncResp, req); - - if (certFileBody.empty()) + long certId = getIDFromURL(objectPath); + if (certId < 0) { - BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; - messages::unrecognizedRequestBody(asyncResp->res); + BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; + messages::internalError(asyncResp->res); return; } + std::string certURL = + "/redfish/v1/Managers/bmc/Truststore/Certificates/" + + std::to_string(certId); - std::shared_ptr<CertificateFile> certFile = - std::make_shared<CertificateFile>(certFileBody); - 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; - } - long certId = getIDFromURL(objectPath); - if (certId < 0) - { - BMCWEB_LOG_ERROR << "Invalid objectPath value" - << objectPath; - messages::internalError(asyncResp->res); - return; - } - std::string certURL = - "/redfish/v1/Managers/bmc/Truststore/Certificates/" + - std::to_string(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()); + 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()); }); } // requestRoutesTrustStoreCertificateCollection @@ -1316,29 +1273,29 @@ inline void requestRoutesTrustStoreCertificate(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string&) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - long id = getIDFromURL(req.url); - if (id < 0) - { - BMCWEB_LOG_ERROR << "Invalid url value" << req.url; - messages::internalError(asyncResp->res); - return; - } - BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" - << std::to_string(id); - std::string certURL = - "/redfish/v1/Managers/bmc/Truststore/Certificates/" + - std::to_string(id); - std::string objectPath = certs::authorityObjectPath; - objectPath += "/"; - objectPath += std::to_string(id); - getCertificateProperties(asyncResp, objectPath, - certs::authorityServiceName, id, - certURL, "TrustStore Certificate"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + long id = getIDFromURL(req.url); + if (id < 0) + { + BMCWEB_LOG_ERROR << "Invalid url value" << req.url; + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" + << std::to_string(id); + std::string certURL = + "/redfish/v1/Managers/bmc/Truststore/Certificates/" + + std::to_string(id); + std::string objectPath = certs::authorityObjectPath; + objectPath += "/"; + objectPath += std::to_string(id); + getCertificateProperties(asyncResp, objectPath, + certs::authorityServiceName, id, certURL, + "TrustStore Certificate"); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") .privileges(redfish::privileges::deleteCertificate) @@ -1346,46 +1303,44 @@ inline void requestRoutesTrustStoreCertificate(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (param.empty()) - { - messages::internalError(asyncResp->res); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (param.empty()) + { + messages::internalError(asyncResp->res); + return; + } - long id = getIDFromURL(req.url); - if (id < 0) - { - BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; - messages::resourceNotFound(asyncResp->res, - "TrustStore Certificate", - std::string(req.url)); - return; - } - BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" - << std::to_string(id); - std::string certPath = certs::authorityObjectPath; - certPath += "/"; - certPath += std::to_string(id); - - crow::connections::systemBus->async_method_call( - [asyncResp, id](const boost::system::error_code ec) { - if (ec) - { - messages::resourceNotFound(asyncResp->res, - "TrustStore Certificate", - std::to_string(id)); - return; - } - BMCWEB_LOG_INFO << "Certificate deleted"; - asyncResp->res.result( - boost::beast::http::status::no_content); - }, - certs::authorityServiceName, certPath, certs::objDeleteIntf, - "Delete"); - }); + long id = getIDFromURL(req.url); + if (id < 0) + { + BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; + messages::resourceNotFound(asyncResp->res, "TrustStore Certificate", + std::string(req.url)); + return; + } + BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" + << std::to_string(id); + std::string certPath = certs::authorityObjectPath; + certPath += "/"; + certPath += std::to_string(id); + + crow::connections::systemBus->async_method_call( + [asyncResp, id](const boost::system::error_code ec) { + if (ec) + { + messages::resourceNotFound(asyncResp->res, + "TrustStore Certificate", + std::to_string(id)); + return; + } + BMCWEB_LOG_INFO << "Certificate deleted"; + asyncResp->res.result(boost::beast::http::status::no_content); + }, + certs::authorityServiceName, certPath, certs::objDeleteIntf, + "Delete"); + }); } // requestRoutesTrustStoreCertificate } // namespace redfish diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp index 1aa7b40bb6..29615132c7 100644 --- a/redfish-core/lib/chassis.hpp +++ b/redfish-core/lib/chassis.hpp @@ -44,34 +44,33 @@ inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp) "xyz.openbmc_project.State.Chassis", "CurrentPowerState", [aResp{std::move(aResp)}](const boost::system::error_code ec, const std::string& chassisState) { - if (ec) + if (ec) + { + if (ec == boost::system::errc::host_unreachable) { - 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(aResp->res); + // Service not available, no error, just don't return + // chassis state info + BMCWEB_LOG_DEBUG << "Service not available " << ec; return; } - - BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState; - // Verify Chassis State - if (chassisState == - "xyz.openbmc_project.State.Chassis.PowerState.On") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "Enabled"; - } - else if (chassisState == - "xyz.openbmc_project.State.Chassis.PowerState.Off") - { - aResp->res.jsonValue["PowerState"] = "Off"; - aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; - } + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + + BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState; + // Verify Chassis State + if (chassisState == "xyz.openbmc_project.State.Chassis.PowerState.On") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "Enabled"; + } + else if (chassisState == + "xyz.openbmc_project.State.Chassis.PowerState.Off") + { + aResp->res.jsonValue["PowerState"] = "Off"; + aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; + } }); } @@ -86,17 +85,16 @@ inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp, "xyz.openbmc_project.Chassis.Intrusion", "Status", [aResp{std::move(aResp)}](const boost::system::error_code ec, const std::string& value) { - if (ec) - { - // do not add err msg in redfish response, because this is not - // mandatory property - BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; - return; - } - - aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = - 1; - aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value; + if (ec) + { + // do not add err msg in redfish response, because this is not + // mandatory property + BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n"; + return; + } + + aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1; + aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value; }); } @@ -109,23 +107,22 @@ inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp) [aResp{std::move(aResp)}]( const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) + if (ec) + { + // do not add err msg in redfish response, because this is not + // mandatory property + BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n"; + return; + } + // Iterate over all retrieved ObjectPaths. + for (const auto& object : subtree) + { + for (const auto& service : object.second) { - // do not add err msg in redfish response, because this is not - // mandatory property - BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec - << "\n"; + getIntrusionByService(aResp, service.first, object.first); return; } - // Iterate over all retrieved ObjectPaths. - for (const auto& object : subtree) - { - for (const auto& service : object.second) - { - getIntrusionByService(aResp, service.first, object.first); - return; - } - } + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -145,20 +142,20 @@ inline void requestRoutesChassisCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#ChassisCollection.ChassisCollection"; - asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; - asyncResp->res.jsonValue["Name"] = "Chassis Collection"; - - collection_util::getCollectionMembers( - asyncResp, "/redfish/v1/Chassis", - {"xyz.openbmc_project.Inventory.Item.Board", - "xyz.openbmc_project.Inventory.Item.Chassis"}); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#ChassisCollection.ChassisCollection"; + asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis"; + asyncResp->res.jsonValue["Name"] = "Chassis Collection"; + + collection_util::getCollectionMembers( + asyncResp, "/redfish/v1/Chassis", + {"xyz.openbmc_project.Inventory.Item.Board", + "xyz.openbmc_project.Inventory.Item.Chassis"}); + }); } inline void @@ -171,16 +168,15 @@ inline void "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; - } - - asyncResp->res - .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = - property; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error for Location"; + messages::internalError(asyncResp->res); + return; + } + + asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = + property; }); } @@ -193,13 +189,13 @@ 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_DEBUG << "DBUS response error for UUID"; - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue["UUID"] = chassisUUID; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error for UUID"; + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue["UUID"] = chassisUUID; }); } @@ -211,381 +207,352 @@ inline void requestRoutesChassis(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") .privileges(redfish::privileges::getChassis) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& chassisId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& chassisId) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + const std::array<const char*, 2> interfaces = { + "xyz.openbmc_project.Inventory.Item.Board", + "xyz.openbmc_project.Inventory.Item.Chassis"}; + + crow::connections::systemBus->async_method_call( + [asyncResp, chassisId(std::string(chassisId))]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec) { + messages::internalError(asyncResp->res); return; } - const std::array<const char*, 2> interfaces = { - "xyz.openbmc_project.Inventory.Item.Board", - "xyz.openbmc_project.Inventory.Item.Chassis"}; - - crow::connections::systemBus->async_method_call( - [asyncResp, chassisId(std::string(chassisId))]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) + // 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) + { + continue; + } + + auto health = std::make_shared<HealthPopulate>(asyncResp); + + sdbusplus::asio::getProperty<std::vector<std::string>>( + *crow::connections::systemBus, + "xyz.openbmc_project.ObjectMapper", path + "/all_sensors", + "xyz.openbmc_project.Association", "endpoints", + [health](const boost::system::error_code ec2, + const std::vector<std::string>& resp) { + if (ec2) { - messages::internalError(asyncResp->res); - return; + return; // no sensors = no failures } - // 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; + health->inventory = resp; + }); - sdbusplus::message::object_path objPath(path); - if (objPath.filename() != chassisId) - { - continue; - } + health->populate(); - auto health = - std::make_shared<HealthPopulate>(asyncResp); - - sdbusplus::asio::getProperty<std::vector<std::string>>( - *crow::connections::systemBus, - "xyz.openbmc_project.ObjectMapper", - path + "/all_sensors", - "xyz.openbmc_project.Association", "endpoints", - [health](const boost::system::error_code ec2, - const std::vector<std::string>& resp) { - if (ec2) - { - return; // no sensors = no failures - } - health->inventory = resp; - }); + if (connectionNames.empty()) + { + BMCWEB_LOG_ERROR << "Got 0 Connection names"; + continue; + } - health->populate(); + asyncResp->res.jsonValue["@odata.type"] = + "#Chassis.v1_16_0.Chassis"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId; + asyncResp->res.jsonValue["Name"] = "Chassis Collection"; + asyncResp->res.jsonValue["ChassisType"] = "RackMount"; + asyncResp->res + .jsonValue["Actions"]["#Chassis.Reset"]["target"] = + "/redfish/v1/Chassis/" + chassisId + + "/Actions/Chassis.Reset"; + asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] + ["@Redfish.ActionInfo"] = + "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; + asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices"; - if (connectionNames.empty()) - { - BMCWEB_LOG_ERROR << "Got 0 Connection names"; - continue; - } + const std::string& connectionName = connectionNames[0].first; - asyncResp->res.jsonValue["@odata.type"] = - "#Chassis.v1_16_0.Chassis"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId; - asyncResp->res.jsonValue["Name"] = "Chassis Collection"; - asyncResp->res.jsonValue["ChassisType"] = "RackMount"; - asyncResp->res - .jsonValue["Actions"]["#Chassis.Reset"]["target"] = - "/redfish/v1/Chassis/" + chassisId + - "/Actions/Chassis.Reset"; - asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"] - ["@Redfish.ActionInfo"] = - "/redfish/v1/Chassis/" + chassisId + - "/ResetActionInfo"; - asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices"; - - const std::string& connectionName = - connectionNames[0].first; - - const std::vector<std::string>& interfaces2 = - connectionNames[0].second; - const std::array<const char*, 2> hasIndicatorLed = { - "xyz.openbmc_project.Inventory.Item.Panel", - "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; - - const std::string assetTagInterface = - "xyz.openbmc_project.Inventory.Decorator.AssetTag"; - if (std::find(interfaces2.begin(), interfaces2.end(), - assetTagInterface) != interfaces2.end()) - { - sdbusplus::asio::getProperty<std::string>( - *crow::connections::systemBus, connectionName, - path, assetTagInterface, "AssetTag", - [asyncResp, chassisId(std::string(chassisId))]( - const boost::system::error_code ec, - const std::string& property) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "DBus response error for AssetTag"; - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue["AssetTag"] = - property; - }); - } + const std::vector<std::string>& interfaces2 = + connectionNames[0].second; + const std::array<const char*, 2> hasIndicatorLed = { + "xyz.openbmc_project.Inventory.Item.Panel", + "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; - for (const char* interface : hasIndicatorLed) + const std::string assetTagInterface = + "xyz.openbmc_project.Inventory.Decorator.AssetTag"; + if (std::find(interfaces2.begin(), interfaces2.end(), + assetTagInterface) != interfaces2.end()) + { + sdbusplus::asio::getProperty<std::string>( + *crow::connections::systemBus, connectionName, path, + assetTagInterface, "AssetTag", + [asyncResp, chassisId(std::string(chassisId))]( + const boost::system::error_code ec, + const std::string& property) { + if (ec) { - if (std::find(interfaces2.begin(), - interfaces2.end(), - interface) != interfaces2.end()) - { - getIndicatorLedState(asyncResp); - getLocationIndicatorActive(asyncResp); - break; - } + BMCWEB_LOG_DEBUG + << "DBus response error for AssetTag"; + messages::internalError(asyncResp->res); + return; } + asyncResp->res.jsonValue["AssetTag"] = property; + }); + } - crow::connections::systemBus->async_method_call( - [asyncResp, chassisId(std::string(chassisId))]( - const boost::system::error_code /*ec2*/, - const dbus::utility::DBusPropertiesMap& - propertiesList) { - for (const std::pair< - std::string, + for (const char* interface : hasIndicatorLed) + { + if (std::find(interfaces2.begin(), interfaces2.end(), + interface) != interfaces2.end()) + { + getIndicatorLedState(asyncResp); + getLocationIndicatorActive(asyncResp); + break; + } + } + + crow::connections::systemBus->async_method_call( + [asyncResp, chassisId(std::string(chassisId))]( + const boost::system::error_code /*ec2*/, + const dbus::utility::DBusPropertiesMap& + propertiesList) { + for (const std::pair<std::string, dbus::utility::DbusVariantType>& - property : propertiesList) - { - // Store DBus properties that are also - // Redfish properties with same name and a - // string value - const std::string& propertyName = - property.first; - if ((propertyName == "PartNumber") || - (propertyName == "SerialNumber") || - (propertyName == "Manufacturer") || - (propertyName == "Model") || - (propertyName == "SparePartNumber")) - { - const std::string* value = - std::get_if<std::string>( - &property.second); - if (value == nullptr) - { - BMCWEB_LOG_ERROR - << "Null value returned for " - << propertyName; - messages::internalError( - asyncResp->res); - return; - } - // SparePartNumber is optional on D-Bus - // so skip if it is empty - if (propertyName == "SparePartNumber") - { - if (value->empty()) - { - continue; - } - } - asyncResp->res.jsonValue[propertyName] = - *value; - } - } - asyncResp->res.jsonValue["Name"] = chassisId; - asyncResp->res.jsonValue["Id"] = chassisId; -#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL - asyncResp->res - .jsonValue["Thermal"]["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId + - "/Thermal"; - // Power object - asyncResp->res.jsonValue["Power"]["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId + - "/Power"; -#endif - // SensorCollection - asyncResp->res - .jsonValue["Sensors"]["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId + - "/Sensors"; - asyncResp->res.jsonValue["Status"]["State"] = - "Enabled"; - - nlohmann::json::array_t computerSystems; - nlohmann::json::object_t system; - system["@odata.id"] = - "/redfish/v1/Systems/system"; - computerSystems.push_back(std::move(system)); - asyncResp->res - .jsonValue["Links"]["ComputerSystems"] = - std::move(computerSystems); - - nlohmann::json::array_t managedBy; - nlohmann::json::object_t manager; - manager["@odata.id"] = - "/redfish/v1/Managers/bmc"; - managedBy.push_back(std::move(manager)); - asyncResp->res.jsonValue["Links"]["ManagedBy"] = - std::move(managedBy); - getChassisState(asyncResp); - }, - connectionName, path, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Inventory.Decorator.Asset"); - - for (const auto& interface : interfaces2) + property : propertiesList) + { + // Store DBus properties that are also + // Redfish properties with same name and a + // string value + const std::string& propertyName = property.first; + if ((propertyName == "PartNumber") || + (propertyName == "SerialNumber") || + (propertyName == "Manufacturer") || + (propertyName == "Model") || + (propertyName == "SparePartNumber")) { - if (interface == "xyz.openbmc_project.Common.UUID") + const std::string* value = + std::get_if<std::string>(&property.second); + if (value == nullptr) { - getChassisUUID(asyncResp, connectionName, path); + BMCWEB_LOG_ERROR << "Null value returned for " + << propertyName; + messages::internalError(asyncResp->res); + return; } - else if ( - interface == - "xyz.openbmc_project.Inventory.Decorator.LocationCode") + // SparePartNumber is optional on D-Bus + // so skip if it is empty + if (propertyName == "SparePartNumber") { - getChassisLocationCode(asyncResp, - connectionName, path); + if (value->empty()) + { + continue; + } } + asyncResp->res.jsonValue[propertyName] = *value; } - - return; } + asyncResp->res.jsonValue["Name"] = chassisId; + asyncResp->res.jsonValue["Id"] = chassisId; +#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL + asyncResp->res.jsonValue["Thermal"]["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId + "/Thermal"; + // Power object + asyncResp->res.jsonValue["Power"]["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId + "/Power"; +#endif + // SensorCollection + asyncResp->res.jsonValue["Sensors"]["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId + "/Sensors"; + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + + nlohmann::json::array_t computerSystems; + nlohmann::json::object_t system; + system["@odata.id"] = "/redfish/v1/Systems/system"; + computerSystems.push_back(std::move(system)); + asyncResp->res.jsonValue["Links"]["ComputerSystems"] = + std::move(computerSystems); + + nlohmann::json::array_t managedBy; + nlohmann::json::object_t manager; + manager["@odata.id"] = "/redfish/v1/Managers/bmc"; + managedBy.push_back(std::move(manager)); + asyncResp->res.jsonValue["Links"]["ManagedBy"] = + std::move(managedBy); + getChassisState(asyncResp); + }, + connectionName, path, "org.freedesktop.DBus.Properties", + "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); + + for (const auto& interface : interfaces2) + { + if (interface == "xyz.openbmc_project.Common.UUID") + { + getChassisUUID(asyncResp, connectionName, path); + } + else if ( + interface == + "xyz.openbmc_project.Inventory.Decorator.LocationCode") + { + getChassisLocationCode(asyncResp, connectionName, path); + } + } + + return; + } - // Couldn't find an object with that name. return an error - messages::resourceNotFound( - asyncResp->res, "#Chassis.v1_16_0.Chassis", chassisId); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", 0, interfaces); + // Couldn't find an object with that name. return an error + messages::resourceNotFound(asyncResp->res, + "#Chassis.v1_16_0.Chassis", chassisId); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", 0, interfaces); - getPhysicalSecurityData(asyncResp); + getPhysicalSecurityData(asyncResp); }); BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/") .privileges(redfish::privileges::patchChassis) - .methods( - boost::beast::http::verb:: - patch)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<bool> locationIndicatorActive; - std::optional<std::string> indicatorLed; - - if (param.empty()) + .methods(boost::beast::http::verb::patch)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& param) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<bool> locationIndicatorActive; + std::optional<std::string> indicatorLed; + + if (param.empty()) + { + return; + } + + if (!json_util::readJsonPatch( + req, asyncResp->res, "LocationIndicatorActive", + locationIndicatorActive, "IndicatorLED", indicatorLed)) + { + return; + } + + // TODO (Gunnar): Remove IndicatorLED after enough time has passed + if (!locationIndicatorActive && !indicatorLed) + { + return; // delete this when we support more patch properties + } + if (indicatorLed) + { + asyncResp->res.addHeader( + boost::beast::http::field::warning, + "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); + } + + const std::array<const char*, 2> interfaces = { + "xyz.openbmc_project.Inventory.Item.Board", + "xyz.openbmc_project.Inventory.Item.Chassis"}; + + const std::string& chassisId = param; + + crow::connections::systemBus->async_method_call( + [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec) { + messages::internalError(asyncResp->res); return; } - if (!json_util::readJsonPatch( - req, asyncResp->res, "LocationIndicatorActive", - locationIndicatorActive, "IndicatorLED", indicatorLed)) + // Iterate over all retrieved ObjectPaths. + for (const std::pair<std::string, + std::vector<std::pair< + std::string, std::vector<std::string>>>>& + object : subtree) { - return; - } + const std::string& path = object.first; + const std::vector< + std::pair<std::string, std::vector<std::string>>>& + connectionNames = object.second; - // TODO (Gunnar): Remove IndicatorLED after enough time has passed - if (!locationIndicatorActive && !indicatorLed) - { - return; // delete this when we support more patch properties - } - if (indicatorLed) - { - asyncResp->res.addHeader( - boost::beast::http::field::warning, - "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\""); - } + sdbusplus::message::object_path objPath(path); + if (objPath.filename() != chassisId) + { + continue; + } - const std::array<const char*, 2> interfaces = { - "xyz.openbmc_project.Inventory.Item.Board", - "xyz.openbmc_project.Inventory.Item.Chassis"}; + if (connectionNames.empty()) + { + BMCWEB_LOG_ERROR << "Got 0 Connection names"; + continue; + } - const std::string& chassisId = param; + const std::vector<std::string>& interfaces3 = + connectionNames[0].second; - crow::connections::systemBus->async_method_call( - [asyncResp, chassisId, locationIndicatorActive, indicatorLed]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) + const std::array<const char*, 2> hasIndicatorLed = { + "xyz.openbmc_project.Inventory.Item.Panel", + "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; + bool indicatorChassis = false; + for (const char* interface : hasIndicatorLed) + { + if (std::find(interfaces3.begin(), interfaces3.end(), + interface) != interfaces3.end()) { - messages::internalError(asyncResp->res); - return; + indicatorChassis = true; + break; } - - // Iterate over all retrieved ObjectPaths. - for (const std::pair< - std::string, - std::vector<std::pair<std::string, - std::vector<std::string>>>>& - object : subtree) + } + if (locationIndicatorActive) + { + if (indicatorChassis) { - 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) - { - continue; - } - - if (connectionNames.empty()) - { - BMCWEB_LOG_ERROR << "Got 0 Connection names"; - continue; - } - - const std::vector<std::string>& interfaces3 = - connectionNames[0].second; - - const std::array<const char*, 2> hasIndicatorLed = { - "xyz.openbmc_project.Inventory.Item.Panel", - "xyz.openbmc_project.Inventory.Item.Board.Motherboard"}; - bool indicatorChassis = false; - for (const char* interface : hasIndicatorLed) - { - if (std::find(interfaces3.begin(), - interfaces3.end(), - interface) != interfaces3.end()) - { - indicatorChassis = true; - break; - } - } - if (locationIndicatorActive) - { - if (indicatorChassis) - { - setLocationIndicatorActive( - asyncResp, *locationIndicatorActive); - } - else - { - messages::propertyUnknown( - asyncResp->res, "LocationIndicatorActive"); - } - } - if (indicatorLed) - { - if (indicatorChassis) - { - setIndicatorLedState(asyncResp, *indicatorLed); - } - else - { - messages::propertyUnknown(asyncResp->res, - "IndicatorLED"); - } - } - return; + setLocationIndicatorActive(asyncResp, + *locationIndicatorActive); + } + else + { + messages::propertyUnknown(asyncResp->res, + "LocationIndicatorActive"); } + } + if (indicatorLed) + { + if (indicatorChassis) + { + setIndicatorLedState(asyncResp, *indicatorLed); + } + else + { + messages::propertyUnknown(asyncResp->res, + "IndicatorLED"); + } + } + return; + } - messages::resourceNotFound( - asyncResp->res, "#Chassis.v1_14_0.Chassis", chassisId); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", 0, interfaces); + messages::resourceNotFound(asyncResp->res, + "#Chassis.v1_14_0.Chassis", chassisId); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", 0, interfaces); }); } @@ -605,47 +572,45 @@ inline void [asyncResp]( const boost::system::error_code ec, const dbus::utility::MapperGetSubTreePathsResponse& chassisList) { + if (ec) + { + BMCWEB_LOG_DEBUG << "[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"; + + /* Look for system reset chassis path */ + if ((std::find(chassisList.begin(), chassisList.end(), 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"; + } + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + // Use "Set" method to set the property value. if (ec) { - BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec; + BMCWEB_LOG_DEBUG << "[Set] 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"; - - /* Look for system reset chassis path */ - if ((std::find(chassisList.begin(), chassisList.end(), - 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"; - } - - crow::connections::systemBus->async_method_call( - [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; - } - - messages::success(asyncResp->res); - }, - processName, objectPath, "org.freedesktop.DBus.Properties", - "Set", interfaceName, destProperty, - dbus::utility::DbusVariantType{propertyValue}); + messages::success(asyncResp->res); + }, + processName, objectPath, "org.freedesktop.DBus.Properties", "Set", + interfaceName, destProperty, + dbus::utility::DbusVariantType{propertyValue}); }, busName, path, interface, method, "/", 0, interfaces); } @@ -665,31 +630,31 @@ inline void requestRoutesChassisResetAction(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string&) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "Post Chassis Reset."; - - std::string resetType; - - if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", - resetType)) - { - return; - } - - if (resetType != "PowerCycle") - { - BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " - << resetType; - messages::actionParameterNotSupported( - asyncResp->res, resetType, "ResetType"); - - return; - } - doChassisPowerCycle(asyncResp); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "Post Chassis Reset."; + + std::string resetType; + + if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", + resetType)) + { + return; + } + + if (resetType != "PowerCycle") + { + BMCWEB_LOG_DEBUG << "Invalid property value for ResetType: " + << resetType; + messages::actionParameterNotSupported(asyncResp->res, resetType, + "ResetType"); + + return; + } + doChassisPowerCycle(asyncResp); + }); } /** @@ -704,26 +669,26 @@ inline void requestRoutesChassisResetActionInfo(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& chassisId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#ActionInfo.v1_1_2.ActionInfo"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; - asyncResp->res.jsonValue["Name"] = "Reset Action Info"; - - asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; - nlohmann::json::object_t parameters; - parameters["Name"] = "ResetType"; - parameters["Required"] = true; - parameters["DataType"] = "String"; - nlohmann::json::array_t allowed; - allowed.push_back("PowerCycle"); - parameters["AllowableValues"] = std::move(allowed); - asyncResp->res.jsonValue["Parameters"] = std::move(parameters); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#ActionInfo.v1_1_2.ActionInfo"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId + "/ResetActionInfo"; + asyncResp->res.jsonValue["Name"] = "Reset Action Info"; + + asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; + nlohmann::json::object_t parameters; + parameters["Name"] = "ResetType"; + parameters["Required"] = true; + parameters["DataType"] = "String"; + nlohmann::json::array_t allowed; + allowed.push_back("PowerCycle"); + parameters["AllowableValues"] = std::move(allowed); + asyncResp->res.jsonValue["Parameters"] = std::move(parameters); + }); } } // namespace redfish diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp index e7f6b8b57c..facc29b6bd 100644 --- a/redfish-core/lib/ethernet.hpp +++ b/redfish-core/lib/ethernet.hpp @@ -682,10 +682,10 @@ inline void deleteIPv4(const std::string& ifaceId, const std::string& ipHash, { 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 + "/ipv4/" + ipHash, @@ -698,12 +698,12 @@ inline void updateIPv4DefaultGateway( { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.result(boost::beast::http::status::no_content); + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.result(boost::beast::http::status::no_content); }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/" + ifaceId, @@ -726,8 +726,8 @@ 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) { + auto createIpHandler = + [asyncResp, ifaceId, gateway](const boost::system::error_code ec) { if (ec) { messages::internalError(asyncResp->res); @@ -766,27 +766,26 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, ifaceId, address, prefixLength, gateway](const boost::system::error_code ec) { - if (ec) + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + + crow::connections::systemBus->async_method_call( + [asyncResp, ifaceId, gateway](const boost::system::error_code ec2) { + if (ec2) { messages::internalError(asyncResp->res); return; } - - crow::connections::systemBus->async_method_call( - [asyncResp, ifaceId, - gateway](const boost::system::error_code ec2) { - if (ec2) - { - messages::internalError(asyncResp->res); - return; - } - updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); - }, - "xyz.openbmc_project.Network", - "/xyz/openbmc_project/network/" + ifaceId, - "xyz.openbmc_project.Network.IP.Create", "IP", - "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, - prefixLength, gateway); + updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); + }, + "xyz.openbmc_project.Network", + "/xyz/openbmc_project/network/" + ifaceId, + "xyz.openbmc_project.Network.IP.Create", "IP", + "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, + prefixLength, gateway); }, "xyz.openbmc_project.Network", +"/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + id, @@ -807,10 +806,10 @@ inline void deleteIPv6(const std::string& ifaceId, const std::string& ipHash, { 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 + "/ipv6/" + ipHash, @@ -837,22 +836,22 @@ inline void crow::connections::systemBus->async_method_call( [asyncResp, ifaceId, address, prefixLength](const boost::system::error_code ec) { - if (ec) + if (ec) + { + messages::internalError(asyncResp->res); + } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec2) { + if (ec2) { messages::internalError(asyncResp->res); } - 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", - "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, - prefixLength, ""); + }, + "xyz.openbmc_project.Network", + "/xyz/openbmc_project/network/" + ifaceId, + "xyz.openbmc_project.Network.IP.Create", "IP", + "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, + prefixLength, ""); }, "xyz.openbmc_project.Network", +"/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + id, @@ -906,39 +905,38 @@ void getEthernetIfaceData(const std::string& ethifaceId, callback{std::forward<CallbackFunc>(callback)}]( const boost::system::error_code errorCode, dbus::utility::ManagedObjectType& resp) { - EthernetInterfaceData ethData{}; - boost::container::flat_set<IPv4AddressData> ipv4Data; - boost::container::flat_set<IPv6AddressData> ipv6Data; + EthernetInterfaceData ethData{}; + boost::container::flat_set<IPv4AddressData> ipv4Data; + boost::container::flat_set<IPv6AddressData> ipv6Data; - if (errorCode) - { - callback(false, ethData, ipv4Data, ipv6Data); - return; - } + if (errorCode) + { + callback(false, ethData, ipv4Data, ipv6Data); + return; + } - bool found = - extractEthernetInterfaceData(ethifaceId, resp, ethData); - if (!found) - { - callback(false, ethData, ipv4Data, ipv6Data); - return; - } + bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); + if (!found) + { + callback(false, ethData, ipv4Data, ipv6Data); + return; + } - extractIPData(ethifaceId, resp, ipv4Data); - // Fix global GW - for (IPv4AddressData& ipv4 : ipv4Data) + 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")) { - if (((ipv4.linktype == LinkType::Global) && - (ipv4.gateway == "0.0.0.0")) || - (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) - { - ipv4.gateway = ethData.defaultGateway; - } + ipv4.gateway = ethData.defaultGateway; } + } - extractIPV6Data(ethifaceId, resp, ipv6Data); - // Finally make a callback with useful data - callback(true, ethData, ipv4Data, ipv6Data); + extractIPV6Data(ethifaceId, resp, ipv6Data); + // Finally make a callback with useful data + callback(true, ethData, ipv4Data, ipv6Data); }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -957,40 +955,40 @@ void getEthernetIfaceList(CallbackFunc&& callback) [callback{std::forward<CallbackFunc>(callback)}]( const boost::system::error_code errorCode, dbus::utility::ManagedObjectType& resp) { - // Callback requires vector<string> to retrieve all available - // ethernet interfaces - boost::container::flat_set<std::string> ifaceList; - ifaceList.reserve(resp.size()); - if (errorCode) - { - callback(false, ifaceList); - return; - } + // Callback requires vector<string> to retrieve all available + // ethernet interfaces + boost::container::flat_set<std::string> ifaceList; + ifaceList.reserve(resp.size()); + if (errorCode) + { + callback(false, ifaceList); + return; + } - // Iterate over all retrieved ObjectPaths. - for (const auto& objpath : resp) + // Iterate over all retrieved ObjectPaths. + for (const auto& objpath : resp) + { + // And all interfaces available for certain ObjectPath. + for (const auto& interface : objpath.second) { - // And all interfaces available for certain ObjectPath. - for (const auto& interface : objpath.second) + // If interface is + // xyz.openbmc_project.Network.EthernetInterface, this is + // what we're looking for. + if (interface.first == + "xyz.openbmc_project.Network.EthernetInterface") { - // If interface is - // xyz.openbmc_project.Network.EthernetInterface, this is - // what we're looking for. - if (interface.first == - "xyz.openbmc_project.Network.EthernetInterface") + std::string ifaceId = objpath.first.filename(); + if (ifaceId.empty()) { - std::string ifaceId = objpath.first.filename(); - if (ifaceId.empty()) - { - continue; - } - // and put it into output vector. - ifaceList.emplace(ifaceId); + continue; } + // and put it into output vector. + ifaceList.emplace(ifaceId); } } - // Finally make a callback with useful data - callback(true, ifaceList); + } + // Finally make a callback with useful data + callback(true, ifaceList); }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -1009,10 +1007,10 @@ inline void } 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/config", "org.freedesktop.DBus.Properties", "Set", @@ -1028,10 +1026,10 @@ inline void "/xyz/openbmc_project/network/" + 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", objPath, "org.freedesktop.DBus.Properties", "Set", @@ -1047,10 +1045,10 @@ inline void std::vector<std::string> vectorDomainname = {domainname}; 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, @@ -1125,11 +1123,11 @@ inline void { crow::connections::systemBus->async_method_call( [asyncResp, macAddress](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/" + ifaceId, @@ -1146,13 +1144,13 @@ inline void setDHCPEnabled(const std::string& ifaceId, const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/" + ifaceId, @@ -1167,12 +1165,12 @@ inline void setEthernetInterfaceBoolProperty( { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/" + ifaceId, @@ -1187,12 +1185,12 @@ inline void setDHCPv4Config(const std::string& propertyName, const bool& value, BMCWEB_LOG_DEBUG << propertyName << " = " << value; crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/config/dhcp", @@ -1521,11 +1519,11 @@ inline void handleStaticNameServersPatch( { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network/" + ifaceId, @@ -1675,12 +1673,12 @@ inline void parseInterfaceData( crow::connections::systemBus->async_method_call( [health](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreePathsResponse& resp) { - if (ec) - { - return; - } + if (ec) + { + return; + } - health->inventory = resp; + health->inventory = resp; }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1827,55 +1825,53 @@ inline void requestEthernetInterfacesRoutes(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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#EthernetInterfaceCollection.EthernetInterfaceCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/EthernetInterfaces"; - 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 boost::container::flat_set< - std::string>& ifaceList) { - if (!success) - { - messages::internalError(asyncResp->res); - return; - } + asyncResp->res.jsonValue["@odata.type"] = + "#EthernetInterfaceCollection.EthernetInterfaceCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/EthernetInterfaces"; + 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 boost::container::flat_set<std::string>& ifaceList) { + if (!success) + { + messages::internalError(asyncResp->res); + return; + } - nlohmann::json& ifaceArray = - asyncResp->res.jsonValue["Members"]; - ifaceArray = nlohmann::json::array(); - std::string tag = "_"; - for (const std::string& ifaceItem : ifaceList) - { - std::size_t found = ifaceItem.find(tag); - if (found == std::string::npos) - { - nlohmann::json::object_t iface; - iface["@odata.id"] = - "/redfish/v1/Managers/bmc/EthernetInterfaces/" + - ifaceItem; - ifaceArray.push_back(std::move(iface)); - } - } + nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; + ifaceArray = nlohmann::json::array(); + std::string tag = "_"; + for (const std::string& ifaceItem : ifaceList) + { + std::size_t found = ifaceItem.find(tag); + if (found == std::string::npos) + { + nlohmann::json::object_t iface; + iface["@odata.id"] = + "/redfish/v1/Managers/bmc/EthernetInterfaces/" + + ifaceItem; + ifaceArray.push_back(std::move(iface)); + } + } - asyncResp->res.jsonValue["Members@odata.count"] = - ifaceArray.size(); - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/EthernetInterfaces"; - }); - }); + asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/EthernetInterfaces"; + }); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") .privileges(redfish::privileges::getEthernetInterface) @@ -1883,39 +1879,34 @@ inline void requestEthernetInterfacesRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& ifaceId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - getEthernetIfaceData( - ifaceId, - [asyncResp, - ifaceId](const bool& success, - const EthernetInterfaceData& ethData, - const boost::container::flat_set<IPv4AddressData>& - ipv4Data, - const boost::container::flat_set<IPv6AddressData>& - ipv6Data) { - if (!success) - { - // TODO(Pawel)consider distinguish between non - // existing object, and other errors - messages::resourceNotFound( - asyncResp->res, "EthernetInterface", ifaceId); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + getEthernetIfaceData( + ifaceId, + [asyncResp, ifaceId]( + const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>& ipv4Data, + const boost::container::flat_set<IPv6AddressData>& ipv6Data) { + 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_4_1.EthernetInterface"; - asyncResp->res.jsonValue["Name"] = - "Manager Ethernet Interface"; - asyncResp->res.jsonValue["Description"] = - "Management Network Interface"; + asyncResp->res.jsonValue["@odata.type"] = + "#EthernetInterface.v1_4_1.EthernetInterface"; + asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; + asyncResp->res.jsonValue["Description"] = + "Management Network Interface"; - parseInterfaceData(asyncResp, ifaceId, ethData, - ipv4Data, ipv6Data); - }); + parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data); }); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") .privileges(redfish::privileges::patchEthernetInterface) @@ -1923,160 +1914,150 @@ inline void requestEthernetInterfacesRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& ifaceId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<std::string> hostname; - std::optional<std::string> fqdn; - std::optional<std::string> macAddress; - std::optional<std::string> ipv6DefaultGateway; - std::optional<nlohmann::json> ipv4StaticAddresses; - std::optional<nlohmann::json> ipv6StaticAddresses; - std::optional<std::vector<std::string>> staticNameServers; - std::optional<nlohmann::json> dhcpv4; - std::optional<nlohmann::json> dhcpv6; - std::optional<bool> interfaceEnabled; - std::optional<size_t> mtuSize; - DHCPParameters v4dhcpParms; - DHCPParameters v6dhcpParms; - - if (!json_util::readJsonPatch( - req, asyncResp->res, "HostName", hostname, "FQDN", fqdn, - "IPv4StaticAddresses", ipv4StaticAddresses, - "MACAddress", macAddress, "StaticNameServers", - staticNameServers, "IPv6DefaultGateway", - ipv6DefaultGateway, "IPv6StaticAddresses", - ipv6StaticAddresses, "DHCPv4", dhcpv4, "DHCPv6", dhcpv6, - "MTUSize", mtuSize, "InterfaceEnabled", - interfaceEnabled)) - { - return; - } - if (dhcpv4) - { - if (!json_util::readJson( - *dhcpv4, asyncResp->res, "DHCPEnabled", - v4dhcpParms.dhcpv4Enabled, "UseDNSServers", - v4dhcpParms.useDnsServers, "UseNTPServers", - v4dhcpParms.useNtpServers, "UseDomainName", - v4dhcpParms.useDomainName)) - { - return; - } - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<std::string> hostname; + std::optional<std::string> fqdn; + std::optional<std::string> macAddress; + std::optional<std::string> ipv6DefaultGateway; + std::optional<nlohmann::json> ipv4StaticAddresses; + std::optional<nlohmann::json> ipv6StaticAddresses; + std::optional<std::vector<std::string>> staticNameServers; + std::optional<nlohmann::json> dhcpv4; + std::optional<nlohmann::json> dhcpv6; + std::optional<bool> interfaceEnabled; + std::optional<size_t> mtuSize; + DHCPParameters v4dhcpParms; + DHCPParameters v6dhcpParms; + + if (!json_util::readJsonPatch( + req, asyncResp->res, "HostName", hostname, "FQDN", fqdn, + "IPv4StaticAddresses", ipv4StaticAddresses, "MACAddress", + macAddress, "StaticNameServers", staticNameServers, + "IPv6DefaultGateway", ipv6DefaultGateway, "IPv6StaticAddresses", + ipv6StaticAddresses, "DHCPv4", dhcpv4, "DHCPv6", dhcpv6, + "MTUSize", mtuSize, "InterfaceEnabled", interfaceEnabled)) + { + return; + } + if (dhcpv4) + { + if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", + v4dhcpParms.dhcpv4Enabled, "UseDNSServers", + v4dhcpParms.useDnsServers, "UseNTPServers", + v4dhcpParms.useNtpServers, "UseDomainName", + v4dhcpParms.useDomainName)) + { + return; + } + } - if (dhcpv6) - { - if (!json_util::readJson( - *dhcpv6, asyncResp->res, "OperatingMode", - v6dhcpParms.dhcpv6OperatingMode, "UseDNSServers", - v6dhcpParms.useDnsServers, "UseNTPServers", - v6dhcpParms.useNtpServers, "UseDomainName", - v6dhcpParms.useDomainName)) - { - return; - } - } + if (dhcpv6) + { + if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", + v6dhcpParms.dhcpv6OperatingMode, + "UseDNSServers", v6dhcpParms.useDnsServers, + "UseNTPServers", v6dhcpParms.useNtpServers, + "UseDomainName", + v6dhcpParms.useDomainName)) + { + return; + } + } - // 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), - staticNameServers = std::move(staticNameServers), - dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), - mtuSize = mtuSize, v4dhcpParms = std::move(v4dhcpParms), - v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( - const bool& success, - const EthernetInterfaceData& ethData, - const boost::container::flat_set<IPv4AddressData>& - ipv4Data, - const boost::container::flat_set<IPv6AddressData>& - ipv6Data) { - if (!success) - { - // ... otherwise return error - // TODO(Pawel)consider distinguish between non - // existing object, and other errors - messages::resourceNotFound( - asyncResp->res, "Ethernet Interface", ifaceId); - return; - } + // 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), + staticNameServers = std::move(staticNameServers), + dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), + mtuSize = mtuSize, v4dhcpParms = std::move(v4dhcpParms), + v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( + const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>& ipv4Data, + const boost::container::flat_set<IPv6AddressData>& ipv6Data) { + if (!success) + { + // ... otherwise return error + // TODO(Pawel)consider distinguish between non + // existing object, and other errors + messages::resourceNotFound(asyncResp->res, "Ethernet Interface", + ifaceId); + return; + } - if (dhcpv4 || dhcpv6) - { - handleDHCPPatch(ifaceId, ethData, v4dhcpParms, - v6dhcpParms, asyncResp); - } + if (dhcpv4 || dhcpv6) + { + handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, + asyncResp); + } - if (hostname) - { - handleHostnamePatch(*hostname, asyncResp); - } + if (hostname) + { + handleHostnamePatch(*hostname, 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) - { - // TODO(ed) for some reason the capture of - // ipv4Addresses above is returning a const value, - // not a non-const value. This doesn't really work - // for us, as we need to be able to efficiently move - // out the intermedia nlohmann::json objects. This - // makes a copy of the structure, and operates on - // that, but could be done more efficiently - nlohmann::json ipv4Static = *ipv4StaticAddresses; - handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, - asyncResp); - } + if (ipv4StaticAddresses) + { + // TODO(ed) for some reason the capture of + // ipv4Addresses above is returning a const value, + // not a non-const value. This doesn't really work + // for us, as we need to be able to efficiently move + // out the intermedia nlohmann::json objects. This + // makes a copy of the structure, and operates on + // that, but could be done more efficiently + nlohmann::json ipv4Static = *ipv4StaticAddresses; + handleIPv4StaticPatch(ifaceId, ipv4Static, 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) - { - const nlohmann::json& ipv6Static = - *ipv6StaticAddresses; - handleIPv6StaticAddressesPatch(ifaceId, ipv6Static, - ipv6Data, asyncResp); - } + if (ipv6StaticAddresses) + { + const nlohmann::json& ipv6Static = *ipv6StaticAddresses; + handleIPv6StaticAddressesPatch(ifaceId, ipv6Static, ipv6Data, + asyncResp); + } - if (interfaceEnabled) - { - setEthernetInterfaceBoolProperty( - ifaceId, "NICEnabled", *interfaceEnabled, - asyncResp); - } + if (interfaceEnabled) + { + setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled", + *interfaceEnabled, asyncResp); + } - if (mtuSize) - { - handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); - } - }); + if (mtuSize) + { + handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); + } }); + }); BMCWEB_ROUTE( app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>/") @@ -2086,44 +2067,42 @@ inline void requestEthernetInterfacesRoutes(App& app) const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& parentIfaceId, const std::string& ifaceId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; - asyncResp->res.jsonValue["Name"] = "VLAN Network Interface"; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; + asyncResp->res.jsonValue["Name"] = "VLAN Network Interface"; - if (!verifyNames(parentIfaceId, ifaceId)) - { - return; - } + if (!verifyNames(parentIfaceId, ifaceId)) + { + return; + } - // Get single eth interface data, and call the below callback - // for JSON preparation - getEthernetIfaceData( - ifaceId, - [asyncResp, parentIfaceId, ifaceId]( - const bool& success, - const EthernetInterfaceData& ethData, - const boost::container::flat_set<IPv4AddressData>&, - const boost::container::flat_set<IPv6AddressData>&) { - if (success && ethData.vlanId) - { - parseInterfaceData(asyncResp->res.jsonValue, - parentIfaceId, ifaceId, ethData); - } - else - { - // ... otherwise return error - // TODO(Pawel)consider distinguish between non - // existing object, and other errors - messages::resourceNotFound(asyncResp->res, - "VLAN Network Interface", - ifaceId); - } - }); + // Get single eth interface data, and call the below callback + // for JSON preparation + getEthernetIfaceData( + ifaceId, + [asyncResp, parentIfaceId, + ifaceId](const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>&, + const boost::container::flat_set<IPv6AddressData>&) { + if (success && ethData.vlanId) + { + parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, + ifaceId, ethData); + } + else + { + // ... otherwise return error + // TODO(Pawel)consider distinguish between non + // existing object, and other errors + messages::resourceNotFound(asyncResp->res, + "VLAN Network Interface", ifaceId); + } }); + }); BMCWEB_ROUTE( app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>/") @@ -2133,79 +2112,71 @@ inline void requestEthernetInterfacesRoutes(App& app) const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& parentIfaceId, const std::string& ifaceId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (!verifyNames(parentIfaceId, ifaceId)) - { - messages::resourceNotFound( - asyncResp->res, "VLAN Network Interface", ifaceId); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (!verifyNames(parentIfaceId, ifaceId)) + { + messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", + ifaceId); + return; + } - std::optional<bool> vlanEnable; - std::optional<uint32_t> vlanId; + std::optional<bool> vlanEnable; + std::optional<uint32_t> vlanId; - if (!json_util::readJsonPatch(req, asyncResp->res, "VLANEnable", - vlanEnable, "VLANId", vlanId)) - { - return; - } + if (!json_util::readJsonPatch(req, asyncResp->res, "VLANEnable", + vlanEnable, "VLANId", vlanId)) + { + return; + } - if (vlanId) + if (vlanId) + { + messages::propertyNotWritable(asyncResp->res, "VLANId"); + return; + } + + // Get single eth interface data, and call the below callback + // for JSON preparation + getEthernetIfaceData( + ifaceId, + [asyncResp, parentIfaceId, ifaceId, vlanEnable]( + const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>&, + const boost::container::flat_set<IPv6AddressData>&) { + if (success && ethData.vlanId) + { + auto callback = + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + }; + + if (vlanEnable && !(*vlanEnable)) { - messages::propertyNotWritable(asyncResp->res, "VLANId"); - return; + BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " + "vlan interface"; + crow::connections::systemBus->async_method_call( + std::move(callback), "xyz.openbmc_project.Network", + std::string("/xyz/openbmc_project/network/") + ifaceId, + "xyz.openbmc_project.Object.Delete", "Delete"); } - - // Get single eth interface data, and call the below callback - // for JSON preparation - getEthernetIfaceData( - ifaceId, - [asyncResp, parentIfaceId, ifaceId, vlanEnable]( - const bool& success, - const EthernetInterfaceData& ethData, - const boost::container::flat_set<IPv4AddressData>&, - const boost::container::flat_set<IPv6AddressData>&) { - if (success && ethData.vlanId) - { - auto callback = - [asyncResp]( - const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - }; - - if (vlanEnable && !(*vlanEnable)) - { - BMCWEB_LOG_DEBUG - << "vlanEnable is false. Deleting the " - "vlan interface"; - crow::connections::systemBus->async_method_call( - std::move(callback), - "xyz.openbmc_project.Network", - std::string( - "/xyz/openbmc_project/network/") + - ifaceId, - "xyz.openbmc_project.Object.Delete", - "Delete"); - } - } - else - { - // TODO(Pawel)consider distinguish between non - // existing object, and other errors - messages::resourceNotFound(asyncResp->res, - "VLAN Network Interface", - ifaceId); - return; - } - }); + } + else + { + // TODO(Pawel)consider distinguish between non + // existing object, and other errors + messages::resourceNotFound(asyncResp->res, + "VLAN Network Interface", ifaceId); + return; + } }); + }); BMCWEB_ROUTE( app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>/") @@ -2215,54 +2186,49 @@ inline void requestEthernetInterfacesRoutes(App& app) const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& parentIfaceId, const std::string& ifaceId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (!verifyNames(parentIfaceId, ifaceId)) - { - messages::resourceNotFound( - asyncResp->res, "VLAN Network Interface", ifaceId); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (!verifyNames(parentIfaceId, ifaceId)) + { + messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", + ifaceId); + return; + } - // Get single eth interface data, and call the below callback - // for JSON preparation - getEthernetIfaceData( - ifaceId, - [asyncResp, parentIfaceId, ifaceId]( - const bool& success, - const EthernetInterfaceData& ethData, - const boost::container::flat_set<IPv4AddressData>&, - const boost::container::flat_set<IPv6AddressData>&) { - if (success && ethData.vlanId) - { - auto callback = - [asyncResp]( - const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - } - }; - crow::connections::systemBus->async_method_call( - std::move(callback), - "xyz.openbmc_project.Network", - std::string("/xyz/openbmc_project/network/") + - ifaceId, - "xyz.openbmc_project.Object.Delete", "Delete"); - } - else - { - // ... otherwise return error - // TODO(Pawel)consider distinguish between non - // existing object, and other errors - messages::resourceNotFound(asyncResp->res, - "VLAN Network Interface", - ifaceId); - } - }); + // Get single eth interface data, and call the below callback + // for JSON preparation + getEthernetIfaceData( + ifaceId, + [asyncResp, parentIfaceId, + ifaceId](const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>&, + const boost::container::flat_set<IPv6AddressData>&) { + if (success && ethData.vlanId) + { + auto callback = + [asyncResp](const boost::system::error_code ec) { + if (ec) + { + messages::internalError(asyncResp->res); + } + }; + crow::connections::systemBus->async_method_call( + std::move(callback), "xyz.openbmc_project.Network", + std::string("/xyz/openbmc_project/network/") + ifaceId, + "xyz.openbmc_project.Object.Delete", "Delete"); + } + else + { + // ... otherwise return error + // TODO(Pawel)consider distinguish between non + // existing object, and other errors + messages::resourceNotFound(asyncResp->res, + "VLAN Network Interface", ifaceId); + } }); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/") @@ -2272,62 +2238,60 @@ inline void requestEthernetInterfacesRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& rootInterfaceName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - // Get eth interface list, and call the below callback for JSON - // preparation - getEthernetIfaceList([asyncResp, rootInterfaceName]( - const bool& success, - const boost::container::flat_set< - std::string>& ifaceList) { - if (!success) - { - messages::internalError(asyncResp->res); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + // Get eth interface list, and call the below callback for JSON + // preparation + getEthernetIfaceList( + [asyncResp, rootInterfaceName]( + const bool& success, + const boost::container::flat_set<std::string>& ifaceList) { + if (!success) + { + messages::internalError(asyncResp->res); + return; + } - if (ifaceList.find(rootInterfaceName) == ifaceList.end()) - { - messages::resourceNotFound( - asyncResp->res, "VLanNetworkInterfaceCollection", - rootInterfaceName); - return; - } + if (ifaceList.find(rootInterfaceName) == ifaceList.end()) + { + messages::resourceNotFound(asyncResp->res, + "VLanNetworkInterfaceCollection", + rootInterfaceName); + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#VLanNetworkInterfaceCollection." - "VLanNetworkInterfaceCollection"; - asyncResp->res.jsonValue["Name"] = - "VLAN Network Interface Collection"; + asyncResp->res.jsonValue["@odata.type"] = + "#VLanNetworkInterfaceCollection." + "VLanNetworkInterfaceCollection"; + asyncResp->res.jsonValue["Name"] = + "VLAN Network Interface Collection"; - nlohmann::json ifaceArray = nlohmann::json::array(); + nlohmann::json ifaceArray = nlohmann::json::array(); - for (const std::string& ifaceItem : ifaceList) - { - if (boost::starts_with(ifaceItem, - rootInterfaceName + "_")) - { - std::string path = - "/redfish/v1/Managers/bmc/EthernetInterfaces/"; - path += rootInterfaceName; - path += "/VLANs/"; - path += ifaceItem; - nlohmann::json::object_t iface; - iface["@odata.id"] = std::move(path); - ifaceArray.push_back(std::move(iface)); - } - } + for (const std::string& ifaceItem : ifaceList) + { + if (boost::starts_with(ifaceItem, rootInterfaceName + "_")) + { + std::string path = + "/redfish/v1/Managers/bmc/EthernetInterfaces/"; + path += rootInterfaceName; + path += "/VLANs/"; + path += ifaceItem; + nlohmann::json::object_t iface; + iface["@odata.id"] = std::move(path); + ifaceArray.push_back(std::move(iface)); + } + } - asyncResp->res.jsonValue["Members@odata.count"] = - ifaceArray.size(); - asyncResp->res.jsonValue["Members"] = std::move(ifaceArray); - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/EthernetInterfaces/" + - rootInterfaceName + "/VLANs"; - }); - }); + asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); + asyncResp->res.jsonValue["Members"] = std::move(ifaceArray); + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/EthernetInterfaces/" + + rootInterfaceName + "/VLANs"; + }); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/") @@ -2336,48 +2300,47 @@ inline void requestEthernetInterfacesRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& rootInterfaceName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - bool vlanEnable = false; - uint32_t vlanId = 0; - if (!json_util::readJsonPatch(req, asyncResp->res, "VLANId", - vlanId, "VLANEnable", vlanEnable)) - { - return; - } - // Need both vlanId and vlanEnable to service this request - if (vlanId == 0U) - { - messages::propertyMissing(asyncResp->res, "VLANId"); - } - if (!vlanEnable) - { - messages::propertyMissing(asyncResp->res, "VLANEnable"); - } - if (static_cast<bool>(vlanId) ^ vlanEnable) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + bool vlanEnable = false; + uint32_t vlanId = 0; + if (!json_util::readJsonPatch(req, asyncResp->res, "VLANId", vlanId, + "VLANEnable", vlanEnable)) + { + return; + } + // Need both vlanId and vlanEnable to service this request + if (vlanId == 0U) + { + messages::propertyMissing(asyncResp->res, "VLANId"); + } + if (!vlanEnable) + { + messages::propertyMissing(asyncResp->res, "VLANEnable"); + } + if (static_cast<bool>(vlanId) ^ vlanEnable) + { + return; + } - auto callback = - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - // TODO(ed) make more consistent error messages - // based on phosphor-network responses - messages::internalError(asyncResp->res); - return; - } - messages::created(asyncResp->res); - }; - crow::connections::systemBus->async_method_call( - std::move(callback), "xyz.openbmc_project.Network", - "/xyz/openbmc_project/network", - "xyz.openbmc_project.Network.VLAN.Create", "VLAN", - rootInterfaceName, vlanId); - }); + auto callback = [asyncResp](const boost::system::error_code ec) { + if (ec) + { + // TODO(ed) make more consistent error messages + // based on phosphor-network responses + messages::internalError(asyncResp->res); + return; + } + messages::created(asyncResp->res); + }; + crow::connections::systemBus->async_method_call( + std::move(callback), "xyz.openbmc_project.Network", + "/xyz/openbmc_project/network", + "xyz.openbmc_project.Network.VLAN.Create", "VLAN", + rootInterfaceName, vlanId); + }); } } // namespace redfish diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp index 51c999f087..d0fa0a66e3 100644 --- a/redfish-core/lib/event_service.hpp +++ b/redfish-core/lib/event_service.hpp @@ -49,50 +49,47 @@ 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->res)) - { - 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["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 supportedSSEFilters = { - {"EventFormatType", true}, {"MessageId", true}, - {"MetricReportDefinition", true}, {"RegistryPrefix", true}, - {"OriginResource", false}, {"ResourceType", false}}; - - asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] = - supportedSSEFilters; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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["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 supportedSSEFilters = { + {"EventFormatType", true}, {"MessageId", true}, + {"MetricReportDefinition", true}, {"RegistryPrefix", true}, + {"OriginResource", false}, {"ResourceType", false}}; + + asyncResp->res.jsonValue["SSEFilterPropertiesSupported"] = + supportedSSEFilters; }); BMCWEB_ROUTE(app, "/redfish/v1/EventService/") @@ -100,65 +97,64 @@ inline void requestRoutesEventService(App& app) .methods(boost::beast::http::verb::patch)( [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - 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(); - - 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 (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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(); + + 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 (retryInterval) - { - // Supported range [30 - 180] - if ((*retryInterval < 30) || (*retryInterval > 180)) - { - messages::queryParameterOutOfRange( - asyncResp->res, std::to_string(*retryInterval), - "DeliveryRetryIntervalSeconds", "[30-180]"); - } - else - { - eventServiceConfig.retryTimeoutInterval = - *retryInterval; - } - } + if (retryInterval) + { + // Supported range [30 - 180] + if ((*retryInterval < 30) || (*retryInterval > 180)) + { + messages::queryParameterOutOfRange( + asyncResp->res, std::to_string(*retryInterval), + "DeliveryRetryIntervalSeconds", "[30-180]"); + } + else + { + eventServiceConfig.retryTimeoutInterval = *retryInterval; + } + } - EventServiceManager::getInstance().setEventServiceConfig( - eventServiceConfig); - }); + EventServiceManager::getInstance().setEventServiceConfig( + eventServiceConfig); + }); } inline void requestRoutesSubmitTestEvent(App& app) @@ -170,18 +166,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->res)) - { - 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->res)) + { + return; + } + if (!EventServiceManager::getInstance().sendTestEventLog()) + { + messages::serviceDisabled(asyncResp->res, + "/redfish/v1/EventService/"); + return; + } + asyncResp->res.result(boost::beast::http::status::no_content); + }); } inline void requestRoutesEventDestinationCollection(App& app) @@ -191,303 +187,296 @@ 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->res)) - { - 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"] = - "/redfish/v1/EventService/Subscriptions/" + id; - memberArray.push_back(std::move(member)); - } - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"] = + "/redfish/v1/EventService/Subscriptions/" + id; + memberArray.push_back(std::move(member)); + } + }); 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->res)) + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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>> headers; + std::optional<std::vector<nlohmann::json>> 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; + } + + if (regPrefixes && msgIds) + { + if (!regPrefixes->empty() && !msgIds->empty()) { + messages::propertyValueConflict(asyncResp->res, "MessageIds", + "RegistryPrefixes"); return; } - if (EventServiceManager::getInstance().getNumberOfSubscriptions() >= - maxNoOfSubscriptions) + } + + std::string host; + std::string urlProto; + uint16_t port = 0; + std::string path; + + if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, port, + path)) + { + BMCWEB_LOG_WARNING + << "Failed to validate and split destination url"; + messages::propertyValueFormatError(asyncResp->res, destUrl, + "Destination"); + return; + } + + if (path.empty()) + { + path = "/"; + } + std::shared_ptr<Subscription> subValue = + std::make_shared<Subscription>(host, port, path, urlProto); + + subValue->destinationUrl = destUrl; + + if (subscriptionType) + { + if (*subscriptionType != "RedfishEvent") { - messages::eventSubscriptionLimitExceeded(asyncResp->res); + messages::propertyValueNotInList( + asyncResp->res, *subscriptionType, "SubscriptionType"); 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>> headers; - std::optional<std::vector<nlohmann::json>> 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)) + 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::find(supportedEvtFormatTypes.begin(), + supportedEvtFormatTypes.end(), + *eventFormatType2) == supportedEvtFormatTypes.end()) { + messages::propertyValueNotInList( + asyncResp->res, *eventFormatType2, "EventFormatType"); return; } - - if (regPrefixes && msgIds) + subValue->eventFormatType = *eventFormatType2; + } + else + { + // If not specified, use default "Event" + subValue->eventFormatType = "Event"; + } + + if (context) + { + subValue->customText = *context; + } + + if (headers) + { + for (const nlohmann::json& headerChunk : *headers) { - if (!regPrefixes->empty() && !msgIds->empty()) + for (const auto& item : headerChunk.items()) { - messages::propertyValueConflict( - asyncResp->res, "MessageIds", "RegistryPrefixes"); - return; + const std::string* value = + item.value().get_ptr<const std::string*>(); + if (value == nullptr) + { + messages::propertyValueFormatError( + asyncResp->res, item.value().dump(2, 1), + "HttpHeaders/" + item.key()); + return; + } + subValue->httpHeaders.set(item.key(), *value); } } + } - std::string host; - std::string urlProto; - uint16_t port = 0; - std::string path; - - if (!crow::utility::validateAndSplitUrl(destUrl, urlProto, host, - port, path)) + if (regPrefixes) + { + for (const std::string& it : *regPrefixes) { - BMCWEB_LOG_WARNING - << "Failed to validate and split destination url"; - messages::propertyValueFormatError(asyncResp->res, destUrl, - "Destination"); - return; - } - - if (path.empty()) - { - path = "/"; - } - std::shared_ptr<Subscription> subValue = - std::make_shared<Subscription>(host, port, path, urlProto); - - subValue->destinationUrl = destUrl; - - if (subscriptionType) - { - if (*subscriptionType != "RedfishEvent") + if (std::find(supportedRegPrefixes.begin(), + supportedRegPrefixes.end(), + it) == supportedRegPrefixes.end()) { - messages::propertyValueNotInList( - asyncResp->res, *subscriptionType, "SubscriptionType"); + messages::propertyValueNotInList(asyncResp->res, it, + "RegistryPrefixes"); return; } - subValue->subscriptionType = *subscriptionType; - } - else - { - subValue->subscriptionType = "RedfishEvent"; // Default } + subValue->registryPrefixes = *regPrefixes; + } - if (protocol != "Redfish") + if (resTypes) + { + for (const std::string& it : *resTypes) { - messages::propertyValueNotInList(asyncResp->res, protocol, - "Protocol"); - return; - } - subValue->protocol = protocol; - - if (eventFormatType2) - { - if (std::find(supportedEvtFormatTypes.begin(), - supportedEvtFormatTypes.end(), - *eventFormatType2) == - supportedEvtFormatTypes.end()) + if (std::find(supportedResourceTypes.begin(), + supportedResourceTypes.end(), + it) == supportedResourceTypes.end()) { - messages::propertyValueNotInList( - asyncResp->res, *eventFormatType2, "EventFormatType"); + messages::propertyValueNotInList(asyncResp->res, it, + "ResourceTypes"); return; } - subValue->eventFormatType = *eventFormatType2; - } - else - { - // If not specified, use default "Event" - subValue->eventFormatType = "Event"; } + subValue->resourceTypes = *resTypes; + } - if (context) - { - subValue->customText = *context; - } + if (msgIds) + { + std::vector<std::string> registryPrefix; - if (headers) + // If no registry prefixes are mentioned, consider all + // supported prefixes + if (subValue->registryPrefixes.empty()) { - for (const nlohmann::json& headerChunk : *headers) - { - for (const auto& item : headerChunk.items()) - { - const std::string* value = - item.value().get_ptr<const std::string*>(); - if (value == nullptr) - { - messages::propertyValueFormatError( - asyncResp->res, item.value().dump(2, 1), - "HttpHeaders/" + item.key()); - return; - } - subValue->httpHeaders.set(item.key(), *value); - } - } + registryPrefix.assign(supportedRegPrefixes.begin(), + supportedRegPrefixes.end()); } - - if (regPrefixes) - { - for (const std::string& it : *regPrefixes) - { - if (std::find(supportedRegPrefixes.begin(), - supportedRegPrefixes.end(), - it) == supportedRegPrefixes.end()) - { - messages::propertyValueNotInList(asyncResp->res, it, - "RegistryPrefixes"); - return; - } - } - subValue->registryPrefixes = *regPrefixes; - } - - if (resTypes) + else { - for (const std::string& it : *resTypes) - { - if (std::find(supportedResourceTypes.begin(), - supportedResourceTypes.end(), - it) == supportedResourceTypes.end()) - { - messages::propertyValueNotInList(asyncResp->res, it, - "ResourceTypes"); - return; - } - } - subValue->resourceTypes = *resTypes; + registryPrefix = subValue->registryPrefixes; } - if (msgIds) + for (const std::string& id : *msgIds) { - std::vector<std::string> registryPrefix; + bool validId = false; - // If no registry prefixes are mentioned, consider all - // supported prefixes - if (subValue->registryPrefixes.empty()) - { - registryPrefix.assign(supportedRegPrefixes.begin(), - supportedRegPrefixes.end()); - } - else + // Check for Message ID in each of the selected Registry + for (const std::string& it : registryPrefix) { - registryPrefix = subValue->registryPrefixes; - } - - 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) + const std::span<const redfish::registries::MessageEntry> + registry = + redfish::registries::getRegistryFromPrefix(it); + + if (std::any_of( + registry.begin(), registry.end(), + [&id](const redfish::registries::MessageEntry& + messageEntry) { + return id == messageEntry.first; + })) { - const std::span<const redfish::registries::MessageEntry> - registry = - redfish::registries::getRegistryFromPrefix(it); - - if (std::any_of( - registry.begin(), registry.end(), - [&id](const redfish::registries::MessageEntry& - messageEntry) { - return id == messageEntry.first; - })) - { - validId = true; - break; - } - } - - if (!validId) - { - messages::propertyValueNotInList(asyncResp->res, id, - "MessageIds"); - return; + validId = true; + break; } } - subValue->registryMsgIds = *msgIds; - } - - if (retryPolicy) - { - if (std::find(supportedRetryPolicies.begin(), - supportedRetryPolicies.end(), - *retryPolicy) == supportedRetryPolicies.end()) + if (!validId) { - messages::propertyValueNotInList( - asyncResp->res, *retryPolicy, "DeliveryRetryPolicy"); + messages::propertyValueNotInList(asyncResp->res, id, + "MessageIds"); return; } - subValue->retryPolicy = *retryPolicy; } - else + + subValue->registryMsgIds = *msgIds; + } + + if (retryPolicy) + { + if (std::find(supportedRetryPolicies.begin(), + supportedRetryPolicies.end(), + *retryPolicy) == supportedRetryPolicies.end()) { - // Default "TerminateAfterRetries" - subValue->retryPolicy = "TerminateAfterRetries"; + messages::propertyValueNotInList(asyncResp->res, *retryPolicy, + "DeliveryRetryPolicy"); + return; } - - if (mrdJsonArray) + subValue->retryPolicy = *retryPolicy; + } + else + { + // Default "TerminateAfterRetries" + subValue->retryPolicy = "TerminateAfterRetries"; + } + + if (mrdJsonArray) + { + for (nlohmann::json& mrdObj : *mrdJsonArray) { - for (nlohmann::json& mrdObj : *mrdJsonArray) - { - std::string mrdUri; + std::string mrdUri; - if (!json_util::readJson(mrdObj, asyncResp->res, - "@odata.id", mrdUri)) + if (!json_util::readJson(mrdObj, asyncResp->res, "@odata.id", + mrdUri)) - { - return; - } - subValue->metricReportDefinitions.emplace_back(mrdUri); + { + return; } + subValue->metricReportDefinitions.emplace_back(mrdUri); } - - std::string id = - EventServiceManager::getInstance().addSubscription(subValue); - if (id.empty()) - { - messages::internalError(asyncResp->res); - return; - } - - messages::created(asyncResp->res); - asyncResp->res.addHeader( - "Location", "/redfish/v1/EventService/Subscriptions/" + id); + } + + std::string id = + EventServiceManager::getInstance().addSubscription(subValue); + if (id.empty()) + { + messages::internalError(asyncResp->res); + return; + } + + messages::created(asyncResp->res); + asyncResp->res.addHeader( + "Location", "/redfish/v1/EventService/Subscriptions/" + id); }); } @@ -499,56 +488,48 @@ 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->res)) - { - 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_7_0.EventDestination"; - asyncResp->res.jsonValue["Protocol"] = "Redfish"; - asyncResp->res.jsonValue["@odata.id"] = - "/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; - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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_7_0.EventDestination"; + asyncResp->res.jsonValue["Protocol"] = "Redfish"; + asyncResp->res.jsonValue["@odata.id"] = + "/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; + }); BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/<str>/") // The below privilege is wrong, it should be ConfigureManager OR // ConfigureSelf @@ -559,76 +540,72 @@ 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->res)) - { - 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>> headers; - - if (!json_util::readJsonPatch(req, asyncResp->res, "Context", - context, "DeliveryRetryPolicy", - retryPolicy, "HttpHeaders", - headers)) - { - return; - } - - if (context) - { - subValue->customText = *context; - } - - if (headers) - { - boost::beast::http::fields fields; - for (const nlohmann::json& headerChunk : *headers) - { - for (auto& it : headerChunk.items()) - { - const std::string* value = - it.value().get_ptr<const std::string*>(); - if (value == nullptr) - { - messages::propertyValueFormatError( - asyncResp->res, - it.value().dump(2, ' ', true), - "HttpHeaders/" + it.key()); - return; - } - fields.set(it.key(), *value); - } - } - subValue->httpHeaders = fields; - } - - if (retryPolicy) + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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>> headers; + + if (!json_util::readJsonPatch(req, asyncResp->res, "Context", context, + "DeliveryRetryPolicy", retryPolicy, + "HttpHeaders", headers)) + { + return; + } + + if (context) + { + subValue->customText = *context; + } + + if (headers) + { + boost::beast::http::fields fields; + for (const nlohmann::json& headerChunk : *headers) + { + for (auto& it : headerChunk.items()) { - if (std::find(supportedRetryPolicies.begin(), - supportedRetryPolicies.end(), - *retryPolicy) == supportedRetryPolicies.end()) + const std::string* value = + it.value().get_ptr<const std::string*>(); + if (value == nullptr) { - messages::propertyValueNotInList(asyncResp->res, - *retryPolicy, - "DeliveryRetryPolicy"); + messages::propertyValueFormatError( + asyncResp->res, it.value().dump(2, ' ', true), + "HttpHeaders/" + it.key()); return; } - subValue->retryPolicy = *retryPolicy; - subValue->updateRetryPolicy(); + fields.set(it.key(), *value); } + } + subValue->httpHeaders = fields; + } + + if (retryPolicy) + { + if (std::find(supportedRetryPolicies.begin(), + supportedRetryPolicies.end(), + *retryPolicy) == supportedRetryPolicies.end()) + { + messages::propertyValueNotInList(asyncResp->res, *retryPolicy, + "DeliveryRetryPolicy"); + return; + } + subValue->retryPolicy = *retryPolicy; + subValue->updateRetryPolicy(); + } - 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 @@ -639,19 +616,17 @@ 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->res)) - { - return; - } - if (!EventServiceManager::getInstance().isSubscriptionExist( - param)) - { - asyncResp->res.result( - boost::beast::http::status::not_found); - return; - } - EventServiceManager::getInstance().deleteSubscription(param); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + 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/health.hpp b/redfish-core/lib/health.hpp index 254f8e9203..c7f296029a 100644 --- a/redfish-core/lib/health.hpp +++ b/redfish-core/lib/health.hpp @@ -196,12 +196,12 @@ struct HealthPopulate : std::enable_shared_from_this<HealthPopulate> crow::connections::systemBus->async_method_call( [self](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreePathsResponse& resp) { - if (ec || resp.size() != 1) - { - // no global item, or too many - return; - } - self->globalInventoryPath = resp[0]; + if (ec || resp.size() != 1) + { + // no global item, or too many + return; + } + self->globalInventoryPath = resp[0]; }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -216,22 +216,21 @@ struct HealthPopulate : std::enable_shared_from_this<HealthPopulate> crow::connections::systemBus->async_method_call( [self](const boost::system::error_code ec, const dbus::utility::ManagedObjectType& resp) { - if (ec) - { - return; - } - self->statuses = resp; - for (auto it = self->statuses.begin(); - it != self->statuses.end();) + if (ec) + { + return; + } + self->statuses = resp; + for (auto it = self->statuses.begin(); it != self->statuses.end();) + { + if (boost::ends_with(it->first.str, "critical") || + boost::ends_with(it->first.str, "warning")) { - if (boost::ends_with(it->first.str, "critical") || - boost::ends_with(it->first.str, "warning")) - { - it++; - continue; - } - it = self->statuses.erase(it); + it++; + continue; } + it = self->statuses.erase(it); + } }, "xyz.openbmc_project.ObjectMapper", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); diff --git a/redfish-core/lib/hypervisor_system.hpp b/redfish-core/lib/hypervisor_system.hpp index 500dc04c89..1edece78ec 100644 --- a/redfish-core/lib/hypervisor_system.hpp +++ b/redfish-core/lib/hypervisor_system.hpp @@ -40,56 +40,55 @@ inline void getHypervisorState(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "xyz.openbmc_project.State.Host", "CurrentHostState", [aResp](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") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "Enabled"; - } - else if (hostState == "xyz.openbmc_project.State.Host.HostState." - "Quiesced") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "Quiesced"; - } - else if (hostState == "xyz.openbmc_project.State.Host.HostState." - "Standby") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; - } - else if (hostState == "xyz.openbmc_project.State.Host.HostState." - "TransitioningToRunning") - { - aResp->res.jsonValue["PowerState"] = "PoweringOn"; - aResp->res.jsonValue["Status"]["State"] = "Starting"; - } - else if (hostState == "xyz.openbmc_project.State.Host.HostState." - "TransitioningToOff") - { - aResp->res.jsonValue["PowerState"] = "PoweringOff"; - aResp->res.jsonValue["Status"]["State"] = "Enabled"; - } - else if (hostState == - "xyz.openbmc_project.State.Host.HostState.Off") - { - aResp->res.jsonValue["PowerState"] = "Off"; - aResp->res.jsonValue["Status"]["State"] = "Disabled"; - } - else - { - messages::internalError(aResp->res); - return; - } + BMCWEB_LOG_DEBUG << "Hypervisor state: " << hostState; + // Verify Host State + if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "Enabled"; + } + else if (hostState == "xyz.openbmc_project.State.Host.HostState." + "Quiesced") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "Quiesced"; + } + else if (hostState == "xyz.openbmc_project.State.Host.HostState." + "Standby") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "StandbyOffline"; + } + else if (hostState == "xyz.openbmc_project.State.Host.HostState." + "TransitioningToRunning") + { + aResp->res.jsonValue["PowerState"] = "PoweringOn"; + aResp->res.jsonValue["Status"]["State"] = "Starting"; + } + else if (hostState == "xyz.openbmc_project.State.Host.HostState." + "TransitioningToOff") + { + aResp->res.jsonValue["PowerState"] = "PoweringOff"; + aResp->res.jsonValue["Status"]["State"] = "Enabled"; + } + else if (hostState == "xyz.openbmc_project.State.Host.HostState.Off") + { + aResp->res.jsonValue["PowerState"] = "Off"; + aResp->res.jsonValue["Status"]["State"] = "Disabled"; + } + else + { + messages::internalError(aResp->res); + return; + } }); } @@ -112,35 +111,35 @@ 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(aResp->res); - return; - } + if (objInfo.size() > 1) + { + // More then one hypervisor object is not supported and is an + // error + messages::internalError(aResp->res); + return; + } - // Object present so system support limited ComputerSystem Action - aResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = { - {"target", - "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"}, - {"@Redfish.ActionInfo", - "/redfish/v1/Systems/hypervisor/ResetActionInfo"}}; + // Object present so system support limited ComputerSystem Action + aResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] = { + {"target", + "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset"}, + {"@Redfish.ActionInfo", + "/redfish/v1/Systems/hypervisor/ResetActionInfo"}}; }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -321,21 +320,21 @@ void getHypervisorIfaceData(const std::string& ethIfaceId, callback{std::forward<CallbackFunc>(callback)}]( const boost::system::error_code error, const dbus::utility::ManagedObjectType& resp) { - EthernetInterfaceData ethData{}; - boost::container::flat_set<IPv4AddressData> ipv4Data; - if (error) - { - callback(false, ethData, ipv4Data); - return; - } + EthernetInterfaceData ethData{}; + boost::container::flat_set<IPv4AddressData> ipv4Data; + if (error) + { + 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); }, "xyz.openbmc_project.Settings", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -359,12 +358,12 @@ inline void << " on Iface: " << ethIfaceId; crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error " << ec; - return; - } - BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set"; + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error " << ec; + return; + } + BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set"; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", @@ -391,12 +390,12 @@ inline void crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error " << ec; - return; - } - BMCWEB_LOG_DEBUG << "SubnetMask is Set"; + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error " << ec; + return; + } + BMCWEB_LOG_DEBUG << "SubnetMask is Set"; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/hypervisor/" + ethIfaceId + "/ipv4/addr0", @@ -423,12 +422,12 @@ inline void crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error " << ec; - return; - } - BMCWEB_LOG_DEBUG << "Default Gateway is Set"; + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error " << ec; + return; + } + BMCWEB_LOG_DEBUG << "Default Gateway is Set"; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/hypervisor", @@ -523,12 +522,12 @@ inline void setDHCPEnabled(const std::string& ifaceId, const std::string dhcp = getDhcpEnabledEnumeration(ipv4DHCPEnabled, false); crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/hypervisor/" + ifaceId, @@ -552,13 +551,13 @@ inline void setDHCPEnabled(const std::string& ifaceId, } crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error " << ec; - messages::internalError(asyncResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set"; + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error " << ec; + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Hypervisor IPaddress Origin is Set"; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", @@ -687,10 +686,10 @@ inline void asyncResp->res.jsonValue["HostName"] = hostName; 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.Settings", "/xyz/openbmc_project/network/hypervisor", @@ -705,12 +704,12 @@ inline void { crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/hypervisor/" + ifaceId + "/ipv4/addr0", @@ -730,48 +729,45 @@ inline void requestRoutesHypervisorSystems(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->res)) - { - return; - } - 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"] = "/redfish/v1/Managers/bmc"; - managedBy.push_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" - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + 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"] = "/redfish/v1/Managers/bmc"; + managedBy.push_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" }); + }); /** * HypervisorInterfaceCollection class to handle the GET and PATCH on @@ -780,62 +776,58 @@ inline void requestRoutesHypervisorSystems(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/") .privileges(redfish::privileges::getEthernetInterfaceCollection) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + const std::array<const char*, 1> interfaces = { + "xyz.openbmc_project.Network.EthernetInterface"}; + + crow::connections::systemBus->async_method_call( + [asyncResp]( + const boost::system::error_code error, + const dbus::utility::MapperGetSubTreePathsResponse& ifaceList) { + if (error) { + messages::resourceNotFound(asyncResp->res, "System", + "hypervisor"); return; } - const std::array<const char*, 1> interfaces = { - "xyz.openbmc_project.Network.EthernetInterface"}; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code error, - const dbus::utility::MapperGetSubTreePathsResponse& - ifaceList) { - if (error) - { - 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()) - { - continue; - } - nlohmann::json::object_t ethIface; - ethIface["@odata.id"] = - "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + - name; - ifaceArray.push_back(std::move(ethIface)); - } - asyncResp->res.jsonValue["Members@odata.count"] = - ifaceArray.size(); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", - "/xyz/openbmc_project/network/hypervisor", 0, interfaces); + 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"] = + "/redfish/v1/Systems/hypervisor/EthernetInterfaces/" + name; + ifaceArray.push_back(std::move(ethIface)); + } + asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", + "/xyz/openbmc_project/network/hypervisor", 0, interfaces); }); BMCWEB_ROUTE(app, @@ -845,153 +837,147 @@ inline void requestRoutesHypervisorSystems(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - getHypervisorIfaceData(id, [asyncResp, - ifaceId{std::string(id)}]( - const bool& success, - const EthernetInterfaceData& - ethData, - const boost::container::flat_set< - IPv4AddressData>& ipv4Data) { - if (!success) - { - messages::resourceNotFound( - asyncResp->res, "EthernetInterface", ifaceId); - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#EthernetInterface.v1_5_1.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 (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + getHypervisorIfaceData( + id, + [asyncResp, ifaceId{std::string(id)}]( + const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>& ipv4Data) { + if (!success) + { + messages::resourceNotFound(asyncResp->res, "EthernetInterface", + ifaceId); + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#EthernetInterface.v1_5_1.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); }); + }); BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/EthernetInterfaces/<str>/") .privileges(redfish::privileges::patchEthernetInterface) - .methods( - boost::beast::http::verb:: - patch)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& ifaceId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<std::string> hostName; - std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; - std::optional<nlohmann::json> ipv4Addresses; - std::optional<nlohmann::json> dhcpv4; - std::optional<bool> ipv4DHCPEnabled; - - if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", - hostName, "IPv4StaticAddresses", - ipv4StaticAddresses, "IPv4Addresses", - ipv4Addresses, "DHCPv4", dhcpv4)) + .methods(boost::beast::http::verb::patch)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& ifaceId) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<std::string> hostName; + std::optional<std::vector<nlohmann::json>> ipv4StaticAddresses; + std::optional<nlohmann::json> ipv4Addresses; + std::optional<nlohmann::json> dhcpv4; + std::optional<bool> ipv4DHCPEnabled; + + if (!json_util::readJsonPatch(req, asyncResp->res, "HostName", hostName, + "IPv4StaticAddresses", + ipv4StaticAddresses, "IPv4Addresses", + ipv4Addresses, "DHCPv4", dhcpv4)) + { + return; + } + + if (ipv4Addresses) + { + messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); + return; + } + + if (dhcpv4) + { + if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", + ipv4DHCPEnabled)) { return; } + } - if (ipv4Addresses) + getHypervisorIfaceData( + ifaceId, + [asyncResp, ifaceId, hostName = std::move(hostName), + ipv4StaticAddresses = std::move(ipv4StaticAddresses), + ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)]( + const bool& success, const EthernetInterfaceData& ethData, + const boost::container::flat_set<IPv4AddressData>&) { + if (!success) { - messages::propertyNotWritable(asyncResp->res, "IPv4Addresses"); + messages::resourceNotFound(asyncResp->res, "EthernetInterface", + ifaceId); return; } - if (dhcpv4) + if (ipv4StaticAddresses) { - if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", - ipv4DHCPEnabled)) + const nlohmann::json& ipv4Static = *ipv4StaticAddresses; + if (ipv4Static.begin() == ipv4Static.end()) { + messages::propertyValueTypeError( + asyncResp->res, + ipv4Static.dump( + 2, ' ', true, + nlohmann::json::error_handler_t::replace), + "IPv4StaticAddresses"); return; } - } - - getHypervisorIfaceData( - ifaceId, - [asyncResp, ifaceId, hostName = std::move(hostName), - ipv4StaticAddresses = std::move(ipv4StaticAddresses), - ipv4DHCPEnabled, dhcpv4 = std::move(dhcpv4)]( - const bool& success, const EthernetInterfaceData& ethData, - const boost::container::flat_set<IPv4AddressData>&) { - if (!success) - { - messages::resourceNotFound( - asyncResp->res, "EthernetInterface", ifaceId); - return; - } - if (ipv4StaticAddresses) - { - const nlohmann::json& ipv4Static = *ipv4StaticAddresses; - if (ipv4Static.begin() == ipv4Static.end()) - { - messages::propertyValueTypeError( - asyncResp->res, - ipv4Static.dump( - 2, ' ', true, - nlohmann::json::error_handler_t::replace), - "IPv4StaticAddresses"); - return; - } - - // One and only one hypervisor instance supported - if (ipv4Static.size() != 1) - { - messages::propertyValueFormatError( - asyncResp->res, - ipv4Static.dump( - 2, ' ', true, - nlohmann::json::error_handler_t::replace), - "IPv4StaticAddresses"); - return; - } + // One and only one hypervisor instance supported + if (ipv4Static.size() != 1) + { + messages::propertyValueFormatError( + asyncResp->res, + ipv4Static.dump( + 2, ' ', true, + nlohmann::json::error_handler_t::replace), + "IPv4StaticAddresses"); + return; + } - const nlohmann::json& 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 ((ipv4Json.is_null()) && - (translateDhcpEnabledToBool(ethData.dhcpEnabled, - true))) - { - BMCWEB_LOG_INFO - << "Ignoring the delete on ipv4StaticAddresses " - "as the interface is DHCP enabled"; - } - else - { - handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, - asyncResp); - } - } + const nlohmann::json& 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 ((ipv4Json.is_null()) && + (translateDhcpEnabledToBool(ethData.dhcpEnabled, true))) + { + BMCWEB_LOG_INFO + << "Ignoring the delete on ipv4StaticAddresses " + "as the interface is DHCP enabled"; + } + else + { + handleHypervisorIPv4StaticPatch(ifaceId, ipv4Static, + asyncResp); + } + } - if (hostName) - { - handleHostnamePatch(*hostName, asyncResp); - } + if (hostName) + { + handleHostnamePatch(*hostName, asyncResp); + } - if (dhcpv4) - { - setDHCPEnabled(ifaceId, *ipv4DHCPEnabled, asyncResp); - } + if (dhcpv4) + { + 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); - }); - asyncResp->res.result(boost::beast::http::status::accepted); + // 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); }); BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/ResetActionInfo/") @@ -999,69 +985,65 @@ inline void requestRoutesHypervisorSystems(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->res)) - { - return; - } - // Only return action info if hypervisor D-Bus object present - crow::connections::systemBus->async_method_call( - [asyncResp]( - const boost::system::error_code ec, + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + // Only return action info if hypervisor D-Bus object present + crow::connections::systemBus->async_method_call( + [asyncResp](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; + if (ec) + { + 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; - } + // 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.push_back("On"); - parameter["AllowableValues"] = std::move(allowed); - parameters.push_back(std::move(parameter)); - asyncResp->res.jsonValue["Parameters"] = - std::move(parameters); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", - "/xyz/openbmc_project/state/hypervisor0", - std::array<const char*, 1>{ - "xyz.openbmc_project.State.Host"}); - }); + // 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.push_back("On"); + parameter["AllowableValues"] = std::move(allowed); + parameters.push_back(std::move(parameter)); + asyncResp->res.jsonValue["Parameters"] = std::move(parameters); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", + "/xyz/openbmc_project/state/hypervisor0", + std::array<const char*, 1>{"xyz.openbmc_project.State.Host"}); + }); BMCWEB_ROUTE(app, "/redfish/v1/Systems/hypervisor/Actions/ComputerSystem.Reset/") @@ -1069,67 +1051,64 @@ inline void requestRoutesHypervisorSystems(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->res)) - { - return; - } - std::optional<std::string> resetType; - if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", - resetType)) - { - // readJson adds appropriate error to response - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<std::string> resetType; + if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", + resetType)) + { + // readJson adds appropriate error to response + return; + } + + if (!resetType) + { + messages::actionParameterMissing( + asyncResp->res, "ComputerSystem.Reset", "ResetType"); + return; + } + + // Hypervisor object only support On operation + if (resetType != "On") + { + messages::propertyValueNotInList(asyncResp->res, *resetType, + "ResetType"); + return; + } + + std::string command = "xyz.openbmc_project.State.Host.Transition.On"; - if (!resetType) + crow::connections::systemBus->async_method_call( + [asyncResp, resetType](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + if (ec.value() == boost::asio::error::invalid_argument) { - messages::actionParameterMissing( - asyncResp->res, "ComputerSystem.Reset", "ResetType"); + messages::actionParameterNotSupported(asyncResp->res, + *resetType, "Reset"); return; } - // Hypervisor object only support On operation - if (resetType != "On") + if (ec.value() == boost::asio::error::host_unreachable) { - messages::propertyValueNotInList(asyncResp->res, *resetType, - "ResetType"); + messages::resourceNotFound(asyncResp->res, "Actions", + "Reset"); return; } - std::string command = - "xyz.openbmc_project.State.Host.Transition.On"; - - crow::connections::systemBus->async_method_call( - [asyncResp, resetType](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - if (ec.value() == - boost::asio::error::invalid_argument) - { - messages::actionParameterNotSupported( - asyncResp->res, *resetType, "Reset"); - return; - } - - if (ec.value() == - boost::asio::error::host_unreachable) - { - messages::resourceNotFound(asyncResp->res, - "Actions", "Reset"); - return; - } - - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); - }, - "xyz.openbmc_project.State.Hypervisor", - "/xyz/openbmc_project/state/hypervisor0", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.State.Host", "RequestedHostTransition", - dbus::utility::DbusVariantType{std::move(command)}); - }); + messages::internalError(asyncResp->res); + return; + } + messages::success(asyncResp->res); + }, + "xyz.openbmc_project.State.Hypervisor", + "/xyz/openbmc_project/state/hypervisor0", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.State.Host", "RequestedHostTransition", + dbus::utility::DbusVariantType{std::move(command)}); + }); } } // namespace redfish::hypervisor diff --git a/redfish-core/lib/led.hpp b/redfish-core/lib/led.hpp index 6f5f5f121b..902e5c86c5 100644 --- a/redfish-core/lib/led.hpp +++ b/redfish-core/lib/led.hpp @@ -41,51 +41,51 @@ inline void "/xyz/openbmc_project/led/groups/enclosure_identify_blink", "xyz.openbmc_project.Led.Group", "Asserted", [aResp](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) + // 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, missmatch in property type"; + messages::internalError(aResp->res); + return; + } + + // Blinking ON, no need to check enclosure_identify assert. + if (!ec && blinking) + { + aResp->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", + [aResp](const boost::system::error_code ec2, const bool ledOn) { + if (ec2 == boost::system::errc::invalid_argument) { BMCWEB_LOG_DEBUG - << "Get identity blinking LED failed, missmatch in property type"; + << "Get enclosure identity led failed, missmatch in property type"; messages::internalError(aResp->res); return; } - // Blinking ON, no need to check enclosure_identify assert. - if (!ec && blinking) + if (ec2) { - aResp->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", - [aResp](const boost::system::error_code ec2, const bool ledOn) { - if (ec2 == boost::system::errc::invalid_argument) - { - BMCWEB_LOG_DEBUG - << "Get enclosure identity led failed, missmatch in property type"; - messages::internalError(aResp->res); - return; - } - - if (ec2) - { - return; - } - - if (ledOn) - { - aResp->res.jsonValue["IndicatorLED"] = "Lit"; - } - else - { - aResp->res.jsonValue["IndicatorLED"] = "Off"; - } - }); + if (ledOn) + { + aResp->res.jsonValue["IndicatorLED"] = "Lit"; + } + else + { + aResp->res.jsonValue["IndicatorLED"] = "Off"; + } + }); }); } @@ -122,31 +122,31 @@ inline void crow::connections::systemBus->async_method_call( [aResp, ledOn, ledBlinkng](const boost::system::error_code ec) mutable { - if (ec) + 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) { - // 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; - } + ledOn = true; } - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec2) { - if (ec2) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec2; - messages::internalError(aResp->res); - return; - } - messages::success(aResp->res); - }, - "xyz.openbmc_project.LED.GroupManager", - "/xyz/openbmc_project/led/groups/enclosure_identify", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Led.Group", "Asserted", - dbus::utility::DbusVariantType(ledOn)); + } + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec2) { + if (ec2) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec2; + messages::internalError(aResp->res); + return; + } + messages::success(aResp->res); + }, + "xyz.openbmc_project.LED.GroupManager", + "/xyz/openbmc_project/led/groups/enclosure_identify", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Led.Group", "Asserted", + dbus::utility::DbusVariantType(ledOn)); }, "xyz.openbmc_project.LED.GroupManager", "/xyz/openbmc_project/led/groups/enclosure_identify_blink", @@ -171,44 +171,44 @@ inline void "/xyz/openbmc_project/led/groups/enclosure_identify_blink", "xyz.openbmc_project.Led.Group", "Asserted", [aResp](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) + // 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, missmatch in property type"; + messages::internalError(aResp->res); + return; + } + + // Blinking ON, no need to check enclosure_identify assert. + if (!ec && blinking) + { + aResp->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", + [aResp](const boost::system::error_code ec2, const bool ledOn) { + if (ec2 == boost::system::errc::invalid_argument) { BMCWEB_LOG_DEBUG - << "Get identity blinking LED failed, missmatch in property type"; + << "Get enclosure identity led failed, missmatch in property type"; messages::internalError(aResp->res); return; } - // Blinking ON, no need to check enclosure_identify assert. - if (!ec && blinking) + if (ec2) { - aResp->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", - [aResp](const boost::system::error_code ec2, const bool ledOn) { - if (ec2 == boost::system::errc::invalid_argument) - { - BMCWEB_LOG_DEBUG - << "Get enclosure identity led failed, missmatch in property type"; - messages::internalError(aResp->res); - return; - } - - if (ec2) - { - return; - } - - aResp->res.jsonValue["LocationIndicatorActive"] = ledOn; - }); + aResp->res.jsonValue["LocationIndicatorActive"] = ledOn; + }); }); } @@ -228,26 +228,26 @@ inline void crow::connections::systemBus->async_method_call( [aResp, ledState](const boost::system::error_code ec) mutable { - if (ec) - { - // Some systems may not have enclosure_identify_blink object so - // lets set enclosure_identify state also if - // enclosure_identify_blink failed - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec2) { - if (ec2) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec2; - messages::internalError(aResp->res); - return; - } - }, - "xyz.openbmc_project.LED.GroupManager", - "/xyz/openbmc_project/led/groups/enclosure_identify", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Led.Group", "Asserted", - dbus::utility::DbusVariantType(ledState)); - } + if (ec) + { + // Some systems may not have enclosure_identify_blink object so + // lets set enclosure_identify state also if + // enclosure_identify_blink failed + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec2) { + if (ec2) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec2; + messages::internalError(aResp->res); + return; + } + }, + "xyz.openbmc_project.LED.GroupManager", + "/xyz/openbmc_project/led/groups/enclosure_identify", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Led.Group", "Asserted", + dbus::utility::DbusVariantType(ledState)); + } }, "xyz.openbmc_project.LED.GroupManager", "/xyz/openbmc_project/led/groups/enclosure_identify_blink", diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp index 0a78009b95..3572ccaf65 100644 --- a/redfish-core/lib/log_services.hpp +++ b/redfish-core/lib/log_services.hpp @@ -63,10 +63,10 @@ static const Message* getMessageFromRegistry(const std::string& messageKey, const std::span<const MessageEntry> registry) { - std::span<const MessageEntry>::iterator messageIt = std::find_if( - registry.begin(), registry.end(), - [&messageKey](const MessageEntry& messageEntry) { - return std::strcmp(messageEntry.first, messageKey.c_str()) == 0; + std::span<const MessageEntry>::iterator messageIt = + std::find_if(registry.begin(), registry.end(), + [&messageKey](const MessageEntry& messageEntry) { + return std::strcmp(messageEntry.first, messageKey.c_str()) == 0; }); if (messageIt != registry.end()) { @@ -349,142 +349,136 @@ inline void [asyncResp, dumpPath, dumpType](const boost::system::error_code ec, dbus::utility::ManagedObjectType& resp) { - 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; + } - nlohmann::json& entriesArray = asyncResp->res.jsonValue["Members"]; - entriesArray = nlohmann::json::array(); - std::string dumpEntryPath = - "/xyz/openbmc_project/dump/" + - std::string(boost::algorithm::to_lower_copy(dumpType)) + - "/entry/"; + nlohmann::json& entriesArray = asyncResp->res.jsonValue["Members"]; + entriesArray = nlohmann::json::array(); + std::string dumpEntryPath = + "/xyz/openbmc_project/dump/" + + std::string(boost::algorithm::to_lower_copy(dumpType)) + "/entry/"; - std::sort(resp.begin(), resp.end(), - [](const auto& l, const auto& r) { - return AlphanumLess<std::string>()( - l.first.filename(), r.first.filename()); - }); + std::sort(resp.begin(), resp.end(), [](const auto& l, const auto& r) { + return AlphanumLess<std::string>()(l.first.filename(), + r.first.filename()); + }); - for (auto& object : resp) + for (auto& object : resp) + { + if (object.first.str.find(dumpEntryPath) == std::string::npos) { - if (object.first.str.find(dumpEntryPath) == std::string::npos) - { - continue; - } - uint64_t timestamp = 0; - uint64_t size = 0; - std::string dumpStatus; - nlohmann::json thisEntry; + continue; + } + uint64_t timestamp = 0; + uint64_t size = 0; + std::string dumpStatus; + nlohmann::json thisEntry; - std::string entryID = object.first.filename(); - if (entryID.empty()) - { - continue; - } + std::string entryID = object.first.filename(); + if (entryID.empty()) + { + continue; + } - for (auto& interfaceMap : object.second) + for (auto& interfaceMap : object.second) + { + if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") { - if (interfaceMap.first == - "xyz.openbmc_project.Common.Progress") + for (const auto& propertyMap : interfaceMap.second) { - for (const auto& propertyMap : interfaceMap.second) + if (propertyMap.first == "Status") { - if (propertyMap.first == "Status") + const auto* status = + std::get_if<std::string>(&propertyMap.second); + if (status == nullptr) { - const auto* status = std::get_if<std::string>( - &propertyMap.second); - if (status == nullptr) - { - messages::internalError(asyncResp->res); - break; - } - dumpStatus = *status; + messages::internalError(asyncResp->res); + break; } + dumpStatus = *status; } } - else if (interfaceMap.first == - "xyz.openbmc_project.Dump.Entry") - { + } + else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") + { - for (auto& propertyMap : interfaceMap.second) + for (auto& propertyMap : interfaceMap.second) + { + if (propertyMap.first == "Size") { - if (propertyMap.first == "Size") + const auto* sizePtr = + std::get_if<uint64_t>(&propertyMap.second); + if (sizePtr == nullptr) { - const auto* sizePtr = - std::get_if<uint64_t>(&propertyMap.second); - if (sizePtr == nullptr) - { - messages::internalError(asyncResp->res); - break; - } - size = *sizePtr; + messages::internalError(asyncResp->res); break; } + size = *sizePtr; + break; } } - else if (interfaceMap.first == - "xyz.openbmc_project.Time.EpochTime") - { + } + else if (interfaceMap.first == + "xyz.openbmc_project.Time.EpochTime") + { - for (const auto& propertyMap : interfaceMap.second) + for (const auto& propertyMap : interfaceMap.second) + { + if (propertyMap.first == "Elapsed") { - if (propertyMap.first == "Elapsed") + const uint64_t* usecsTimeStamp = + std::get_if<uint64_t>(&propertyMap.second); + if (usecsTimeStamp == nullptr) { - const uint64_t* usecsTimeStamp = - std::get_if<uint64_t>(&propertyMap.second); - if (usecsTimeStamp == nullptr) - { - messages::internalError(asyncResp->res); - break; - } - timestamp = (*usecsTimeStamp / 1000 / 1000); + messages::internalError(asyncResp->res); break; } + timestamp = (*usecsTimeStamp / 1000 / 1000); + break; } } } + } - 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_8_0.LogEntry"; - thisEntry["@odata.id"] = dumpPath + entryID; - thisEntry["Id"] = entryID; - thisEntry["EntryType"] = "Event"; - thisEntry["Created"] = - crow::utility::getDateTimeUint(timestamp); - thisEntry["Name"] = dumpType + " Dump Entry"; + thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry"; + thisEntry["@odata.id"] = dumpPath + entryID; + thisEntry["Id"] = entryID; + thisEntry["EntryType"] = "Event"; + thisEntry["Created"] = crow::utility::getDateTimeUint(timestamp); + thisEntry["Name"] = dumpType + " Dump Entry"; - thisEntry["AdditionalDataSizeBytes"] = size; + thisEntry["AdditionalDataSizeBytes"] = size; - if (dumpType == "BMC") - { - thisEntry["DiagnosticDataType"] = "Manager"; - thisEntry["AdditionalDataURI"] = - "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/" + - entryID + "/attachment"; - } - else if (dumpType == "System") - { - thisEntry["DiagnosticDataType"] = "OEM"; - thisEntry["OEMDiagnosticDataType"] = "System"; - thisEntry["AdditionalDataURI"] = - "/redfish/v1/Systems/system/LogServices/Dump/Entries/" + - entryID + "/attachment"; - } - entriesArray.push_back(std::move(thisEntry)); + if (dumpType == "BMC") + { + thisEntry["DiagnosticDataType"] = "Manager"; + thisEntry["AdditionalDataURI"] = + "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/" + + entryID + "/attachment"; } - asyncResp->res.jsonValue["Members@odata.count"] = - entriesArray.size(); + else if (dumpType == "System") + { + thisEntry["DiagnosticDataType"] = "OEM"; + thisEntry["OEMDiagnosticDataType"] = "System"; + thisEntry["AdditionalDataURI"] = + "/redfish/v1/Systems/system/LogServices/Dump/Entries/" + + entryID + "/attachment"; + } + entriesArray.push_back(std::move(thisEntry)); + } + asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size(); }, "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -519,137 +513,132 @@ inline void [asyncResp, entryID, dumpPath, dumpType](const boost::system::error_code ec, dbus::utility::ManagedObjectType& resp) { - 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; + } - bool foundDumpEntry = false; - std::string dumpEntryPath = - "/xyz/openbmc_project/dump/" + - std::string(boost::algorithm::to_lower_copy(dumpType)) + - "/entry/"; + bool foundDumpEntry = false; + std::string dumpEntryPath = + "/xyz/openbmc_project/dump/" + + std::string(boost::algorithm::to_lower_copy(dumpType)) + "/entry/"; - for (const auto& objectPath : resp) + for (const auto& objectPath : resp) + { + if (objectPath.first.str != dumpEntryPath + entryID) { - if (objectPath.first.str != dumpEntryPath + entryID) - { - continue; - } + continue; + } - foundDumpEntry = true; - uint64_t timestamp = 0; - uint64_t size = 0; - std::string dumpStatus; + foundDumpEntry = true; + uint64_t timestamp = 0; + uint64_t size = 0; + std::string dumpStatus; - for (const auto& interfaceMap : objectPath.second) + for (const auto& interfaceMap : objectPath.second) + { + if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") { - if (interfaceMap.first == - "xyz.openbmc_project.Common.Progress") + for (const auto& propertyMap : interfaceMap.second) { - for (const auto& propertyMap : interfaceMap.second) + if (propertyMap.first == "Status") { - if (propertyMap.first == "Status") + const std::string* status = + std::get_if<std::string>(&propertyMap.second); + if (status == nullptr) { - const std::string* status = - std::get_if<std::string>( - &propertyMap.second); - if (status == nullptr) - { - messages::internalError(asyncResp->res); - break; - } - dumpStatus = *status; + messages::internalError(asyncResp->res); + break; } + dumpStatus = *status; } } - else if (interfaceMap.first == - "xyz.openbmc_project.Dump.Entry") + } + else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") + { + for (const auto& propertyMap : interfaceMap.second) { - for (const auto& propertyMap : interfaceMap.second) + if (propertyMap.first == "Size") { - if (propertyMap.first == "Size") + const uint64_t* sizePtr = + std::get_if<uint64_t>(&propertyMap.second); + if (sizePtr == nullptr) { - const uint64_t* sizePtr = - std::get_if<uint64_t>(&propertyMap.second); - if (sizePtr == nullptr) - { - messages::internalError(asyncResp->res); - break; - } - size = *sizePtr; + messages::internalError(asyncResp->res); break; } + size = *sizePtr; + break; } } - else if (interfaceMap.first == - "xyz.openbmc_project.Time.EpochTime") + } + else if (interfaceMap.first == + "xyz.openbmc_project.Time.EpochTime") + { + for (const auto& propertyMap : interfaceMap.second) { - for (const auto& propertyMap : interfaceMap.second) + if (propertyMap.first == "Elapsed") { - if (propertyMap.first == "Elapsed") + const uint64_t* usecsTimeStamp = + std::get_if<uint64_t>(&propertyMap.second); + if (usecsTimeStamp == nullptr) { - const uint64_t* usecsTimeStamp = - std::get_if<uint64_t>(&propertyMap.second); - if (usecsTimeStamp == nullptr) - { - messages::internalError(asyncResp->res); - break; - } - timestamp = *usecsTimeStamp / 1000 / 1000; + messages::internalError(asyncResp->res); break; } + timestamp = *usecsTimeStamp / 1000 / 1000; + break; } } } + } - 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; - } + 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_8_0.LogEntry"; - asyncResp->res.jsonValue["@odata.id"] = dumpPath + entryID; - asyncResp->res.jsonValue["Id"] = entryID; - asyncResp->res.jsonValue["EntryType"] = "Event"; - asyncResp->res.jsonValue["Created"] = - crow::utility::getDateTimeUint(timestamp); - asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; + asyncResp->res.jsonValue["@odata.type"] = + "#LogEntry.v1_8_0.LogEntry"; + asyncResp->res.jsonValue["@odata.id"] = dumpPath + entryID; + asyncResp->res.jsonValue["Id"] = entryID; + asyncResp->res.jsonValue["EntryType"] = "Event"; + asyncResp->res.jsonValue["Created"] = + crow::utility::getDateTimeUint(timestamp); + asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry"; - asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; + asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size; - if (dumpType == "BMC") - { - asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; - asyncResp->res.jsonValue["AdditionalDataURI"] = - "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/" + - entryID + "/attachment"; - } - else if (dumpType == "System") - { - asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; - asyncResp->res.jsonValue["OEMDiagnosticDataType"] = - "System"; - asyncResp->res.jsonValue["AdditionalDataURI"] = - "/redfish/v1/Systems/system/LogServices/Dump/Entries/" + - entryID + "/attachment"; - } + if (dumpType == "BMC") + { + asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager"; + asyncResp->res.jsonValue["AdditionalDataURI"] = + "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/" + + entryID + "/attachment"; } - if (!foundDumpEntry) + else if (dumpType == "System") { - BMCWEB_LOG_ERROR << "Can't find Dump Entry"; - messages::internalError(asyncResp->res); - return; + asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM"; + asyncResp->res.jsonValue["OEMDiagnosticDataType"] = "System"; + asyncResp->res.jsonValue["AdditionalDataURI"] = + "/redfish/v1/Systems/system/LogServices/Dump/Entries/" + + entryID + "/attachment"; } + } + if (!foundDumpEntry) + { + BMCWEB_LOG_ERROR << "Can't find Dump Entry"; + messages::internalError(asyncResp->res); + return; + } }, "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -659,8 +648,8 @@ inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& entryID, const std::string& dumpType) { - auto respHandler = [asyncResp, - entryID](const boost::system::error_code ec) { + auto respHandler = + [asyncResp, entryID](const boost::system::error_code ec) { BMCWEB_LOG_DEBUG << "Dump Entry doDelete callback: Done"; if (ec) { @@ -693,36 +682,35 @@ inline void [dumpId, dumpPath, dumpType]( boost::system::error_code err, sdbusplus::message::message& m, const std::shared_ptr<task::TaskData>& taskData) { - if (err) - { - BMCWEB_LOG_ERROR << "Error in creating a dump"; - taskData->state = "Cancelled"; - return task::completed; - } + if (err) + { + BMCWEB_LOG_ERROR << "Error in creating a dump"; + taskData->state = "Cancelled"; + return task::completed; + } - dbus::utility::DBusInteracesMap interfacesList; + dbus::utility::DBusInteracesMap interfacesList; - sdbusplus::message::object_path objPath; + sdbusplus::message::object_path objPath; - m.read(objPath, interfacesList); + m.read(objPath, interfacesList); - if (objPath.str == - "/xyz/openbmc_project/dump/" + - std::string(boost::algorithm::to_lower_copy(dumpType)) + - "/entry/" + std::to_string(dumpId)) - { - nlohmann::json retMessage = messages::success(); - taskData->messages.emplace_back(retMessage); + if (objPath.str == + "/xyz/openbmc_project/dump/" + + std::string(boost::algorithm::to_lower_copy(dumpType)) + + "/entry/" + std::to_string(dumpId)) + { + nlohmann::json retMessage = messages::success(); + taskData->messages.emplace_back(retMessage); - std::string headerLoc = - "Location: " + dumpPath + std::to_string(dumpId); - taskData->payload->httpHeaders.emplace_back( - std::move(headerLoc)); + std::string headerLoc = + "Location: " + dumpPath + std::to_string(dumpId); + taskData->payload->httpHeaders.emplace_back(std::move(headerLoc)); - taskData->state = "Completed"; - return task::completed; - } + taskData->state = "Completed"; return task::completed; + } + return task::completed; }, "type='signal',interface='org.freedesktop.DBus.ObjectManager'," "member='InterfacesAdded', " @@ -804,16 +792,16 @@ inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, [asyncResp, payload(task::Payload(req)), dumpPath, dumpType](const boost::system::error_code ec, const uint32_t& dumpId) mutable { - if (ec) - { - BMCWEB_LOG_ERROR << "CreateDump resp_handler got error " << ec; - messages::internalError(asyncResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Dump Created. Id: " << dumpId; + if (ec) + { + BMCWEB_LOG_ERROR << "CreateDump resp_handler got error " << ec; + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Dump Created. Id: " << dumpId; - createDumpTaskCallback(std::move(payload), asyncResp, dumpId, - dumpPath, dumpType); + createDumpTaskCallback(std::move(payload), asyncResp, dumpId, dumpPath, + dumpType); }, "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/" + @@ -831,23 +819,23 @@ inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, [asyncResp, dumpType]( const boost::system::error_code ec, const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) { - if (ec) - { - BMCWEB_LOG_ERROR << "resp_handler got error " << ec; - messages::internalError(asyncResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_ERROR << "resp_handler got error " << ec; + messages::internalError(asyncResp->res); + return; + } - for (const std::string& path : subTreePaths) + for (const std::string& path : subTreePaths) + { + sdbusplus::message::object_path objPath(path); + std::string logID = objPath.filename(); + if (logID.empty()) { - sdbusplus::message::object_path objPath(path); - std::string logID = objPath.filename(); - if (logID.empty()) - { - continue; - } - deleteDumpEntry(asyncResp, logID, dumpType); + continue; } + deleteDumpEntry(asyncResp, logID, dumpType); + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -902,82 +890,79 @@ inline void requestRoutesSystemLogServiceCollection(App& app) */ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/") .privileges(redfish::privileges::getLogServiceCollection) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - 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"] = - "/redfish/v1/Systems/system/LogServices"; - 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"] = - "/redfish/v1/Systems/system/LogServices/EventLog"; - logServiceArray.push_back(std::move(eventLog)); + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"] = + "/redfish/v1/Systems/system/LogServices"; + 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"] = + "/redfish/v1/Systems/system/LogServices/EventLog"; + logServiceArray.push_back(std::move(eventLog)); #ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG - nlohmann::json::object_t dumpLog; - dumpLog["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Dump"; - logServiceArray.push_back(std::move(dumpLog)); + nlohmann::json::object_t dumpLog; + dumpLog["@odata.id"] = "/redfish/v1/Systems/system/LogServices/Dump"; + logServiceArray.push_back(std::move(dumpLog)); #endif #ifdef BMCWEB_ENABLE_REDFISH_CPU_LOG - nlohmann::json::object_t crashdump; - crashdump["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Crashdump"; - logServiceArray.push_back(std::move(crashdump)); + nlohmann::json::object_t crashdump; + crashdump["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Crashdump"; + logServiceArray.push_back(std::move(crashdump)); #endif #ifdef BMCWEB_ENABLE_REDFISH_HOST_LOGGER - nlohmann::json::object_t hostlogger; - hostlogger["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/HostLogger"; - logServiceArray.push_back(std::move(hostlogger)); + nlohmann::json::object_t hostlogger; + hostlogger["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/HostLogger"; + logServiceArray.push_back(std::move(hostlogger)); #endif - asyncResp->res.jsonValue["Members@odata.count"] = - logServiceArray.size(); + asyncResp->res.jsonValue["Members@odata.count"] = + logServiceArray.size(); - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreePathsResponse& - subtreePath) { - if (ec) - { - BMCWEB_LOG_ERROR << ec; - return; - } + crow::connections::systemBus->async_method_call( + [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"]; - logServiceArrayLocal.push_back( - {{"@odata.id", - "/redfish/v1/Systems/system/LogServices/PostCodes"}}); - asyncResp->res.jsonValue["Members@odata.count"] = - logServiceArrayLocal.size(); - return; - } - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", 0, - std::array<const char*, 1>{postCodeIface}); + for (const auto& pathStr : subtreePath) + { + if (pathStr.find("PostCode") != std::string::npos) + { + nlohmann::json& logServiceArrayLocal = + asyncResp->res.jsonValue["Members"]; + logServiceArrayLocal.push_back( + {{"@odata.id", + "/redfish/v1/Systems/system/LogServices/PostCodes"}}); + asyncResp->res.jsonValue["Members@odata.count"] = + logServiceArrayLocal.size(); + return; + } + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", 0, + std::array<const char*, 1>{postCodeIface}); }); } @@ -985,37 +970,35 @@ inline void requestRoutesEventLogService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/EventLog/") .privileges(redfish::privileges::getLogService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/EventLog"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_1_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 = - crow::utility::getDateTimeOffsetNow(); - - asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; - asyncResp->res.jsonValue["DateTimeLocalOffset"] = - redfishDateTimeOffset.second; - - asyncResp->res.jsonValue["Entries"]["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; - asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = { - - {"target", - "/redfish/v1/Systems/system/LogServices/EventLog/Actions/LogService.ClearLog"}}; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/EventLog"; + asyncResp->res.jsonValue["@odata.type"] = + "#LogService.v1_1_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 = + crow::utility::getDateTimeOffsetNow(); + + asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; + asyncResp->res.jsonValue["DateTimeLocalOffset"] = + redfishDateTimeOffset.second; + + asyncResp->res.jsonValue["Entries"]["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; + asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = { + + {"target", + "/redfish/v1/Systems/system/LogServices/EventLog/Actions/LogService.ClearLog"}}; }); } @@ -1028,38 +1011,37 @@ inline void requestRoutesJournalEventLogClear(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->res)) - { - 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) - { - std::error_code ec; - std::filesystem::remove(file, ec); - } - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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) + { + 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) { - if (ec) - { - BMCWEB_LOG_ERROR << "Failed to reload rsyslog: " - << ec; - messages::internalError(asyncResp->res); - return; - } + // 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; + messages::internalError(asyncResp->res); + return; + } - messages::success(asyncResp->res); - }, - "org.freedesktop.systemd1", "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", "ReloadUnit", - "rsyslog.service", "replace"); - }); + messages::success(asyncResp->res); + }, + "org.freedesktop.systemd1", "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", "ReloadUnit", "rsyslog.service", + "replace"); + }); } static int fillEventLogEntryJson(const std::string& logEntryID, @@ -1163,92 +1145,90 @@ inline void requestRoutesJournalEventLogEntryCollection(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/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) { - query_param::QueryCapabilities capabilities = { - .canDelegateTop = true, - .canDelegateSkip = true, - }; - query_param::Query delegatedQuery; - if (!redfish::setUpRedfishRouteWithDelegation( - app, req, asyncResp->res, delegatedQuery, capabilities)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + query_param::QueryCapabilities capabilities = { + .canDelegateTop = true, + .canDelegateSkip = true, + }; + query_param::Query delegatedQuery; + if (!redfish::setUpRedfishRouteWithDelegation( + app, req, asyncResp->res, delegatedQuery, capabilities)) + { + 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"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; + 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()) { - return; + continue; } - // 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"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; - 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()) + + // Reset the unique ID on the first entry + bool firstEntry = true; + while (std::getline(logStream, logEntry)) + { + entryCount++; + // Handle paging using skip (number of entries to skip + // from the start) and top (number of entries to + // display) + if (entryCount <= delegatedQuery.skip || + entryCount > delegatedQuery.skip + delegatedQuery.top) { 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)) { - entryCount++; - // Handle paging using skip (number of entries to skip - // from the start) and top (number of entries to - // display) - if (entryCount <= delegatedQuery.skip || - entryCount > delegatedQuery.skip + delegatedQuery.top) - { - continue; - } - - std::string idStr; - if (!getUniqueEntryID(logEntry, idStr, firstEntry)) - { - continue; - } + continue; + } - if (firstEntry) - { - firstEntry = false; - } + if (firstEntry) + { + firstEntry = false; + } - logEntryArray.push_back({}); - nlohmann::json& bmcLogEntry = logEntryArray.back(); - if (fillEventLogEntryJson(idStr, logEntry, bmcLogEntry) != - 0) - { - messages::internalError(asyncResp->res); - return; - } + logEntryArray.push_back({}); + nlohmann::json& bmcLogEntry = logEntryArray.back(); + if (fillEventLogEntryJson(idStr, logEntry, bmcLogEntry) != 0) + { + messages::internalError(asyncResp->res); + return; } } - asyncResp->res.jsonValue["Members@odata.count"] = entryCount; - if (delegatedQuery.skip + delegatedQuery.top < entryCount) - { - asyncResp->res.jsonValue["Members@odata.nextLink"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries?$skip=" + - std::to_string(delegatedQuery.skip + delegatedQuery.top); - } + } + asyncResp->res.jsonValue["Members@odata.count"] = entryCount; + if (delegatedQuery.skip + delegatedQuery.top < entryCount) + { + asyncResp->res.jsonValue["Members@odata.nextLink"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries?$skip=" + + std::to_string(delegatedQuery.skip + delegatedQuery.top); + } }); } @@ -1261,61 +1241,60 @@ inline void requestRoutesJournalEventLogEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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; + + // 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()) + { + 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)) { - return; + continue; } - 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; - - // Oldest logs are in the last file, so start there and loop - // backwards - for (auto it = redfishLogFiles.rbegin(); - it < redfishLogFiles.rend(); it++) + + if (firstEntry) { - std::ifstream logStream(*it); - if (!logStream.is_open()) - { - continue; - } + firstEntry = false; + } - // Reset the unique ID on the first entry - bool firstEntry = true; - while (std::getline(logStream, logEntry)) + if (idStr == targetID) + { + if (fillEventLogEntryJson(idStr, logEntry, + asyncResp->res.jsonValue) != 0) { - std::string idStr; - if (!getUniqueEntryID(logEntry, idStr, firstEntry)) - { - continue; - } - - if (firstEntry) - { - firstEntry = false; - } - - if (idStr == targetID) - { - if (fillEventLogEntryJson( - idStr, logEntry, - asyncResp->res.jsonValue) != 0) - { - messages::internalError(asyncResp->res); - return; - } - return; - } + messages::internalError(asyncResp->res); + return; } + return; } - // Requested ID was not found - messages::resourceMissingAtURI( - asyncResp->res, crow::utility::urlFromPieces(targetID)); - }); + } + } + // Requested ID was not found + messages::resourceMissingAtURI(asyncResp->res, + crow::utility::urlFromPieces(targetID)); + }); } inline void requestRoutesDBusEventLogEntryCollection(App& app) @@ -1323,162 +1302,153 @@ inline void requestRoutesDBusEventLogEntryCollection(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/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) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; + 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 + crow::connections::systemBus->async_method_call( + [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; } - // 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"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries"; - 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 - crow::connections::systemBus->async_method_call( - [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& entriesArray = - asyncResp->res.jsonValue["Members"]; - entriesArray = nlohmann::json::array(); - for (const auto& objectPath : resp) + nlohmann::json& entriesArray = asyncResp->res.jsonValue["Members"]; + entriesArray = nlohmann::json::array(); + 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; + bool resolved = false; + for (const auto& interfaceMap : objectPath.second) + { + if (interfaceMap.first == + "xyz.openbmc_project.Logging.Entry") { - 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; - bool resolved = false; - for (const auto& interfaceMap : objectPath.second) + for (const auto& propertyMap : interfaceMap.second) { - if (interfaceMap.first == - "xyz.openbmc_project.Logging.Entry") + if (propertyMap.first == "Id") { - 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 == "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; - } - } - if (id == nullptr || message == nullptr || - severity == nullptr) - { - messages::internalError(asyncResp->res); - return; - } + 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 (interfaceMap.first == - "xyz.openbmc_project.Common.FilePath") + else if (propertyMap.first == "Severity") { - for (const auto& propertyMap : - interfaceMap.second) + severity = 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) { - if (propertyMap.first == "Path") - { - filePath = std::get_if<std::string>( - &propertyMap.second); - } + messages::internalError(asyncResp->res); + return; } + resolved = *resolveptr; } } - // Object path without the - // xyz.openbmc_project.Logging.Entry interface, ignore - // and continue. if (id == nullptr || message == nullptr || - severity == nullptr || timestamp == nullptr || - updateTimestamp == nullptr) + severity == nullptr) { - continue; + messages::internalError(asyncResp->res); + return; } - entriesArray.push_back({}); - nlohmann::json& thisEntry = entriesArray.back(); - thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry"; - thisEntry["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + - std::to_string(*id); - thisEntry["Name"] = "System Event Log Entry"; - thisEntry["Id"] = std::to_string(*id); - thisEntry["Message"] = *message; - thisEntry["Resolved"] = resolved; - thisEntry["EntryType"] = "Event"; - thisEntry["Severity"] = - translateSeverityDbusToRedfish(*severity); - thisEntry["Created"] = - crow::utility::getDateTimeUintMs(*timestamp); - thisEntry["Modified"] = - crow::utility::getDateTimeUintMs(*updateTimestamp); - if (filePath != nullptr) + } + else if (interfaceMap.first == + "xyz.openbmc_project.Common.FilePath") + { + for (const auto& propertyMap : interfaceMap.second) { - thisEntry["AdditionalDataURI"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + - std::to_string(*id) + "/attachment"; + if (propertyMap.first == "Path") + { + filePath = std::get_if<std::string>( + &propertyMap.second); + } } } - std::sort(entriesArray.begin(), entriesArray.end(), - [](const nlohmann::json& left, - const nlohmann::json& right) { - return (left["Id"] <= right["Id"]); - }); - asyncResp->res.jsonValue["Members@odata.count"] = - entriesArray.size(); - }, - "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", - "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + } + // 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; + } + entriesArray.push_back({}); + nlohmann::json& thisEntry = entriesArray.back(); + thisEntry["@odata.type"] = "#LogEntry.v1_8_0.LogEntry"; + thisEntry["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + + std::to_string(*id); + thisEntry["Name"] = "System Event Log Entry"; + thisEntry["Id"] = std::to_string(*id); + thisEntry["Message"] = *message; + thisEntry["Resolved"] = resolved; + thisEntry["EntryType"] = "Event"; + thisEntry["Severity"] = + translateSeverityDbusToRedfish(*severity); + thisEntry["Created"] = + crow::utility::getDateTimeUintMs(*timestamp); + thisEntry["Modified"] = + crow::utility::getDateTimeUintMs(*updateTimestamp); + if (filePath != nullptr) + { + thisEntry["AdditionalDataURI"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + + std::to_string(*id) + "/attachment"; + } + } + std::sort( + entriesArray.begin(), entriesArray.end(), + [](const nlohmann::json& left, const nlohmann::json& right) { + return (left["Id"] <= right["Id"]); + }); + asyncResp->res.jsonValue["Members@odata.count"] = + entriesArray.size(); + }, + "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); }); } @@ -1487,122 +1457,114 @@ inline void requestRoutesDBusEventLogEntry(App& app) BMCWEB_ROUTE( app, "/redfish/v1/Systems/system/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& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& param) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string entryID = param; + dbus::utility::escapePathForDbus(entryID); + + // DBus implementation of EventLog/Entries + // Make call to Logging Service to find all log entry objects + crow::connections::systemBus->async_method_call( + [asyncResp, entryID](const boost::system::error_code ec, + const dbus::utility::DBusPropertiesMap& resp) { + if (ec.value() == EBADR) { + messages::resourceNotFound(asyncResp->res, "EventLogEntry", + entryID); return; } - std::string entryID = param; - dbus::utility::escapePathForDbus(entryID); - - // DBus implementation of EventLog/Entries - // Make call to Logging Service to find all log entry objects - crow::connections::systemBus->async_method_call( - [asyncResp, - entryID](const boost::system::error_code ec, - const dbus::utility::DBusPropertiesMap& resp) { - if (ec.value() == EBADR) - { - messages::resourceNotFound(asyncResp->res, - "EventLogEntry", entryID); - return; - } - if (ec) - { - BMCWEB_LOG_ERROR - << "EventLogEntry (DBus) resp_handler got error " - << ec; - 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; - bool resolved = false; - - for (const auto& propertyMap : resp) - { - 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 == "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 == "Path") - { - filePath = - std::get_if<std::string>(&propertyMap.second); - } - } - if (id == nullptr || message == nullptr || - severity == nullptr || timestamp == nullptr || - updateTimestamp == nullptr) + if (ec) + { + BMCWEB_LOG_ERROR + << "EventLogEntry (DBus) resp_handler got error " << ec; + 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; + bool resolved = false; + + for (const auto& propertyMap : resp) + { + 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 == "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; } - asyncResp->res.jsonValue["@odata.type"] = - "#LogEntry.v1_8_0.LogEntry"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + - 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; - asyncResp->res.jsonValue["EntryType"] = "Event"; - asyncResp->res.jsonValue["Severity"] = - translateSeverityDbusToRedfish(*severity); - asyncResp->res.jsonValue["Created"] = - crow::utility::getDateTimeUintMs(*timestamp); - asyncResp->res.jsonValue["Modified"] = - crow::utility::getDateTimeUintMs(*updateTimestamp); - if (filePath != nullptr) - { - asyncResp->res.jsonValue["AdditionalDataURI"] = - "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + - std::to_string(*id) + "/attachment"; - } - }, - "xyz.openbmc_project.Logging", - "/xyz/openbmc_project/logging/entry/" + entryID, - "org.freedesktop.DBus.Properties", "GetAll", ""); + resolved = *resolveptr; + } + else if (propertyMap.first == "Path") + { + filePath = std::get_if<std::string>(&propertyMap.second); + } + } + if (id == nullptr || message == nullptr || severity == nullptr || + timestamp == nullptr || updateTimestamp == nullptr) + { + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#LogEntry.v1_8_0.LogEntry"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + + 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; + asyncResp->res.jsonValue["EntryType"] = "Event"; + asyncResp->res.jsonValue["Severity"] = + translateSeverityDbusToRedfish(*severity); + asyncResp->res.jsonValue["Created"] = + crow::utility::getDateTimeUintMs(*timestamp); + asyncResp->res.jsonValue["Modified"] = + crow::utility::getDateTimeUintMs(*updateTimestamp); + if (filePath != nullptr) + { + asyncResp->res.jsonValue["AdditionalDataURI"] = + "/redfish/v1/Systems/system/LogServices/EventLog/Entries/" + + std::to_string(*id) + "/attachment"; + } + }, + "xyz.openbmc_project.Logging", + "/xyz/openbmc_project/logging/entry/" + entryID, + "org.freedesktop.DBus.Properties", "GetAll", ""); }); BMCWEB_ROUTE( @@ -1612,84 +1574,82 @@ inline void requestRoutesDBusEventLogEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& entryId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<bool> resolved; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<bool> resolved; - if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", - resolved)) - { - return; - } - BMCWEB_LOG_DEBUG << "Set Resolved"; + if (!json_util::readJsonPatch(req, asyncResp->res, "Resolved", + resolved)) + { + return; + } + BMCWEB_LOG_DEBUG << "Set Resolved"; - crow::connections::systemBus->async_method_call( - [asyncResp, entryId](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(asyncResp->res); - return; - } - }, - "xyz.openbmc_project.Logging", - "/xyz/openbmc_project/logging/entry/" + entryId, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Logging.Entry", "Resolved", - dbus::utility::DbusVariantType(*resolved)); - }); + crow::connections::systemBus->async_method_call( + [asyncResp, entryId](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(asyncResp->res); + return; + } + }, + "xyz.openbmc_project.Logging", + "/xyz/openbmc_project/logging/entry/" + entryId, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Logging.Entry", "Resolved", + dbus::utility::DbusVariantType(*resolved)); + }); BMCWEB_ROUTE( app, "/redfish/v1/Systems/system/LogServices/EventLog/Entries/<str>/") .privileges(redfish::privileges::deleteLogEntry) - .methods(boost::beast::http::verb:: - delete_)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& - asyncResp, - const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "Do delete single event entries."; + .methods(boost::beast::http::verb::delete_)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& param) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "Do delete single event entries."; - std::string entryID = param; + std::string entryID = param; - dbus::utility::escapePathForDbus(entryID); + 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) + // 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 (ec.value() == EBADR) - { - 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); + 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); - }; + 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"); + // 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"); }); } @@ -1703,92 +1663,86 @@ inline void requestRoutesDBusEventLogEntryDownload(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (!http_helpers::isOctetAccepted( - req.getHeaderValue("Accept"))) - { - asyncResp->res.result( - boost::beast::http::status::bad_request); - return; - } - - std::string entryID = param; - dbus::utility::escapePathForDbus(entryID); - - crow::connections::systemBus->async_method_call( - [asyncResp, - entryID](const boost::system::error_code ec, - const sdbusplus::message::unix_fd& unixfd) { - if (ec.value() == EBADR) - { - messages::resourceNotFound( - asyncResp->res, "EventLogAttachment", entryID); - return; - } - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(asyncResp->res); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (!http_helpers::isOctetAccepted(req.getHeaderValue("Accept"))) + { + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } - int fd = -1; - fd = dup(unixfd); - if (fd == -1) - { - messages::internalError(asyncResp->res); - return; - } + std::string entryID = param; + dbus::utility::escapePathForDbus(entryID); - long long int size = lseek(fd, 0, SEEK_END); - if (size == -1) - { - messages::internalError(asyncResp->res); - return; - } + crow::connections::systemBus->async_method_call( + [asyncResp, entryID](const boost::system::error_code ec, + const sdbusplus::message::unix_fd& unixfd) { + if (ec.value() == EBADR) + { + messages::resourceNotFound(asyncResp->res, "EventLogAttachment", + entryID); + return; + } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(asyncResp->res); + return; + } - // Arbitrary max size of 64kb - constexpr int maxFileSize = 65536; - if (size > maxFileSize) - { - BMCWEB_LOG_ERROR - << "File size exceeds maximum allowed size of " - << maxFileSize; - messages::internalError(asyncResp->res); - return; - } - std::vector<char> data(static_cast<size_t>(size)); - long long int rc = lseek(fd, 0, SEEK_SET); - if (rc == -1) - { - messages::internalError(asyncResp->res); - return; - } - rc = read(fd, data.data(), data.size()); - if ((rc == -1) || (rc != size)) - { - messages::internalError(asyncResp->res); - return; - } - close(fd); + int fd = -1; + fd = dup(unixfd); + if (fd == -1) + { + messages::internalError(asyncResp->res); + return; + } - std::string_view strData(data.data(), data.size()); - std::string output = - crow::utility::base64encode(strData); + long long int size = lseek(fd, 0, SEEK_END); + if (size == -1) + { + messages::internalError(asyncResp->res); + return; + } - asyncResp->res.addHeader("Content-Type", - "application/octet-stream"); - asyncResp->res.addHeader("Content-Transfer-Encoding", - "Base64"); - asyncResp->res.body() = std::move(output); - }, - "xyz.openbmc_project.Logging", - "/xyz/openbmc_project/logging/entry/" + entryID, - "xyz.openbmc_project.Logging.Entry", "GetEntry"); - }); + // Arbitrary max size of 64kb + constexpr int maxFileSize = 65536; + if (size > maxFileSize) + { + BMCWEB_LOG_ERROR << "File size exceeds maximum allowed size of " + << maxFileSize; + messages::internalError(asyncResp->res); + return; + } + std::vector<char> data(static_cast<size_t>(size)); + long long int rc = lseek(fd, 0, SEEK_SET); + if (rc == -1) + { + messages::internalError(asyncResp->res); + return; + } + rc = read(fd, data.data(), data.size()); + if ((rc == -1) || (rc != size)) + { + messages::internalError(asyncResp->res); + return; + } + close(fd); + + std::string_view strData(data.data(), data.size()); + std::string output = crow::utility::base64encode(strData); + + asyncResp->res.addHeader("Content-Type", + "application/octet-stream"); + asyncResp->res.addHeader("Content-Transfer-Encoding", "Base64"); + asyncResp->res.body() = std::move(output); + }, + "xyz.openbmc_project.Logging", + "/xyz/openbmc_project/logging/entry/" + entryID, + "xyz.openbmc_project.Logging.Entry", "GetEntry"); + }); } constexpr const char* hostLoggerFolderPath = "/var/log/console"; @@ -1877,20 +1831,20 @@ inline void requestRoutesSystemHostLogger(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/HostLogger"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_1_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"] = - "/redfish/v1/Systems/system/LogServices/HostLogger/Entries"; - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/HostLogger"; + asyncResp->res.jsonValue["@odata.type"] = + "#LogService.v1_1_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"] = + "/redfish/v1/Systems/system/LogServices/HostLogger/Entries"; + }); } inline void requestRoutesSystemHostLoggerCollection(App& app) @@ -1898,75 +1852,72 @@ inline void requestRoutesSystemHostLoggerCollection(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/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) { - query_param::QueryCapabilities capabilities = { - .canDelegateTop = true, - .canDelegateSkip = true, - }; - query_param::Query delegatedQuery; - if (!redfish::setUpRedfishRouteWithDelegation( - app, req, asyncResp->res, delegatedQuery, capabilities)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/HostLogger/Entries"; - 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; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + query_param::QueryCapabilities capabilities = { + .canDelegateTop = true, + .canDelegateSkip = true, + }; + query_param::Query delegatedQuery; + if (!redfish::setUpRedfishRouteWithDelegation( + app, req, asyncResp->res, delegatedQuery, capabilities)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/HostLogger/Entries"; + 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_ERROR << "fail to get host log file path"; + return; + } - std::vector<std::filesystem::path> hostLoggerFiles; - if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles)) + 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, delegatedQuery.skip, + delegatedQuery.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++) { - BMCWEB_LOG_ERROR << "fail to get host log file path"; - return; + logEntryArray.push_back({}); + nlohmann::json& hostLogEntry = logEntryArray.back(); + fillHostLoggerEntryJson(std::to_string(delegatedQuery.skip + i), + logEntries[i], hostLogEntry); } - 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, delegatedQuery.skip, - delegatedQuery.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()) + asyncResp->res.jsonValue["Members@odata.count"] = logCount; + if (delegatedQuery.skip + delegatedQuery.top < logCount) { - for (size_t i = 0; i < logEntries.size(); i++) - { - logEntryArray.push_back({}); - nlohmann::json& hostLogEntry = logEntryArray.back(); - fillHostLoggerEntryJson( - std::to_string(delegatedQuery.skip + i), logEntries[i], - hostLogEntry); - } - - asyncResp->res.jsonValue["Members@odata.count"] = logCount; - if (delegatedQuery.skip + delegatedQuery.top < logCount) - { - asyncResp->res.jsonValue["Members@odata.nextLink"] = - "/redfish/v1/Systems/system/LogServices/HostLogger/Entries?$skip=" + - std::to_string(delegatedQuery.skip + - delegatedQuery.top); - } + asyncResp->res.jsonValue["Members@odata.nextLink"] = + "/redfish/v1/Systems/system/LogServices/HostLogger/Entries?$skip=" + + std::to_string(delegatedQuery.skip + delegatedQuery.top); } + } }); } @@ -1979,59 +1930,59 @@ inline void requestRoutesSystemHostLoggerLogEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - const std::string& targetID = param; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + const std::string& targetID = param; - uint64_t idInt = 0; + uint64_t idInt = 0; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - const char* end = targetID.data() + targetID.size(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + const char* end = targetID.data() + targetID.size(); - auto [ptr, ec] = std::from_chars(targetID.data(), end, idInt); - if (ec == std::errc::invalid_argument) - { - messages::resourceMissingAtURI(asyncResp->res, req.urlView); - return; - } - if (ec == std::errc::result_out_of_range) - { - messages::resourceMissingAtURI(asyncResp->res, req.urlView); - return; - } + auto [ptr, ec] = std::from_chars(targetID.data(), end, idInt); + if (ec == std::errc::invalid_argument) + { + messages::resourceMissingAtURI(asyncResp->res, req.urlView); + return; + } + if (ec == std::errc::result_out_of_range) + { + messages::resourceMissingAtURI(asyncResp->res, req.urlView); + return; + } - std::vector<std::filesystem::path> hostLoggerFiles; - if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles)) - { - BMCWEB_LOG_ERROR << "fail to get host log file path"; - return; - } + std::vector<std::filesystem::path> hostLoggerFiles; + if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles)) + { + BMCWEB_LOG_ERROR << "fail to get host log file path"; + return; + } - size_t logCount = 0; - uint64_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; - } + size_t logCount = 0; + uint64_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()) - { - fillHostLoggerEntryJson(targetID, logEntries[0], - asyncResp->res.jsonValue); - return; - } + if (!logEntries.empty()) + { + fillHostLoggerEntryJson(targetID, logEntries[0], + asyncResp->res.jsonValue); + return; + } - // Requested ID was not found - messages::resourceMissingAtURI(asyncResp->res, req.urlView); - }); + // Requested ID was not found + messages::resourceMissingAtURI(asyncResp->res, req.urlView); + }); } inline void requestRoutesBMCLogServiceCollection(App& app) @@ -2041,36 +1992,32 @@ inline void requestRoutesBMCLogServiceCollection(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->res)) - { - 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"] = - "/redfish/v1/Managers/bmc/LogServices"; - asyncResp->res.jsonValue["Name"] = - "Open BMC Log Services Collection"; - asyncResp->res.jsonValue["Description"] = - "Collection of LogServices for this Manager"; - nlohmann::json& logServiceArray = - asyncResp->res.jsonValue["Members"]; - logServiceArray = nlohmann::json::array(); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"] = + "/redfish/v1/Managers/bmc/LogServices"; + asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection"; + asyncResp->res.jsonValue["Description"] = + "Collection of LogServices for this Manager"; + nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"]; + logServiceArray = nlohmann::json::array(); #ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG - logServiceArray.push_back( - {{"@odata.id", - "/redfish/v1/Managers/bmc/LogServices/Dump"}}); + logServiceArray.push_back( + {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Dump"}}); #endif #ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL - logServiceArray.push_back( - {{"@odata.id", - "/redfish/v1/Managers/bmc/LogServices/Journal"}}); + logServiceArray.push_back( + {{"@odata.id", "/redfish/v1/Managers/bmc/LogServices/Journal"}}); #endif - asyncResp->res.jsonValue["Members@odata.count"] = - logServiceArray.size(); - }); + asyncResp->res.jsonValue["Members@odata.count"] = + logServiceArray.size(); + }); } inline void requestRoutesBMCJournalLogService(App& app) @@ -2080,31 +2027,28 @@ inline void requestRoutesBMCJournalLogService(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_1_0.LogService"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/LogServices/Journal"; - asyncResp->res.jsonValue["Name"] = - "Open BMC Journal Log Service"; - asyncResp->res.jsonValue["Description"] = - "BMC Journal Log Service"; - asyncResp->res.jsonValue["Id"] = "BMC Journal"; - asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; - - std::pair<std::string, std::string> redfishDateTimeOffset = - crow::utility::getDateTimeOffsetNow(); - asyncResp->res.jsonValue["DateTime"] = - redfishDateTimeOffset.first; - asyncResp->res.jsonValue["DateTimeLocalOffset"] = - redfishDateTimeOffset.second; - - asyncResp->res.jsonValue["Entries"]["@odata.id"] = - "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"; - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#LogService.v1_1_0.LogService"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/LogServices/Journal"; + asyncResp->res.jsonValue["Name"] = "Open BMC Journal Log Service"; + asyncResp->res.jsonValue["Description"] = "BMC Journal Log Service"; + asyncResp->res.jsonValue["Id"] = "BMC Journal"; + asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; + + std::pair<std::string, std::string> redfishDateTimeOffset = + crow::utility::getDateTimeOffsetNow(); + asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; + asyncResp->res.jsonValue["DateTimeLocalOffset"] = + redfishDateTimeOffset.second; + + asyncResp->res.jsonValue["Entries"]["@odata.id"] = + "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"; + }); } static int fillBMCJournalLogEntryJson(const std::string& bmcJournalLogEntryID, @@ -2172,87 +2116,85 @@ inline void requestRoutesBMCJournalLogEntryCollection(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/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) { - query_param::QueryCapabilities capabilities = { - .canDelegateTop = true, - .canDelegateSkip = true, - }; - query_param::Query delegatedQuery; - if (!redfish::setUpRedfishRouteWithDelegation( - app, req, asyncResp->res, delegatedQuery, capabilities)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + query_param::QueryCapabilities capabilities = { + .canDelegateTop = true, + .canDelegateSkip = true, + }; + query_param::Query delegatedQuery; + if (!redfish::setUpRedfishRouteWithDelegation( + app, req, asyncResp->res, delegatedQuery, capabilities)) + { + 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"] = + "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"; + 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 <= delegatedQuery.skip || + entryCount > delegatedQuery.skip + delegatedQuery.top) { - return; + continue; } - // 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"] = - "/redfish/v1/Managers/bmc/LogServices/Journal/Entries"; - 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 <= delegatedQuery.skip || - entryCount > delegatedQuery.skip + delegatedQuery.top) - { - continue; - } - - std::string idStr; - if (!getUniqueEntryID(journal.get(), idStr, firstEntry)) - { - continue; - } - if (firstEntry) - { - firstEntry = false; - } + std::string idStr; + if (!getUniqueEntryID(journal.get(), idStr, firstEntry)) + { + continue; + } - logEntryArray.push_back({}); - nlohmann::json& bmcJournalLogEntry = logEntryArray.back(); - if (fillBMCJournalLogEntryJson(idStr, journal.get(), - bmcJournalLogEntry) != 0) - { - messages::internalError(asyncResp->res); - return; - } + if (firstEntry) + { + firstEntry = false; } - asyncResp->res.jsonValue["Members@odata.count"] = entryCount; - if (delegatedQuery.skip + delegatedQuery.top < entryCount) + + logEntryArray.push_back({}); + nlohmann::json& bmcJournalLogEntry = logEntryArray.back(); + if (fillBMCJournalLogEntryJson(idStr, journal.get(), + bmcJournalLogEntry) != 0) { - asyncResp->res.jsonValue["Members@odata.nextLink"] = - "/redfish/v1/Managers/bmc/LogServices/Journal/Entries?$skip=" + - std::to_string(delegatedQuery.skip + delegatedQuery.top); + messages::internalError(asyncResp->res); + return; } + } + asyncResp->res.jsonValue["Members@odata.count"] = entryCount; + if (delegatedQuery.skip + delegatedQuery.top < entryCount) + { + asyncResp->res.jsonValue["Members@odata.nextLink"] = + "/redfish/v1/Managers/bmc/LogServices/Journal/Entries?$skip=" + + std::to_string(delegatedQuery.skip + delegatedQuery.top); + } }); } @@ -2265,107 +2207,103 @@ inline void requestRoutesBMCJournalLogEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& entryID) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - // Convert the unique ID back to a timestamp to find the entry - uint64_t ts = 0; - uint64_t index = 0; - if (!getTimestampFromID(asyncResp, entryID, ts, index)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + // Convert the unique ID back to a timestamp to find the entry + uint64_t ts = 0; + uint64_t index = 0; + if (!getTimestampFromID(asyncResp, entryID, 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_realtime_usec(journal.get(), 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; - } - if (firstEntry) - { - firstEntry = false; - } - } - // Confirm that the entry ID matches what was requested - if (idStr != entryID) - { - messages::resourceMissingAtURI(asyncResp->res, req.urlView); - 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_realtime_usec(journal.get(), 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; + } + if (firstEntry) + { + firstEntry = false; + } + } + // Confirm that the entry ID matches what was requested + if (idStr != entryID) + { + messages::resourceMissingAtURI(asyncResp->res, req.urlView); + return; + } - if (fillBMCJournalLogEntryJson(entryID, journal.get(), - asyncResp->res.jsonValue) != 0) - { - messages::internalError(asyncResp->res); - return; - } - }); + if (fillBMCJournalLogEntryJson(entryID, journal.get(), + asyncResp->res.jsonValue) != 0) + { + messages::internalError(asyncResp->res); + return; + } + }); } inline void requestRoutesBMCDumpService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/") .privileges(redfish::privileges::getLogService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/LogServices/Dump"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_2_0.LogService"; - asyncResp->res.jsonValue["Name"] = "Dump LogService"; - asyncResp->res.jsonValue["Description"] = "BMC Dump LogService"; - asyncResp->res.jsonValue["Id"] = "Dump"; - asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; - - std::pair<std::string, std::string> redfishDateTimeOffset = - crow::utility::getDateTimeOffsetNow(); - asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; - asyncResp->res.jsonValue["DateTimeLocalOffset"] = - redfishDateTimeOffset.second; - - asyncResp->res.jsonValue["Entries"]["@odata.id"] = - "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"; - asyncResp->res - .jsonValue["Actions"]["#LogService.ClearLog"]["target"] = - "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.ClearLog"; - asyncResp->res - .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] - ["target"] = - "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData"; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/LogServices/Dump"; + asyncResp->res.jsonValue["@odata.type"] = + "#LogService.v1_2_0.LogService"; + asyncResp->res.jsonValue["Name"] = "Dump LogService"; + asyncResp->res.jsonValue["Description"] = "BMC Dump LogService"; + asyncResp->res.jsonValue["Id"] = "Dump"; + asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; + + std::pair<std::string, std::string> redfishDateTimeOffset = + crow::utility::getDateTimeOffsetNow(); + asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; + asyncResp->res.jsonValue["DateTimeLocalOffset"] = + redfishDateTimeOffset.second; + + asyncResp->res.jsonValue["Entries"]["@odata.id"] = + "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"; + asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] = + "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.ClearLog"; + asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] + ["target"] = + "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.CollectDiagnosticData"; }); } @@ -2380,20 +2318,20 @@ inline void requestRoutesBMCDumpEntryCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#LogEntryCollection.LogEntryCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"; - asyncResp->res.jsonValue["Name"] = "BMC Dump Entries"; - asyncResp->res.jsonValue["Description"] = - "Collection of BMC Dump Entries"; - - getDumpEntryCollection(asyncResp, "BMC"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#LogEntryCollection.LogEntryCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/bmc/LogServices/Dump/Entries"; + asyncResp->res.jsonValue["Name"] = "BMC Dump Entries"; + asyncResp->res.jsonValue["Description"] = + "Collection of BMC Dump Entries"; + + getDumpEntryCollection(asyncResp, "BMC"); + }); } inline void requestRoutesBMCDumpEntry(App& app) @@ -2405,13 +2343,13 @@ inline void requestRoutesBMCDumpEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - getDumpEntryById(app, req, asyncResp, param, "BMC"); - }); + getDumpEntryById(app, req, asyncResp, param, "BMC"); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/") .privileges(redfish::privileges::deleteLogEntry) @@ -2419,12 +2357,12 @@ inline void requestRoutesBMCDumpEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - deleteDumpEntry(asyncResp, param, "bmc"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + deleteDumpEntry(asyncResp, param, "bmc"); + }); } inline void requestRoutesBMCDumpCreate(App& app) @@ -2436,12 +2374,12 @@ inline void requestRoutesBMCDumpCreate(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->res)) - { - return; - } - createDump(asyncResp, req, "BMC"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + createDump(asyncResp, req, "BMC"); + }); } inline void requestRoutesBMCDumpClear(App& app) @@ -2453,51 +2391,48 @@ inline void requestRoutesBMCDumpClear(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->res)) - { - return; - } - clearDump(asyncResp, "BMC"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + clearDump(asyncResp, "BMC"); + }); } inline void requestRoutesSystemDumpService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/") .privileges(redfish::privileges::getLogService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Dump"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_2_0.LogService"; - asyncResp->res.jsonValue["Name"] = "Dump LogService"; - asyncResp->res.jsonValue["Description"] = "System Dump LogService"; - asyncResp->res.jsonValue["Id"] = "Dump"; - asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; - - std::pair<std::string, std::string> redfishDateTimeOffset = - crow::utility::getDateTimeOffsetNow(); - asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; - asyncResp->res.jsonValue["DateTimeLocalOffset"] = - redfishDateTimeOffset.second; - - asyncResp->res.jsonValue["Entries"]["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Dump/Entries"; - asyncResp->res - .jsonValue["Actions"]["#LogService.ClearLog"]["target"] = - "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog"; - - asyncResp->res - .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] - ["target"] = - "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData"; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Dump"; + asyncResp->res.jsonValue["@odata.type"] = + "#LogService.v1_2_0.LogService"; + asyncResp->res.jsonValue["Name"] = "Dump LogService"; + asyncResp->res.jsonValue["Description"] = "System Dump LogService"; + asyncResp->res.jsonValue["Id"] = "Dump"; + asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; + + std::pair<std::string, std::string> redfishDateTimeOffset = + crow::utility::getDateTimeOffsetNow(); + asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; + asyncResp->res.jsonValue["DateTimeLocalOffset"] = + redfishDateTimeOffset.second; + + asyncResp->res.jsonValue["Entries"]["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Dump/Entries"; + asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] = + "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.ClearLog"; + + asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] + ["target"] = + "/redfish/v1/Systems/system/LogServices/Dump/Actions/LogService.CollectDiagnosticData"; }); } @@ -2512,20 +2447,20 @@ inline void requestRoutesSystemDumpEntryCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#LogEntryCollection.LogEntryCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Dump/Entries"; - asyncResp->res.jsonValue["Name"] = "System Dump Entries"; - asyncResp->res.jsonValue["Description"] = - "Collection of System Dump Entries"; - - getDumpEntryCollection(asyncResp, "System"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#LogEntryCollection.LogEntryCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Dump/Entries"; + asyncResp->res.jsonValue["Name"] = "System Dump Entries"; + asyncResp->res.jsonValue["Description"] = + "Collection of System Dump Entries"; + + getDumpEntryCollection(asyncResp, "System"); + }); } inline void requestRoutesSystemDumpEntry(App& app) @@ -2538,8 +2473,8 @@ inline void requestRoutesSystemDumpEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - getDumpEntryById(app, req, asyncResp, param, "System"); - }); + getDumpEntryById(app, req, asyncResp, param, "System"); + }); BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/Dump/Entries/<str>/") @@ -2548,12 +2483,12 @@ inline void requestRoutesSystemDumpEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - deleteDumpEntry(asyncResp, param, "system"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + deleteDumpEntry(asyncResp, param, "system"); + }); } inline void requestRoutesSystemDumpCreate(App& app) @@ -2565,12 +2500,12 @@ inline void requestRoutesSystemDumpCreate(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->res)) - { - return; - } - createDump(asyncResp, req, "System"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + createDump(asyncResp, req, "System"); + }); } inline void requestRoutesSystemDumpClear(App& app) @@ -2584,12 +2519,12 @@ inline void requestRoutesSystemDumpClear(App& app) const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - clearDump(asyncResp, "System"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + clearDump(asyncResp, "System"); + }); } inline void requestRoutesCrashdumpService(App& app) @@ -2603,41 +2538,38 @@ 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) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - // Copy over the static data to include the entries added by - // SubRoute - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Crashdump"; - 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"] = "Oem Crashdump"; - asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; - asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; - - std::pair<std::string, std::string> redfishDateTimeOffset = - crow::utility::getDateTimeOffsetNow(); - asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; - asyncResp->res.jsonValue["DateTimeLocalOffset"] = - redfishDateTimeOffset.second; - - asyncResp->res.jsonValue["Entries"]["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"; - asyncResp->res - .jsonValue["Actions"]["#LogService.ClearLog"]["target"] = - "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/LogService.ClearLog"; - asyncResp->res - .jsonValue["Actions"]["#LogService.CollectDiagnosticData"] - ["target"] = - "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData"; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + // Copy over the static data to include the entries added by + // SubRoute + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Crashdump"; + 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"] = "Oem Crashdump"; + asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; + asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3; + + std::pair<std::string, std::string> redfishDateTimeOffset = + crow::utility::getDateTimeOffsetNow(); + asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; + asyncResp->res.jsonValue["DateTimeLocalOffset"] = + redfishDateTimeOffset.second; + + asyncResp->res.jsonValue["Entries"]["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"; + asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] = + "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/LogService.ClearLog"; + asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"] + ["target"] = + "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/LogService.CollectDiagnosticData"; }); } @@ -2652,23 +2584,22 @@ void inline requestRoutesCrashdumpClear(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->res)) - { - 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->res)) + { + 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 @@ -2679,64 +2610,63 @@ 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) - { - 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()) + if (ec) + { + BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message(); + if (ec.value() == + boost::system::linux_error::bad_request_descriptor) { - messages::resourceMissingAtURI( - asyncResp->res, crow::utility::urlFromPieces(logID)); - return; - } - - std::string crashdumpURI = - "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + - logID + "/" + filename; - nlohmann::json logEntry = { - {"@odata.type", "#LogEntry.v1_7_0.LogEntry"}, - {"@odata.id", - "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + - logID}, - {"Name", "CPU Crashdump"}, - {"Id", logID}, - {"EntryType", "Oem"}, - {"AdditionalDataURI", std::move(crashdumpURI)}, - {"DiagnosticDataType", "OEM"}, - {"OEMDiagnosticDataType", "PECICrashdump"}, - {"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(); + messages::resourceNotFound(asyncResp->res, "LogEntry", logID); } else { - logEntryJson = logEntry; + 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::resourceMissingAtURI(asyncResp->res, + crow::utility::urlFromPieces(logID)); + return; + } + + std::string crashdumpURI = + "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + + logID + "/" + filename; + nlohmann::json logEntry = { + {"@odata.type", "#LogEntry.v1_7_0.LogEntry"}, + {"@odata.id", + "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" + + logID}, + {"Name", "CPU Crashdump"}, + {"Id", logID}, + {"EntryType", "Oem"}, + {"AdditionalDataURI", std::move(crashdumpURI)}, + {"DiagnosticDataType", "OEM"}, + {"OEMDiagnosticDataType", "PECICrashdump"}, + {"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 = logEntry; + } + }; crow::connections::systemBus->async_method_call( std::move(getStoredLogCallback), crashdumpObject, crashdumpPath + std::string("/") + logID, @@ -2755,58 +2685,55 @@ 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) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const std::vector<std::string>& resp) { + if (ec) { - return; + 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; + } } - crow::connections::systemBus->async_method_call( - [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"] = - "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"; - 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"]); - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0, - std::array<const char*, 1>{crashdumpInterface}); + asyncResp->res.jsonValue["@odata.type"] = + "#LogEntryCollection.LogEntryCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/Crashdump/Entries"; + 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"]); + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0, + std::array<const char*, 1>{crashdumpInterface}); }); } @@ -2824,13 +2751,13 @@ inline void requestRoutesCrashdumpEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - const std::string& logID = param; - logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + const std::string& logID = param; + logCrashdumpEntry(asyncResp, logID, asyncResp->res.jsonValue); + }); } inline void requestRoutesCrashdumpFile(App& app) @@ -2845,67 +2772,62 @@ inline void requestRoutesCrashdumpFile(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& logID, const std::string& fileName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - auto getStoredLogCallback = - [asyncResp, logID, fileName, - url(boost::urls::url(req.urlView))]( - 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; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + auto getStoredLogCallback = + [asyncResp, logID, fileName, url(boost::urls::url(req.urlView))]( + 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::resourceMissingAtURI(asyncResp->res, url); - return; - } + if (dbusFilename.empty() || dbusTimestamp.empty() || + dbusFilepath.empty()) + { + messages::resourceMissingAtURI(asyncResp->res, url); + return; + } - // Verify the file name parameter is correct - if (fileName != dbusFilename) - { - messages::resourceMissingAtURI(asyncResp->res, url); - return; - } + // Verify the file name parameter is correct + if (fileName != dbusFilename) + { + messages::resourceMissingAtURI(asyncResp->res, url); + return; + } - if (!std::filesystem::exists(dbusFilepath)) - { - messages::resourceMissingAtURI(asyncResp->res, url); - return; - } - std::ifstream ifs(dbusFilepath, - std::ios::in | std::ios::binary); - asyncResp->res.body() = std::string( - std::istreambuf_iterator<char>{ifs}, {}); - - // Configure this to be a file download when accessed - // from a browser - asyncResp->res.addHeader("Content-Disposition", - "attachment"); - }; - crow::connections::systemBus->async_method_call( - std::move(getStoredLogCallback), crashdumpObject, - crashdumpPath + std::string("/") + logID, - "org.freedesktop.DBus.Properties", "GetAll", - crashdumpInterface); - }); + if (!std::filesystem::exists(dbusFilepath)) + { + messages::resourceMissingAtURI(asyncResp->res, url); + return; + } + std::ifstream ifs(dbusFilepath, std::ios::in | std::ios::binary); + asyncResp->res.body() = + std::string(std::istreambuf_iterator<char>{ifs}, {}); + + // Configure this to be a file download when accessed + // from a browser + asyncResp->res.addHeader("Content-Disposition", "attachment"); + }; + crow::connections::systemBus->async_method_call( + std::move(getStoredLogCallback), crashdumpObject, + crashdumpPath + std::string("/") + logID, + "org.freedesktop.DBus.Properties", "GetAll", crashdumpInterface); + }); } enum class OEMDiagnosticType @@ -2940,117 +2862,109 @@ inline void requestRoutesCrashdumpCollect(App& app) // The below is incorrect; 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) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::string diagnosticDataType; - std::string oemDiagnosticDataType; - if (!redfish::json_util::readJsonAction( - req, asyncResp->res, "DiagnosticDataType", - diagnosticDataType, "OEMDiagnosticDataType", - oemDiagnosticDataType)) - { - return; - } + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string diagnosticDataType; + std::string oemDiagnosticDataType; + if (!redfish::json_util::readJsonAction( + req, asyncResp->res, "DiagnosticDataType", diagnosticDataType, + "OEMDiagnosticDataType", oemDiagnosticDataType)) + { + return; + } - if (diagnosticDataType != "OEM") - { - BMCWEB_LOG_ERROR - << "Only OEM DiagnosticDataType supported for Crashdump"; - messages::actionParameterValueFormatError( - asyncResp->res, diagnosticDataType, "DiagnosticDataType", - "CollectDiagnosticData"); - return; - } + if (diagnosticDataType != "OEM") + { + BMCWEB_LOG_ERROR + << "Only OEM DiagnosticDataType supported for Crashdump"; + messages::actionParameterValueFormatError( + asyncResp->res, diagnosticDataType, "DiagnosticDataType", + "CollectDiagnosticData"); + return; + } - OEMDiagnosticType oemDiagType = - getOEMDiagnosticType(oemDiagnosticDataType); + OEMDiagnosticType oemDiagType = + getOEMDiagnosticType(oemDiagnosticDataType); - 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 + 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; + } + + auto collectCrashdumpCallback = + [asyncResp, payload(task::Payload(req)), + taskMatchStr](const boost::system::error_code ec, + const std::string&) mutable { + if (ec) { - BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: " - << oemDiagnosticDataType; - messages::actionParameterValueFormatError( - asyncResp->res, oemDiagnosticDataType, - "OEMDiagnosticDataType", "CollectDiagnosticData"); + 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( + [](boost::system::error_code err, sdbusplus::message::message&, + const std::shared_ptr<task::TaskData>& taskData) { + if (!err) + { + taskData->messages.emplace_back(messages::taskCompletedOK( + std::to_string(taskData->index))); + taskData->state = "Completed"; + } + return task::completed; + }, + taskMatchStr); - 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( - [](boost::system::error_code err, - sdbusplus::message::message&, - const std::shared_ptr<task::TaskData>& - taskData) { - if (!err) - { - 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); + 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); }); } @@ -3072,37 +2986,33 @@ inline void requestRoutesDBusLogServiceActionsClear(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->res)) - { - 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; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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); - }; + 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"); - }); + // 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"); + }); } /**************************************************** @@ -3113,35 +3023,34 @@ inline void requestRoutesPostCodesLogService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/LogServices/PostCodes/") .privileges(redfish::privileges::getLogService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - 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->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/PostCodes"; - asyncResp->res.jsonValue["@odata.type"] = - "#LogService.v1_1_0.LogService"; - asyncResp->res.jsonValue["Name"] = "POST Code Log Service"; - asyncResp->res.jsonValue["Description"] = "POST Code Log Service"; - asyncResp->res.jsonValue["Id"] = "BIOS POST Code Log"; - asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; - asyncResp->res.jsonValue["Entries"]["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; - - std::pair<std::string, std::string> redfishDateTimeOffset = - crow::utility::getDateTimeOffsetNow(); - asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; - asyncResp->res.jsonValue["DateTimeLocalOffset"] = - redfishDateTimeOffset.second; - - asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = { - {"target", - "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/LogService.ClearLog"}}; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/PostCodes"; + asyncResp->res.jsonValue["@odata.type"] = + "#LogService.v1_1_0.LogService"; + asyncResp->res.jsonValue["Name"] = "POST Code Log Service"; + asyncResp->res.jsonValue["Description"] = "POST Code Log Service"; + asyncResp->res.jsonValue["Id"] = "BIOS POST Code Log"; + asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull"; + asyncResp->res.jsonValue["Entries"]["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; + + std::pair<std::string, std::string> redfishDateTimeOffset = + crow::utility::getDateTimeOffsetNow(); + asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first; + asyncResp->res.jsonValue["DateTimeLocalOffset"] = + redfishDateTimeOffset.second; + + asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = { + {"target", + "/redfish/v1/Systems/system/LogServices/PostCodes/Actions/LogService.ClearLog"}}; }); } @@ -3156,31 +3065,30 @@ inline void requestRoutesPostCodesClear(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->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "Do delete all postcodes entries."; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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; - } - }, - "xyz.openbmc_project.State.Boot.PostCode0", - "/xyz/openbmc_project/State/Boot/PostCode0", - "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); - }); + // 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; + } + }, + "xyz.openbmc_project.State.Boot.PostCode0", + "/xyz/openbmc_project/State/Boot/PostCode0", + "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll"); + }); } static void fillPostCodeEntry( @@ -3319,23 +3227,23 @@ static void getPostCodeForEntry(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 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(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS POST CODE PostCode response error"; + messages::internalError(aResp->res); + return; + } - // skip the empty postcode boots - if (postcode.empty()) - { - return; - } + // skip the empty postcode boots + if (postcode.empty()) + { + return; + } - fillPostCodeEntry(aResp, postcode, bootIndex, codeIndex); + fillPostCodeEntry(aResp, postcode, bootIndex, codeIndex); - aResp->res.jsonValue["Members@odata.count"] = - aResp->res.jsonValue["Members"].size(); + aResp->res.jsonValue["Members@odata.count"] = + aResp->res.jsonValue["Members"].size(); }, "xyz.openbmc_project.State.Boot.PostCode0", "/xyz/openbmc_project/State/Boot/PostCode0", @@ -3355,43 +3263,42 @@ static void getPostCodeForBoot(const std::shared_ptr<bmcweb::AsyncResp>& aResp, 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(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS POST CODE PostCode response error"; + messages::internalError(aResp->res); + return; + } - uint64_t endCount = entryCount; - if (!postcode.empty()) - { - endCount = entryCount + postcode.size(); + uint64_t endCount = entryCount; + if (!postcode.empty()) + { + endCount = entryCount + postcode.size(); - if ((skip < endCount) && ((top + skip) > entryCount)) - { - uint64_t thisBootSkip = - std::max(skip, entryCount) - entryCount; - uint64_t thisBootTop = - std::min(top + skip, endCount) - entryCount; + if ((skip < endCount) && ((top + skip) > entryCount)) + { + uint64_t thisBootSkip = std::max(skip, entryCount) - entryCount; + uint64_t thisBootTop = + std::min(top + skip, endCount) - entryCount; - fillPostCodeEntry(aResp, postcode, bootIndex, 0, - thisBootSkip, thisBootTop); - } - aResp->res.jsonValue["Members@odata.count"] = endCount; + fillPostCodeEntry(aResp, postcode, bootIndex, 0, thisBootSkip, + thisBootTop); } + aResp->res.jsonValue["Members@odata.count"] = endCount; + } - // continue to previous bootIndex - if (bootIndex < bootCount) - { - getPostCodeForBoot(aResp, static_cast<uint16_t>(bootIndex + 1), - bootCount, endCount, skip, top); - } - else - { - aResp->res.jsonValue["Members@odata.nextLink"] = - "/redfish/v1/Systems/system/LogServices/PostCodes/Entries?$skip=" + - std::to_string(skip + top); - } + // continue to previous bootIndex + if (bootIndex < bootCount) + { + getPostCodeForBoot(aResp, static_cast<uint16_t>(bootIndex + 1), + bootCount, endCount, skip, top); + } + else + { + aResp->res.jsonValue["Members@odata.nextLink"] = + "/redfish/v1/Systems/system/LogServices/PostCodes/Entries?$skip=" + + std::to_string(skip + top); + } }, "xyz.openbmc_project.State.Boot.PostCode0", "/xyz/openbmc_project/State/Boot/PostCode0", @@ -3411,13 +3318,13 @@ static void "xyz.openbmc_project.State.Boot.PostCode", "CurrentBootCycleCount", [aResp, entryCount, skip, top](const boost::system::error_code ec, const uint16_t bootCount) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - getPostCodeForBoot(aResp, 1, bootCount, entryCount, skip, top); + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + getPostCodeForBoot(aResp, 1, bootCount, entryCount, skip, top); }); } @@ -3429,29 +3336,29 @@ inline void requestRoutesPostCodesEntryCollection(App& app) .methods(boost::beast::http::verb::get)( [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - query_param::QueryCapabilities capabilities = { - .canDelegateTop = true, - .canDelegateSkip = true, - }; - query_param::Query delegatedQuery; - if (!redfish::setUpRedfishRouteWithDelegation( - app, req, asyncResp->res, delegatedQuery, capabilities)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#LogEntryCollection.LogEntryCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; - 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; - - getCurrentBootNumber(asyncResp, delegatedQuery.skip, - delegatedQuery.top); - }); + query_param::QueryCapabilities capabilities = { + .canDelegateTop = true, + .canDelegateSkip = true, + }; + query_param::Query delegatedQuery; + if (!redfish::setUpRedfishRouteWithDelegation( + app, req, asyncResp->res, delegatedQuery, capabilities)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#LogEntryCollection.LogEntryCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; + 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; + + getCurrentBootNumber(asyncResp, delegatedQuery.skip, + delegatedQuery.top); + }); } /** @@ -3504,79 +3411,72 @@ inline void requestRoutesPostCodesEntryAdditionalData(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& postCodeID) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (!http_helpers::isOctetAccepted( - req.getHeaderValue("Accept"))) - { - asyncResp->res.result( - boost::beast::http::status::bad_request); - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (!http_helpers::isOctetAccepted(req.getHeaderValue("Accept"))) + { + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } - uint64_t currentValue = 0; - uint16_t index = 0; - if (!parsePostCode(postCodeID, currentValue, index)) - { - messages::resourceNotFound(asyncResp->res, "LogEntry", - postCodeID); - 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; - } + 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_ERROR << "Wrong currentValue value"; - messages::resourceNotFound(asyncResp->res, - "LogEntry", postCodeID); - return; - } + size_t value = static_cast<size_t>(currentValue) - 1; + if (value == std::string::npos || postcodes.size() < currentValue) + { + BMCWEB_LOG_ERROR << "Wrong currentValue value"; + messages::resourceNotFound(asyncResp->res, "LogEntry", + postCodeID); + return; + } - const auto& [tID, c] = postcodes[value]; - if (c.empty()) - { - BMCWEB_LOG_INFO << "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("Content-Type", - "application/octet-stream"); - asyncResp->res.addHeader("Content-Transfer-Encoding", - "Base64"); - asyncResp->res.body() = - crow::utility::base64encode(strData); - }, - "xyz.openbmc_project.State.Boot.PostCode0", - "/xyz/openbmc_project/State/Boot/PostCode0", - "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodes", - index); - }); + const auto& [tID, c] = postcodes[value]; + if (c.empty()) + { + BMCWEB_LOG_INFO << "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("Content-Type", + "application/octet-stream"); + asyncResp->res.addHeader("Content-Transfer-Encoding", "Base64"); + asyncResp->res.body() = 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) @@ -3588,36 +3488,35 @@ inline void requestRoutesPostCodesEntry(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& targetID) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - uint16_t bootIndex = 0; - uint64_t codeIndex = 0; - if (!parsePostCode(targetID, codeIndex, bootIndex)) - { - // Requested ID was not found - messages::resourceMissingAtURI(asyncResp->res, req.urlView); - return; - } - if (bootIndex == 0 || codeIndex == 0) - { - BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string " - << targetID; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + uint16_t bootIndex = 0; + uint64_t codeIndex = 0; + if (!parsePostCode(targetID, codeIndex, bootIndex)) + { + // Requested ID was not found + messages::resourceMissingAtURI(asyncResp->res, req.urlView); + return; + } + if (bootIndex == 0 || codeIndex == 0) + { + BMCWEB_LOG_DEBUG << "Get Post Code invalid entry string " + << targetID; + } - asyncResp->res.jsonValue["@odata.type"] = - "#LogEntry.v1_4_0.LogEntry"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; - 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; - - getPostCodeForEntry(asyncResp, bootIndex, codeIndex); - }); + asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_4_0.LogEntry"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/LogServices/PostCodes/Entries"; + 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; + + getPostCodeForEntry(asyncResp, bootIndex, codeIndex); + }); } } // namespace redfish diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp index cd9910ef55..87fcae98b9 100644 --- a/redfish-core/lib/managers.hpp +++ b/redfish-core/lib/managers.hpp @@ -55,15 +55,15 @@ inline void crow::connections::systemBus->async_method_call( [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); }, processName, objectPath, "org.freedesktop.DBus.Properties", "Set", interfaceName, destProperty, dbusPropertyValue); @@ -84,15 +84,15 @@ inline void crow::connections::systemBus->async_method_call( [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); }, processName, objectPath, "org.freedesktop.DBus.Properties", "Set", interfaceName, destProperty, dbusPropertyValue); @@ -115,39 +115,39 @@ inline void requestRoutesManagerResetAction(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->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "Post Manager Reset."; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + 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; + }); } /** @@ -175,52 +175,50 @@ inline void requestRoutesManagerResetToDefaultsAction(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->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "Post ResetToDefaults."; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "Post ResetToDefaults."; - std::string resetType; + std::string resetType; - if (!json_util::readJsonAction( - req, asyncResp->res, "ResetToDefaultsType", resetType)) - { - BMCWEB_LOG_DEBUG << "Missing property ResetToDefaultsType."; + if (!json_util::readJsonAction(req, asyncResp->res, + "ResetToDefaultsType", resetType)) + { + BMCWEB_LOG_DEBUG << "Missing property ResetToDefaultsType."; - messages::actionParameterMissing(asyncResp->res, - "ResetToDefaults", - "ResetToDefaultsType"); - return; - } + messages::actionParameterMissing(asyncResp->res, "ResetToDefaults", + "ResetToDefaultsType"); + return; + } - if (resetType != "ResetAll") - { - BMCWEB_LOG_DEBUG - << "Invalid property value for ResetToDefaultsType: " - << resetType; - messages::actionParameterNotSupported( - asyncResp->res, resetType, "ResetToDefaultsType"); - return; - } + if (resetType != "ResetAll") + { + BMCWEB_LOG_DEBUG + << "Invalid property value for ResetToDefaultsType: " + << resetType; + messages::actionParameterNotSupported(asyncResp->res, resetType, + "ResetToDefaultsType"); + return; + } - 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"); - }); + 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"); + }); } /** @@ -238,32 +236,32 @@ inline void requestRoutesManagerResetActionInfo(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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#ActionInfo.v1_1_2.ActionInfo"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/bmc/ResetActionInfo"; - 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.push_back("GracefulRestart"); - allowableValues.push_back("ForceRestart"); - parameter["AllowableValues"] = std::move(allowableValues); - - nlohmann::json::array_t parameters; - parameters.push_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"] = + "/redfish/v1/Managers/bmc/ResetActionInfo"; + 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.push_back("GracefulRestart"); + allowableValues.push_back("ForceRestart"); + parameter["AllowableValues"] = std::move(allowableValues); + + nlohmann::json::array_t parameters; + parameters.push_back(std::move(parameter)); + + asyncResp->res.jsonValue["Parameters"] = std::move(parameters); + }); } static constexpr const char* objectManagerIface = @@ -288,206 +286,218 @@ inline void [asyncResp, currentProfile, supportedProfiles]( const boost::system::error_code ec, const dbus::utility::ManagedObjectType& managedObj) { - if (ec) - { - BMCWEB_LOG_ERROR << ec; - asyncResp->res.jsonValue.clear(); - 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"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanControllers"; - - nlohmann::json& pids = configRoot["PidControllers"]; - pids["@odata.type"] = "#OemManager.PidControllers"; - pids["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/PidControllers"; - - nlohmann::json& stepwise = configRoot["StepwiseControllers"]; - stepwise["@odata.type"] = "#OemManager.StepwiseControllers"; - stepwise["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/StepwiseControllers"; - - nlohmann::json& zones = configRoot["FanZones"]; - zones["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones"; - zones["@odata.type"] = "#OemManager.FanZones"; - configRoot["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan"; - configRoot["@odata.type"] = "#OemManager.Fan"; - configRoot["Profile@Redfish.AllowableValues"] = supportedProfiles; - - if (!currentProfile.empty()) - { - configRoot["Profile"] = currentProfile; - } - BMCWEB_LOG_ERROR << "profile = " << currentProfile << " !"; + if (ec) + { + BMCWEB_LOG_ERROR << ec; + asyncResp->res.jsonValue.clear(); + 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"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanControllers"; + + nlohmann::json& pids = configRoot["PidControllers"]; + pids["@odata.type"] = "#OemManager.PidControllers"; + pids["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/PidControllers"; + + nlohmann::json& stepwise = configRoot["StepwiseControllers"]; + stepwise["@odata.type"] = "#OemManager.StepwiseControllers"; + stepwise["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/StepwiseControllers"; + + nlohmann::json& zones = configRoot["FanZones"]; + zones["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones"; + zones["@odata.type"] = "#OemManager.FanZones"; + configRoot["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan"; + configRoot["@odata.type"] = "#OemManager.Fan"; + configRoot["Profile@Redfish.AllowableValues"] = supportedProfiles; + + if (!currentProfile.empty()) + { + configRoot["Profile"] = currentProfile; + } + BMCWEB_LOG_ERROR << "profile = " << currentProfile << " !"; - for (const auto& pathPair : managedObj) + for (const auto& pathPair : managedObj) + { + for (const auto& intfPair : pathPair.second) { - for (const auto& intfPair : pathPair.second) + if (intfPair.first != pidConfigurationIface && + intfPair.first != pidZoneConfigurationIface && + intfPair.first != stepwiseConfigurationIface) { - if (intfPair.first != pidConfigurationIface && - intfPair.first != pidZoneConfigurationIface && - intfPair.first != stepwiseConfigurationIface) - { - continue; - } + continue; + } - std::string name; + std::string name; - for (const std::pair<std::string, - dbus::utility::DbusVariantType>& - propPair : intfPair.second) + for (const std::pair<std::string, + dbus::utility::DbusVariantType>& propPair : + intfPair.second) + { + if (propPair.first == "Name") { - if (propPair.first == "Name") + const std::string* namePtr = + std::get_if<std::string>(&propPair.second); + if (namePtr == nullptr) { - 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); + BMCWEB_LOG_ERROR << "Pid Name Field illegal"; + messages::internalError(asyncResp->res); + return; } - else if (propPair.first == "Profiles") + name = *namePtr; + dbus::utility::escapePathForDbus(name); + } + else if (propPair.first == "Profiles") + { + const std::vector<std::string>* profiles = + std::get_if<std::vector<std::string>>( + &propPair.second); + if (profiles == nullptr) { - 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 - << name - << " not supported in current profile"; - continue; - } + 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 + << name << " not supported in current profile"; + continue; } } - nlohmann::json* config = nullptr; - const std::string* classPtr = nullptr; + } + nlohmann::json* config = nullptr; + const std::string* classPtr = nullptr; - for (const std::pair<std::string, - dbus::utility::DbusVariantType>& - propPair : intfPair.second) + for (const std::pair<std::string, + dbus::utility::DbusVariantType>& propPair : + intfPair.second) + { + if (propPair.first == "Class") { - if (propPair.first == "Class") - { - classPtr = - std::get_if<std::string>(&propPair.second); - } + classPtr = std::get_if<std::string>(&propPair.second); } + } - if (intfPair.first == pidZoneConfigurationIface) + if (intfPair.first == pidZoneConfigurationIface) + { + std::string chassis; + if (!dbus::utility::getNthStringFromPath(pathPair.first.str, + 5, chassis)) { - std::string chassis; - if (!dbus::utility::getNthStringFromPath( - pathPair.first.str, 5, chassis)) - { - chassis = "#IllegalValue"; - } - nlohmann::json& zone = zones[name]; - zone["Chassis"] = { - {"@odata.id", "/redfish/v1/Chassis/" + chassis}}; - zone["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/" + - name; - zone["@odata.type"] = "#OemManager.FanZone"; - config = &zone; + chassis = "#IllegalValue"; } + nlohmann::json& zone = zones[name]; + zone["Chassis"] = { + {"@odata.id", "/redfish/v1/Chassis/" + chassis}}; + zone["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/" + + name; + zone["@odata.type"] = "#OemManager.FanZone"; + config = &zone; + } - else if (intfPair.first == stepwiseConfigurationIface) + else if (intfPair.first == stepwiseConfigurationIface) + { + if (classPtr == nullptr) { - if (classPtr == nullptr) - { - BMCWEB_LOG_ERROR << "Pid Class Field illegal"; - messages::internalError(asyncResp->res); - return; - } + BMCWEB_LOG_ERROR << "Pid Class Field illegal"; + messages::internalError(asyncResp->res); + return; + } - nlohmann::json& controller = stepwise[name]; - config = &controller; + nlohmann::json& controller = stepwise[name]; + config = &controller; - controller["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/StepwiseControllers/" + - name; - controller["@odata.type"] = - "#OemManager.StepwiseController"; + controller["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/StepwiseControllers/" + + name; + controller["@odata.type"] = + "#OemManager.StepwiseController"; - controller["Direction"] = *classPtr; - } + controller["Direction"] = *classPtr; + } - // pid and fans are off the same configuration - else if (intfPair.first == pidConfigurationIface) - { + // 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) - { - element["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanControllers/" + - name; - element["@odata.type"] = - "#OemManager.FanController"; - } - else - { - element["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/PidControllers/" + - name; - element["@odata.type"] = - "#OemManager.PidController"; - } - } - else + if (classPtr == nullptr) { - BMCWEB_LOG_ERROR << "Unexpected configuration"; + 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) + { + element["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanControllers/" + + name; + element["@odata.type"] = "#OemManager.FanController"; + } + else + { + element["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/PidControllers/" + + name; + 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; + // used for making maps out of 2 vectors + const std::vector<double>* keys = nullptr; + const std::vector<double>* values = nullptr; - for (const auto& propertyPair : intfPair.second) + for (const auto& propertyPair : intfPair.second) + { + if (propertyPair.first == "Type" || + propertyPair.first == "Class" || + propertyPair.first == "Name") { - if (propertyPair.first == "Type" || - propertyPair.first == "Class" || - propertyPair.first == "Name") + continue; + } + + // zones + if (intfPair.first == pidZoneConfigurationIface) + { + const double* ptr = + std::get_if<double>(&propertyPair.second); + if (ptr == nullptr) { - continue; + BMCWEB_LOG_ERROR << "Field Illegal " + << propertyPair.first; + messages::internalError(asyncResp->res); + return; } + (*config)[propertyPair.first] = *ptr; + } - // zones - if (intfPair.first == pidZoneConfigurationIface) + if (intfPair.first == stepwiseConfigurationIface) + { + if (propertyPair.first == "Reading" || + propertyPair.first == "Output") { - const double* ptr = - std::get_if<double>(&propertyPair.second); + const std::vector<double>* ptr = + std::get_if<std::vector<double>>( + &propertyPair.second); + if (ptr == nullptr) { BMCWEB_LOG_ERROR << "Field Illegal " @@ -495,199 +505,174 @@ inline void messages::internalError(asyncResp->res); return; } - (*config)[propertyPair.first] = *ptr; - } - if (intfPair.first == stepwiseConfigurationIface) - { - if (propertyPair.first == "Reading" || - propertyPair.first == "Output") + if (propertyPair.first == "Reading") { - const std::vector<double>* ptr = - std::get_if<std::vector<double>>( - &propertyPair.second); - - if (ptr == nullptr) + keys = ptr; + } + else + { + values = ptr; + } + if (keys != nullptr && values != nullptr) + { + if (keys->size() != values->size()) { - BMCWEB_LOG_ERROR << "Field Illegal " - << propertyPair.first; + BMCWEB_LOG_ERROR + << "Reading and Output size don't match "; messages::internalError(asyncResp->res); return; } - - if (propertyPair.first == "Reading") - { - keys = ptr; - } - else + nlohmann::json& steps = (*config)["Steps"]; + steps = nlohmann::json::array(); + for (size_t ii = 0; ii < keys->size(); ii++) { - 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.push_back(std::move(step)); - } + nlohmann::json::object_t step; + step["Target"] = (*keys)[ii]; + step["Output"] = (*values)[ii]; + steps.push_back(std::move(step)); } } - if (propertyPair.first == "NegativeHysteresis" || - propertyPair.first == "PositiveHysteresis") + } + if (propertyPair.first == "NegativeHysteresis" || + propertyPair.first == "PositiveHysteresis") + { + const double* ptr = + std::get_if<double>(&propertyPair.second); + if (ptr == nullptr) { - 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; + BMCWEB_LOG_ERROR << "Field Illegal " + << propertyPair.first; + messages::internalError(asyncResp->res); + return; } + (*config)[propertyPair.first] = *ptr; } + } + + // pid and fans are off the same configuration + if (intfPair.first == pidConfigurationIface || + intfPair.first == stepwiseConfigurationIface) + { - // 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 (propertyPair.first == "Zones") + if (inputs == nullptr) { - 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; - input["@odata.id"] = - "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/" + - itemCopy; - data.push_back(std::move(input)); - } + BMCWEB_LOG_ERROR << "Zones Pid Field Illegal"; + messages::internalError(asyncResp->res); + return; } - // 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") + auto& data = (*config)[propertyPair.first]; + data = nlohmann::json::array(); + for (std::string itemCopy : *inputs) { - 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; + dbus::utility::escapePathForDbus(itemCopy); + nlohmann::json::object_t input; + input["@odata.id"] = + "/redfish/v1/Managers/bmc#/Oem/OpenBmc/Fan/FanZones/" + + itemCopy; + data.push_back(std::move(input)); } - else if (propertyPair.first == "SetPointOffset") + } + // 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") + { + auto& data = (*config)[propertyPair.first]; + const std::vector<std::string>* inputs = + std::get_if<std::vector<std::string>>( + &propertyPair.second); + + if (inputs == nullptr) { - const std::string* ptr = - std::get_if<std::string>( - &propertyPair.second); + 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); - 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; - } + if (ptr == nullptr) + { + BMCWEB_LOG_ERROR << "Field Illegal " + << propertyPair.first; + 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") + // translate from dbus to redfish + if (*ptr == "WarningHigh") { - 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)["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) + { + BMCWEB_LOG_ERROR << "Field Illegal " + << propertyPair.first; + messages::internalError(asyncResp->res); + return; + } + (*config)[propertyPair.first] = *ptr; + } } } } + } }, connection, path, objectManagerIface, "GetManagedObjects"); } @@ -745,15 +730,15 @@ inline const dbus::utility::ManagedObjectType::value_type* std::string escaped = boost::replace_all_copy(value, " ", "_"); escaped = "/" + escaped; - auto it = std::find_if( - managedObj.begin(), managedObj.end(), [&escaped](const auto& obj) { - if (boost::algorithm::ends_with(obj.first.str, escaped)) - { - BMCWEB_LOG_DEBUG << "Matched " << obj.first.str << "\n"; - return true; - } - return false; - }); + auto it = std::find_if(managedObj.begin(), managedObj.end(), + [&escaped](const auto& obj) { + if (boost::algorithm::ends_with(obj.first.str, escaped)) + { + BMCWEB_LOG_DEBUG << "Matched " << obj.first.str << "\n"; + return true; + } + return false; + }); if (it == managedObj.end()) { @@ -804,13 +789,13 @@ 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; @@ -1197,13 +1182,13 @@ 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->subtree = subtreeLocal; + if (ec) + { + BMCWEB_LOG_ERROR << ec; + messages::internalError(self->asyncResp->res); + return; + } + self->subtree = subtreeLocal; }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1217,78 +1202,73 @@ 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) + 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; + crow::connections::systemBus->async_method_call( + [path, owner, + self](const boost::system::error_code ec2, + const dbus::utility::DBusPropertiesMap& resp) { + if (ec2) { - // invalid mapper response, should never happen - BMCWEB_LOG_ERROR << "GetPIDValues: Mapper Error"; + BMCWEB_LOG_ERROR + << "GetPIDValues: Can't get thermalModeIface " << path; messages::internalError(self->asyncResp->res); return; } - - const std::string& path = subtreeLocal[0].first; - const std::string& owner = subtreeLocal[0].second[0].first; - crow::connections::systemBus->async_method_call( - [path, owner, - self](const boost::system::error_code ec2, - const dbus::utility::DBusPropertiesMap& resp) { - if (ec2) + const std::string* current = nullptr; + const std::vector<std::string>* supported = nullptr; + for (const auto& [key, value] : resp) + { + if (key == "Current") + { + current = std::get_if<std::string>(&value); + if (current == nullptr) { BMCWEB_LOG_ERROR - << "GetPIDValues: Can't get thermalModeIface " + << "GetPIDValues: thermal mode iface invalid " << path; messages::internalError(self->asyncResp->res); return; } - const std::string* current = nullptr; - const std::vector<std::string>* supported = nullptr; - for (const auto& [key, value] : resp) - { - if (key == "Current") - { - current = std::get_if<std::string>(&value); - if (current == nullptr) - { - BMCWEB_LOG_ERROR - << "GetPIDValues: thermal mode iface invalid " - << path; - messages::internalError( - self->asyncResp->res); - return; - } - } - if (key == "Supported") - { - supported = - std::get_if<std::vector<std::string>>( - &value); - if (supported == nullptr) - { - BMCWEB_LOG_ERROR - << "GetPIDValues: thermal mode iface invalid" - << path; - messages::internalError( - self->asyncResp->res); - return; - } - } - } - if (current == nullptr || supported == nullptr) + } + if (key == "Supported") + { + supported = + std::get_if<std::vector<std::string>>(&value); + if (supported == nullptr) { BMCWEB_LOG_ERROR - << "GetPIDValues: thermal mode iface invalid " + << "GetPIDValues: thermal mode iface invalid" << path; messages::internalError(self->asyncResp->res); return; } - self->currentProfile = *current; - self->supportedProfiles = *supported; - }, - owner, path, "org.freedesktop.DBus.Properties", "GetAll", - thermalModeIface); + } + } + if (current == nullptr || supported == nullptr) + { + BMCWEB_LOG_ERROR + << "GetPIDValues: thermal mode iface invalid " << path; + messages::internalError(self->asyncResp->res); + return; + } + self->currentProfile = *current; + self->supportedProfiles = *supported; + }, + owner, path, "org.freedesktop.DBus.Properties", "GetAll", + thermalModeIface); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1409,30 +1389,29 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues> crow::connections::systemBus->async_method_call( [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& [path, object] : mObj) + { + for (const auto& [interface, _] : object) { - for (const auto& [interface, _] : object) + if (std::find(configurations.begin(), configurations.end(), + interface) != configurations.end()) { - if (std::find(configurations.begin(), - configurations.end(), - interface) != configurations.end()) - { - self->objectCount++; - break; - } + self->objectCount++; + break; } } - self->managedObj = mObj; + } + self->managedObj = mObj; }, "xyz.openbmc_project.EntityManager", "/", objectManagerIface, "GetManagedObjects"); @@ -1441,80 +1420,74 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues> crow::connections::systemBus->async_method_call( [self](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec || subtree.empty()) - { - return; - } - if (subtree[0].second.empty()) + 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; + crow::connections::systemBus->async_method_call( + [self, path, owner](const boost::system::error_code ec2, + const dbus::utility::DBusPropertiesMap& r) { + if (ec2) { - // invalid mapper response, should never happen - BMCWEB_LOG_ERROR << "SetPIDValues: Mapper Error"; + BMCWEB_LOG_ERROR + << "SetPIDValues: Can't get thermalModeIface " << path; messages::internalError(self->asyncResp->res); return; } - - const std::string& path = subtree[0].first; - const std::string& owner = subtree[0].second[0].first; - crow::connections::systemBus->async_method_call( - [self, path, - owner](const boost::system::error_code ec2, - const dbus::utility::DBusPropertiesMap& r) { - if (ec2) + const std::string* current = nullptr; + const std::vector<std::string>* supported = nullptr; + for (const auto& [key, value] : r) + { + if (key == "Current") + { + current = std::get_if<std::string>(&value); + if (current == nullptr) { BMCWEB_LOG_ERROR - << "SetPIDValues: Can't get thermalModeIface " + << "SetPIDValues: thermal mode iface invalid " << path; messages::internalError(self->asyncResp->res); return; } - const std::string* current = nullptr; - const std::vector<std::string>* supported = nullptr; - for (const auto& [key, value] : r) - { - if (key == "Current") - { - current = std::get_if<std::string>(&value); - if (current == nullptr) - { - BMCWEB_LOG_ERROR - << "SetPIDValues: thermal mode iface invalid " - << path; - messages::internalError( - self->asyncResp->res); - return; - } - } - if (key == "Supported") - { - supported = - std::get_if<std::vector<std::string>>( - &value); - if (supported == nullptr) - { - BMCWEB_LOG_ERROR - << "SetPIDValues: thermal mode iface invalid" - << path; - messages::internalError( - self->asyncResp->res); - return; - } - } - } - if (current == nullptr || supported == nullptr) + } + if (key == "Supported") + { + supported = + std::get_if<std::vector<std::string>>(&value); + if (supported == nullptr) { BMCWEB_LOG_ERROR - << "SetPIDValues: thermal mode iface invalid " + << "SetPIDValues: thermal mode iface invalid" << path; messages::internalError(self->asyncResp->res); return; } - self->currentProfile = *current; - self->supportedProfiles = *supported; - self->profileConnection = owner; - self->profilePath = path; - }, - owner, path, "org.freedesktop.DBus.Properties", "GetAll", - thermalModeIface); + } + } + 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; + }, + owner, path, "org.freedesktop.DBus.Properties", "GetAll", + thermalModeIface); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1540,11 +1513,11 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues> currentProfile = *profile; crow::connections::systemBus->async_method_call( [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); + } }, profileConnection, profilePath, "org.freedesktop.DBus.Properties", "Set", thermalModeIface, @@ -1571,9 +1544,9 @@ struct SetPIDValues : std::enable_shared_from_this<SetPIDValues> auto pathItr = std::find_if(managedObj.begin(), managedObj.end(), [&name](const auto& obj) { - return boost::algorithm::ends_with( - obj.first.str, "/" + name); - }); + return boost::algorithm::ends_with(obj.first.str, + "/" + name); + }); dbus::utility::DBusPropertiesMap output; output.reserve(16); // The pid interface length @@ -1664,15 +1637,14 @@ 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, @@ -1710,14 +1682,14 @@ 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); @@ -1769,16 +1741,16 @@ inline void getLocation(const std::shared_ptr<bmcweb::AsyncResp>& aResp, "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", [aResp](const boost::system::error_code ec, const std::string& property) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error for " - "Location"; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error for " + "Location"; + messages::internalError(aResp->res); + return; + } - aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = - property; + aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = + property; }); } // avoid name collision systems.hpp @@ -1793,19 +1765,19 @@ inline void "LastRebootTime", [aResp](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 - aResp->res.jsonValue["LastResetTime"] = - crow::utility::getDateTimeUint(lastResetTimeStamp); + // Convert to ISO 8601 standard + aResp->res.jsonValue["LastResetTime"] = + crow::utility::getDateTimeUint(lastResetTimeStamp); }); } @@ -1845,75 +1817,75 @@ inline void [aResp, firmwareId, runningFirmwareTarget](const boost::system::error_code ec, dbus::utility::ManagedObjectType& subtree) { - if (ec) + if (ec) + { + BMCWEB_LOG_DEBUG << "D-Bus response error getting objects."; + messages::internalError(aResp->res); + return; + } + + if (subtree.empty()) + { + BMCWEB_LOG_DEBUG << "Can't find image!"; + messages::internalError(aResp->res); + return; + } + + bool foundImage = false; + for (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) { - BMCWEB_LOG_DEBUG << "D-Bus response error getting objects."; - messages::internalError(aResp->res); - return; + continue; } - if (subtree.empty()) + idPos2++; + if (idPos2 >= path.size()) { - BMCWEB_LOG_DEBUG << "Can't find image!"; - messages::internalError(aResp->res); - return; + continue; } - bool foundImage = false; - for (auto& object : subtree) + if (path.substr(idPos2) == firmwareId) { - const std::string& path = - static_cast<const std::string&>(object.first); - std::size_t idPos2 = path.rfind('/'); - - if (idPos2 == std::string::npos) - { - continue; - } + foundImage = true; + break; + } + } - idPos2++; - if (idPos2 >= path.size()) - { - continue; - } + if (!foundImage) + { + messages::propertyValueNotInList(aResp->res, runningFirmwareTarget, + "@odata.id"); + BMCWEB_LOG_DEBUG << "Invalid firmware ID."; + return; + } - if (path.substr(idPos2) == firmwareId) - { - foundImage = true; - break; - } - } + BMCWEB_LOG_DEBUG << "Setting firmware version " << firmwareId + << " to priority 0."; - if (!foundImage) + // Only support Immediate + // An addition could be a Redfish Setting like + // ActiveSoftwareImageApplyTime and support OnReset + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) { - messages::propertyValueNotInList( - aResp->res, runningFirmwareTarget, "@odata.id"); - BMCWEB_LOG_DEBUG << "Invalid firmware ID."; + BMCWEB_LOG_DEBUG << "D-Bus response error setting."; + messages::internalError(aResp->res); return; } + doBMCGracefulRestart(aResp); + }, - BMCWEB_LOG_DEBUG << "Setting firmware version " << firmwareId - << " to priority 0."; - - // Only support Immediate - // An addition could be a Redfish Setting like - // ActiveSoftwareImageApplyTime and support OnReset - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "D-Bus response error setting."; - messages::internalError(aResp->res); - return; - } - doBMCGracefulRestart(aResp); - }, - - "xyz.openbmc_project.Software.BMC.Updater", - "/xyz/openbmc_project/software/" + firmwareId, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Software.RedundancyPriority", "Priority", - dbus::utility::DbusVariantType(static_cast<uint8_t>(0))); + "xyz.openbmc_project.Software.BMC.Updater", + "/xyz/openbmc_project/software/" + firmwareId, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Software.RedundancyPriority", "Priority", + dbus::utility::DbusVariantType(static_cast<uint8_t>(0))); }, "xyz.openbmc_project.Software.BMC.Updater", "/xyz/openbmc_project/software", "org.freedesktop.DBus.ObjectManager", @@ -1945,15 +1917,15 @@ inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> aResp, crow::connections::systemBus->async_method_call( [aResp{std::move(aResp)}, datetime{std::move(datetime)}]( const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "Failed to set elapsed time. " - "DBUS response error " - << ec; - messages::internalError(aResp->res); - return; - } - aResp->res.jsonValue["DateTime"] = datetime; + if (ec) + { + BMCWEB_LOG_DEBUG << "Failed to set elapsed time. " + "DBUS response error " + << ec; + messages::internalError(aResp->res); + return; + } + aResp->res.jsonValue["DateTime"] = datetime; }, "xyz.openbmc_project.Time.Manager", "/xyz/openbmc_project/time/bmc", "org.freedesktop.DBus.Properties", "Set", @@ -1973,266 +1945,243 @@ inline void requestRoutesManager(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/") .privileges(redfish::privileges::getManager) - .methods( - boost::beast::http::verb:: - get)([&app, uuid]( - const crow::Request& req, + .methods(boost::beast::http::verb::get)( + [&app, uuid](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers/bmc"; - asyncResp->res.jsonValue["@odata.type"] = - "#Manager.v1_11_0.Manager"; - asyncResp->res.jsonValue["Id"] = "bmc"; - asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; - asyncResp->res.jsonValue["Description"] = - "Baseboard Management Controller"; - asyncResp->res.jsonValue["PowerState"] = "On"; - asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; - asyncResp->res.jsonValue["Status"]["Health"] = "OK"; - - 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"] = - "/redfish/v1/Managers/bmc/LogServices"; - asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = - "/redfish/v1/Managers/bmc/NetworkProtocol"; - asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = - "/redfish/v1/Managers/bmc/EthernetInterfaces"; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Managers/bmc"; + asyncResp->res.jsonValue["@odata.type"] = "#Manager.v1_11_0.Manager"; + asyncResp->res.jsonValue["Id"] = "bmc"; + asyncResp->res.jsonValue["Name"] = "OpenBmc Manager"; + asyncResp->res.jsonValue["Description"] = + "Baseboard Management Controller"; + asyncResp->res.jsonValue["PowerState"] = "On"; + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + asyncResp->res.jsonValue["Status"]["Health"] = "OK"; + + 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"] = + "/redfish/v1/Managers/bmc/LogServices"; + asyncResp->res.jsonValue["NetworkProtocol"]["@odata.id"] = + "/redfish/v1/Managers/bmc/NetworkProtocol"; + asyncResp->res.jsonValue["EthernetInterfaces"]["@odata.id"] = + "/redfish/v1/Managers/bmc/EthernetInterfaces"; #ifdef BMCWEB_ENABLE_VM_NBDPROXY - asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = - "/redfish/v1/Managers/bmc/VirtualMedia"; + asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] = + "/redfish/v1/Managers/bmc/VirtualMedia"; #endif // BMCWEB_ENABLE_VM_NBDPROXY - // default oem data - nlohmann::json& oem = asyncResp->res.jsonValue["Oem"]; - nlohmann::json& oemOpenbmc = oem["OpenBmc"]; - oem["@odata.type"] = "#OemManager.Oem"; - oem["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem"; - oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc"; - oemOpenbmc["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc"; - - nlohmann::json::object_t certificates; - certificates["@odata.id"] = - "/redfish/v1/Managers/bmc/Truststore/Certificates"; - 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"] = - "/redfish/v1/Managers/bmc/Actions/Manager.Reset"; - managerReset["@Redfish.ActionInfo"] = - "/redfish/v1/Managers/bmc/ResetActionInfo"; - - // 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"] = - "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults"; - resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"}; - - std::pair<std::string, std::string> redfishDateTimeOffset = - crow::utility::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"] = - {"IPMI", "SSH"}; + // default oem data + nlohmann::json& oem = asyncResp->res.jsonValue["Oem"]; + nlohmann::json& oemOpenbmc = oem["OpenBmc"]; + oem["@odata.type"] = "#OemManager.Oem"; + oem["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem"; + oemOpenbmc["@odata.type"] = "#OemManager.OpenBmc"; + oemOpenbmc["@odata.id"] = "/redfish/v1/Managers/bmc#/Oem/OpenBmc"; + + nlohmann::json::object_t certificates; + certificates["@odata.id"] = + "/redfish/v1/Managers/bmc/Truststore/Certificates"; + 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"] = + "/redfish/v1/Managers/bmc/Actions/Manager.Reset"; + managerReset["@Redfish.ActionInfo"] = + "/redfish/v1/Managers/bmc/ResetActionInfo"; + + // 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"] = + "/redfish/v1/Managers/bmc/Actions/Manager.ResetToDefaults"; + resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"}; + + std::pair<std::string, std::string> redfishDateTimeOffset = + crow::utility::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"] = { + "IPMI", "SSH"}; #ifdef BMCWEB_ENABLE_KVM - // Fill in GraphicalConsole info - asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = - true; - asyncResp->res - .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4; - asyncResp->res.jsonValue["GraphicalConsole"] - ["ConnectTypesSupported"] = {"KVMIP"}; + // Fill in GraphicalConsole info + asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true; + asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = + 4; + asyncResp->res + .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"}; #endif // BMCWEB_ENABLE_KVM - asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] = - 1; + asyncResp->res.jsonValue["Links"]["ManagerForServers@odata.count"] = 1; + + nlohmann::json::array_t managerForServers; + nlohmann::json::object_t manager; + manager["@odata.id"] = "/redfish/v1/Systems/system"; + managerForServers.push_back(std::move(manager)); + + asyncResp->res.jsonValue["Links"]["ManagerForServers"] = + std::move(managerForServers); + + auto health = std::make_shared<HealthPopulate>(asyncResp); + health->isManagersHealth = true; + health->populate(); + + fw_util::populateFirmwareInformation(asyncResp, fw_util::bmcPurpose, + "FirmwareVersion", true); - nlohmann::json::array_t managerForServers; + managerGetLastResetTime(asyncResp); + + 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 manager; - manager["@odata.id"] = "/redfish/v1/Systems/system"; - managerForServers.push_back(std::move(manager)); - - asyncResp->res.jsonValue["Links"]["ManagerForServers"] = - std::move(managerForServers); - - auto health = std::make_shared<HealthPopulate>(asyncResp); - health->isManagersHealth = true; - health->populate(); - - fw_util::populateFirmwareInformation(asyncResp, fw_util::bmcPurpose, - "FirmwareVersion", true); - - managerGetLastResetTime(asyncResp); - - 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 manager; - manager["@odata.id"] = "/redfish/v1/Chassis/" + chassisId; - managerForChassis.push_back(std::move(manager)); - aRsp->res.jsonValue["Links"]["ManagerForChassis"] = - std::move(managerForChassis); - aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId; - }); - - static bool started = false; - - if (!started) + manager["@odata.id"] = "/redfish/v1/Chassis/" + chassisId; + managerForChassis.push_back(std::move(manager)); + aRsp->res.jsonValue["Links"]["ManagerForChassis"] = + std::move(managerForChassis); + aRsp->res.jsonValue["Links"]["ManagerInChassis"]["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId; + }); + + static bool started = false; + + if (!started) + { + 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, + const double& val) { + if (ec) + { + BMCWEB_LOG_ERROR << "Error while getting progress"; + messages::internalError(asyncResp->res); + return; + } + if (val < 1.0) + { + asyncResp->res.jsonValue["Status"]["State"] = "Starting"; + started = true; + } + }); + } + + crow::connections::systemBus->async_method_call( + [asyncResp]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec) { - 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, - const double& val) { - if (ec) - { - BMCWEB_LOG_ERROR << "Error while getting progress"; - messages::internalError(asyncResp->res); - return; - } - if (val < 1.0) - { - asyncResp->res.jsonValue["Status"]["State"] = - "Starting"; - started = true; - } - }); + 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; } - crow::connections::systemBus->async_method_call( - [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 (subtree[0].first.empty() || - subtree[0].second.size() != 1) - { - BMCWEB_LOG_DEBUG << "Error getting bmc D-Bus object!"; - messages::internalError(asyncResp->res); - return; - } + 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; + const std::string& path = subtree[0].first; + const std::string& connectionName = subtree[0].second[0].first; - for (const auto& interfaceName : - subtree[0].second[0].second) - { - if (interfaceName == - "xyz.openbmc_project.Inventory.Decorator.Asset") - { - crow::connections::systemBus->async_method_call( - [asyncResp]( - const boost::system::error_code ec, + for (const auto& interfaceName : subtree[0].second[0].second) + { + if (interfaceName == + "xyz.openbmc_project.Inventory.Decorator.Asset") + { + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, const dbus::utility::DBusPropertiesMap& propertiesList) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "Can't get bmc asset!"; - return; - } - for (const std::pair< - std::string, - dbus::utility::DbusVariantType>& - property : propertiesList) - { - const std::string& propertyName = - property.first; - - if ((propertyName == "PartNumber") || - (propertyName == "SerialNumber") || - (propertyName == "Manufacturer") || - (propertyName == "Model") || - (propertyName == "SparePartNumber")) - { - const std::string* value = - std::get_if<std::string>( - &property.second); - if (value == nullptr) - { - // illegal property - messages::internalError( - asyncResp->res); - return; - } - asyncResp->res - .jsonValue[propertyName] = - *value; - } - } - }, - connectionName, path, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Inventory.Decorator.Asset"); + if (ec) + { + BMCWEB_LOG_DEBUG << "Can't get bmc asset!"; + return; } - else if ( - interfaceName == - "xyz.openbmc_project.Inventory.Decorator.LocationCode") + for (const std::pair<std::string, + dbus::utility::DbusVariantType>& + property : propertiesList) { - getLocation(asyncResp, connectionName, path); + const std::string& propertyName = property.first; + + if ((propertyName == "PartNumber") || + (propertyName == "SerialNumber") || + (propertyName == "Manufacturer") || + (propertyName == "Model") || + (propertyName == "SparePartNumber")) + { + const std::string* value = + std::get_if<std::string>(&property.second); + if (value == nullptr) + { + // illegal property + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue[propertyName] = *value; + } } - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", int32_t(0), - std::array<const char*, 1>{ - "xyz.openbmc_project.Inventory.Item.Bmc"}); + }, + connectionName, path, "org.freedesktop.DBus.Properties", + "GetAll", + "xyz.openbmc_project.Inventory.Decorator.Asset"); + } + else if (interfaceName == + "xyz.openbmc_project.Inventory.Decorator.LocationCode") + { + getLocation(asyncResp, connectionName, path); + } + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", int32_t(0), + std::array<const char*, 1>{ + "xyz.openbmc_project.Inventory.Item.Bmc"}); }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/") @@ -2240,85 +2189,81 @@ inline void requestRoutesManager(App& app) .methods(boost::beast::http::verb::patch)( [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<nlohmann::json> oem; - std::optional<nlohmann::json> links; - std::optional<std::string> datetime; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<nlohmann::json> oem; + std::optional<nlohmann::json> links; + std::optional<std::string> datetime; - if (!json_util::readJsonPatch(req, asyncResp->res, "Oem", oem, - "DateTime", datetime, "Links", - links)) + if (!json_util::readJsonPatch(req, asyncResp->res, "Oem", oem, + "DateTime", datetime, "Links", links)) + { + return; + } + + if (oem) + { + std::optional<nlohmann::json> openbmc; + if (!redfish::json_util::readJson(*oem, asyncResp->res, "OpenBmc", + openbmc)) + { + BMCWEB_LOG_ERROR + << "Illegal Property " + << oem->dump(2, ' ', true, + nlohmann::json::error_handler_t::replace); + return; + } + if (openbmc) + { + std::optional<nlohmann::json> fan; + if (!redfish::json_util::readJson(*openbmc, asyncResp->res, + "Fan", fan)) { + BMCWEB_LOG_ERROR + << "Illegal Property " + << openbmc->dump( + 2, ' ', true, + nlohmann::json::error_handler_t::replace); return; } - - if (oem) + if (fan) { - std::optional<nlohmann::json> openbmc; - if (!redfish::json_util::readJson(*oem, asyncResp->res, - "OpenBmc", openbmc)) - { - BMCWEB_LOG_ERROR - << "Illegal Property " - << oem->dump( - 2, ' ', true, - nlohmann::json::error_handler_t::replace); - return; - } - if (openbmc) - { - std::optional<nlohmann::json> fan; - if (!redfish::json_util::readJson( - *openbmc, asyncResp->res, "Fan", fan)) - { - BMCWEB_LOG_ERROR - << "Illegal Property " - << openbmc->dump(2, ' ', true, - nlohmann::json:: - error_handler_t::replace); - return; - } - if (fan) - { - auto pid = - std::make_shared<SetPIDValues>(asyncResp, *fan); - pid->run(); - } - } + auto pid = std::make_shared<SetPIDValues>(asyncResp, *fan); + pid->run(); } - if (links) + } + } + if (links) + { + std::optional<nlohmann::json> activeSoftwareImage; + if (!redfish::json_util::readJson(*links, asyncResp->res, + "ActiveSoftwareImage", + activeSoftwareImage)) + { + return; + } + if (activeSoftwareImage) + { + std::optional<std::string> odataId; + if (!json_util::readJson(*activeSoftwareImage, asyncResp->res, + "@odata.id", odataId)) { - std::optional<nlohmann::json> activeSoftwareImage; - if (!redfish::json_util::readJson(*links, asyncResp->res, - "ActiveSoftwareImage", - activeSoftwareImage)) - { - return; - } - if (activeSoftwareImage) - { - std::optional<std::string> odataId; - if (!json_util::readJson(*activeSoftwareImage, - asyncResp->res, "@odata.id", - odataId)) - { - return; - } - - if (odataId) - { - setActiveFirmwareImage(asyncResp, *odataId); - } - } + return; } - if (datetime) + + if (odataId) { - setDateTime(asyncResp, std::move(*datetime)); + setActiveFirmwareImage(asyncResp, *odataId); } - }); + } + } + if (datetime) + { + setDateTime(asyncResp, std::move(*datetime)); + } + }); } inline void requestRoutesManagerCollection(App& app) @@ -2328,21 +2273,21 @@ 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->res)) - { - 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"] = "/redfish/v1/Managers/bmc"; - asyncResp->res.jsonValue["Members"] = std::move(members); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"] = "/redfish/v1/Managers/bmc"; + asyncResp->res.jsonValue["Members"] = std::move(members); + }); } } // namespace redfish diff --git a/redfish-core/lib/memory.hpp b/redfish-core/lib/memory.hpp index 68be9a762d..27f5a5b4eb 100644 --- a/redfish-core/lib/memory.hpp +++ b/redfish-core/lib/memory.hpp @@ -698,13 +698,13 @@ inline void getDimmDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, [dimmId, aResp{std::move(aResp)}]( const boost::system::error_code ec, const dbus::utility::DBusPropertiesMap& properties) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; - } - assembleDimmProperties(dimmId, aResp, properties); + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } + assembleDimmProperties(dimmId, aResp, properties); }, service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); } @@ -781,14 +781,14 @@ inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp, [aResp{std::move(aResp)}]( const boost::system::error_code ec, const dbus::utility::DBusPropertiesMap& properties) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); - return; - } - assembleDimmPartitionData(aResp, properties); + return; + } + assembleDimmPartitionData(aResp, properties); }, service, path, "org.freedesktop.DBus.Properties", "GetAll", @@ -803,55 +803,54 @@ inline void getDimmData(std::shared_ptr<bmcweb::AsyncResp> aResp, [dimmId, aResp{std::move(aResp)}]( const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); - return; - } - bool found = false; - for (const auto& [path, object] : subtree) + return; + } + bool found = false; + for (const auto& [path, object] : subtree) + { + if (path.find(dimmId) != std::string::npos) { - if (path.find(dimmId) != std::string::npos) + for (const auto& [service, interfaces] : object) { - for (const auto& [service, interfaces] : object) + for (const auto& interface : interfaces) { - for (const auto& interface : interfaces) + if (interface == + "xyz.openbmc_project.Inventory.Item.Dimm") + { + getDimmDataByService(aResp, dimmId, service, path); + 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") { - if (interface == - "xyz.openbmc_project.Inventory.Item.Dimm") - { - getDimmDataByService(aResp, dimmId, service, - path); - 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") - { - getDimmPartitionData(aResp, service, path); - } + getDimmPartitionData(aResp, service, path); } } } } - // Object not found - if (!found) - { - messages::resourceNotFound(aResp->res, "Memory", dimmId); - return; - } - // Set @odata only if object is found - aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory"; - aResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Memory/" + dimmId; + } + // Object not found + if (!found) + { + messages::resourceNotFound(aResp->res, "Memory", dimmId); return; + } + // Set @odata only if object is found + aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory"; + aResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Memory/" + dimmId; + return; }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -872,20 +871,20 @@ inline void requestRoutesMemoryCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#MemoryCollection.MemoryCollection"; - asyncResp->res.jsonValue["Name"] = "Memory Module Collection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Memory"; - - collection_util::getCollectionMembers( - asyncResp, "/redfish/v1/Systems/system/Memory", - {"xyz.openbmc_project.Inventory.Item.Dimm"}); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#MemoryCollection.MemoryCollection"; + asyncResp->res.jsonValue["Name"] = "Memory Module Collection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Memory"; + + collection_util::getCollectionMembers( + asyncResp, "/redfish/v1/Systems/system/Memory", + {"xyz.openbmc_project.Inventory.Item.Dimm"}); + }); } inline void requestRoutesMemory(App& app) @@ -899,12 +898,12 @@ inline void requestRoutesMemory(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& dimmId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - getDimmData(asyncResp, dimmId); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + getDimmData(asyncResp, dimmId); + }); } } // namespace redfish diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp index a47f6efcf4..3dd7181558 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp @@ -68,22 +68,20 @@ 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->res)) - { - return; - } - - asyncResp->res.jsonValue["@odata.type"] = - "#MetricReportCollection.MetricReportCollection"; - asyncResp->res.jsonValue["@odata.id"] = - telemetry::metricReportUri; - asyncResp->res.jsonValue["Name"] = "Metric Report Collection"; - const std::vector<const char*> interfaces{ - telemetry::reportInterface}; - collection_util::getCollectionMembers( - asyncResp, telemetry::metricReportUri, interfaces, - "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + + asyncResp->res.jsonValue["@odata.type"] = + "#MetricReportCollection.MetricReportCollection"; + asyncResp->res.jsonValue["@odata.id"] = telemetry::metricReportUri; + asyncResp->res.jsonValue["Name"] = "Metric Report Collection"; + const std::vector<const char*> interfaces{telemetry::reportInterface}; + collection_util::getCollectionMembers( + asyncResp, telemetry::metricReportUri, interfaces, + "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); + }); } inline void requestRoutesMetricReport(App& app) @@ -94,49 +92,43 @@ 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->res)) + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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 ec, + const telemetry::TimestampReadings& ret) { + if (ec) { + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + messages::internalError(asyncResp->res); 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 ec, - const telemetry::TimestampReadings& ret) { - if (ec) - { - BMCWEB_LOG_ERROR - << "respHandler DBus error " << ec; - messages::internalError(asyncResp->res); - return; - } - - telemetry::fillReport(asyncResp->res.jsonValue, - id, ret); - }); - }, - telemetry::service, reportPath, telemetry::reportInterface, - "Update"); - }); + + telemetry::fillReport(asyncResp->res.jsonValue, id, ret); + }); + }, + 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 b01c3bd13d..b5f59bece8 100644 --- a/redfish-core/lib/metric_report_definition.hpp +++ b/redfish-core/lib/metric_report_definition.hpp @@ -292,37 +292,36 @@ class AddReport crow::connections::systemBus->async_method_call( [aResp, name = args.name, uriToDbus = std::move(uriToDbus)]( const boost::system::error_code ec, const std::string&) { - if (ec == boost::system::errc::file_exists) - { - messages::resourceAlreadyExists( - aResp->res, "MetricReportDefinition", "Id", name); - return; - } - if (ec == boost::system::errc::too_many_files_open) - { - messages::createLimitReachedForResource(aResp->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(aResp->res, - metricProperties.dump(), - "MetricProperties"); - return; - } - if (ec) + if (ec == boost::system::errc::file_exists) + { + messages::resourceAlreadyExists( + aResp->res, "MetricReportDefinition", "Id", name); + return; + } + if (ec == boost::system::errc::too_many_files_open) + { + messages::createLimitReachedForResource(aResp->res); + return; + } + if (ec == boost::system::errc::argument_list_too_long) + { + nlohmann::json metricProperties = nlohmann::json::array(); + for (const auto& [uri, _] : uriToDbus) { - messages::internalError(aResp->res); - BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; - return; + metricProperties.emplace_back(uri); } + messages::propertyValueIncorrect( + aResp->res, metricProperties.dump(), "MetricProperties"); + return; + } + if (ec) + { + messages::internalError(aResp->res); + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + return; + } - messages::created(aResp->res); + messages::created(aResp->res); }, telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", "xyz.openbmc_project.Telemetry.ReportManager", "AddReport", @@ -355,71 +354,67 @@ inline void requestRoutesMetricReportDefinitionCollection(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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#MetricReportDefinitionCollection." - "MetricReportDefinitionCollection"; - asyncResp->res.jsonValue["@odata.id"] = - telemetry::metricReportDefinitionUri; - asyncResp->res.jsonValue["Name"] = - "Metric Definition Collection"; - const std::vector<const char*> interfaces{ - telemetry::reportInterface}; - collection_util::getCollectionMembers( - asyncResp, telemetry::metricReportDefinitionUri, interfaces, - "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); - }); + asyncResp->res.jsonValue["@odata.type"] = + "#MetricReportDefinitionCollection." + "MetricReportDefinitionCollection"; + asyncResp->res.jsonValue["@odata.id"] = + telemetry::metricReportDefinitionUri; + asyncResp->res.jsonValue["Name"] = "Metric Definition Collection"; + const std::vector<const char*> interfaces{telemetry::reportInterface}; + collection_util::getCollectionMembers( + asyncResp, telemetry::metricReportDefinitionUri, interfaces, + "/xyz/openbmc_project/Telemetry/Reports/TelemetryService"); + }); BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") .privileges(redfish::privileges::postMetricReportDefinitionCollection) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - telemetry::AddReportArgs args; - if (!telemetry::getUserParameters(asyncResp->res, req, args)) - { - return; - } + telemetry::AddReportArgs args; + if (!telemetry::getUserParameters(asyncResp->res, req, args)) + { + return; + } - boost::container::flat_set<std::pair<std::string, std::string>> - chassisSensors; - if (!telemetry::getChassisSensorNodeFromMetrics( - asyncResp, args.metrics, chassisSensors)) - { - return; - } + boost::container::flat_set<std::pair<std::string, std::string>> + chassisSensors; + if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics, + chassisSensors)) + { + return; + } - auto addReportReq = std::make_shared<telemetry::AddReport>( - std::move(args), asyncResp); - for (const auto& [chassis, sensorType] : chassisSensors) - { - retrieveUriToDbusMap( - chassis, sensorType, - [asyncResp, - addReportReq](const boost::beast::http::status status, - const boost::container::flat_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; - } - addReportReq->insert(uriToDbus); - }); - } + auto addReportReq = + std::make_shared<telemetry::AddReport>(std::move(args), asyncResp); + for (const auto& [chassis, sensorType] : chassisSensors) + { + retrieveUriToDbusMap( + chassis, sensorType, + [asyncResp, addReportReq]( + const boost::beast::http::status status, + const boost::container::flat_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; + } + addReportReq->insert(uriToDbus); + }); + } }); } @@ -432,37 +427,36 @@ inline void requestRoutesMetricReportDefinition(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - crow::connections::systemBus->async_method_call( - [asyncResp, - id](const boost::system::error_code ec, - const std::vector<std::pair< - std::string, dbus::utility::DbusVariantType>>& - ret) { - if (ec.value() == EBADR || - ec == boost::system::errc::host_unreachable) - { - messages::resourceNotFound( - asyncResp->res, "MetricReportDefinition", id); - return; - } - if (ec) - { - BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; - messages::internalError(asyncResp->res); - return; - } - - telemetry::fillReportDefinition(asyncResp, id, ret); - }, - telemetry::service, telemetry::getDbusReportPath(id), - "org.freedesktop.DBus.Properties", "GetAll", - telemetry::reportInterface); - }); + crow::connections::systemBus->async_method_call( + [asyncResp, + id](const boost::system::error_code ec, + const std::vector<std::pair< + std::string, dbus::utility::DbusVariantType>>& ret) { + if (ec.value() == EBADR || + ec == boost::system::errc::host_unreachable) + { + messages::resourceNotFound(asyncResp->res, + "MetricReportDefinition", id); + return; + } + if (ec) + { + BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; + messages::internalError(asyncResp->res); + return; + } + + telemetry::fillReportDefinition(asyncResp, id, ret); + }, + telemetry::service, telemetry::getDbusReportPath(id), + "org.freedesktop.DBus.Properties", "GetAll", + telemetry::reportInterface); + }); BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/") .privileges(redfish::privileges::deleteMetricReportDefinitionCollection) @@ -472,38 +466,37 @@ inline void requestRoutesMetricReportDefinition(App& app) const std::string& id) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + + const std::string reportPath = telemetry::getDbusReportPath(id); - const std::string reportPath = telemetry::getDbusReportPath(id); - - 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; - } - - 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, reportPath, - "xyz.openbmc_project.Object.Delete", "Delete"); - }); + 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; + } + + 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, reportPath, "xyz.openbmc_project.Object.Delete", + "Delete"); + }); } } // namespace redfish diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp index a6dd3b0a40..cfb4451466 100644 --- a/redfish-core/lib/network_protocol.hpp +++ b/redfish-core/lib/network_protocol.hpp @@ -87,19 +87,18 @@ void getEthernetIfaceData(CallbackFunc&& callback) [callback{std::forward<CallbackFunc>(callback)}]( const boost::system::error_code errorCode, const dbus::utility::ManagedObjectType& dbusData) { - std::vector<std::string> ntpServers; - std::vector<std::string> domainNames; + std::vector<std::string> ntpServers; + std::vector<std::string> domainNames; - if (errorCode) - { - callback(false, ntpServers, domainNames); - return; - } + if (errorCode) + { + callback(false, ntpServers, domainNames); + return; + } - extractNTPServersAndDomainNamesData(dbusData, ntpServers, - domainNames); + extractNTPServersAndDomainNamesData(dbusData, ntpServers, domainNames); - callback(true, ntpServers, domainNames); + callback(true, ntpServers, domainNames); }, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -132,10 +131,10 @@ inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, getNTPProtocolEnabled(asyncResp); - getEthernetIfaceData([hostName, asyncResp]( - const bool& success, - std::vector<std::string>& ntpServers, - const std::vector<std::string>& domainNames) { + getEthernetIfaceData( + [hostName, asyncResp](const bool& success, + std::vector<std::string>& ntpServers, + const std::vector<std::string>& domainNames) { if (!success) { messages::resourceNotFound(asyncResp->res, "ManagerNetworkProtocol", @@ -178,34 +177,32 @@ inline void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, [asyncResp, protocolName](const boost::system::error_code ec, const std::string& socketPath, bool isProtocolEnabled) { - // If the service is not installed, that is not an error - if (ec == boost::system::errc::no_such_process) - { - asyncResp->res.jsonValue[protocolName]["Port"] = - nlohmann::detail::value_t::null; - asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = - false; - return; - } + // If the service is not installed, that is not an error + if (ec == boost::system::errc::no_such_process) + { + asyncResp->res.jsonValue[protocolName]["Port"] = + nlohmann::detail::value_t::null; + asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = + false; + return; + } + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = + isProtocolEnabled; + getPortNumber(socketPath, [asyncResp, protocolName]( + const boost::system::error_code ec, + int portNumber) { if (ec) { messages::internalError(asyncResp->res); return; } - asyncResp->res.jsonValue[protocolName]["ProtocolEnabled"] = - isProtocolEnabled; - getPortNumber( - socketPath, - [asyncResp, protocolName]( - const boost::system::error_code ec, int portNumber) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue[protocolName]["Port"] = - portNumber; - }); + asyncResp->res.jsonValue[protocolName]["Port"] = portNumber; + }); }); } } // namespace redfish @@ -226,10 +223,10 @@ inline void handleNTPProtocolEnabled( crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code errorCode) { - if (errorCode) - { - messages::internalError(asyncResp->res); - } + if (errorCode) + { + messages::internalError(asyncResp->res); + } }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/time/sync_method", "org.freedesktop.DBus.Properties", "Set", @@ -255,41 +252,39 @@ inline void [asyncResp, ntpServers](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& [objectPath, serviceMap] : subtree) + { + for (const auto& [service, interfaces] : serviceMap) { - for (const auto& [service, interfaces] : serviceMap) + for (const auto& interface : interfaces) { - for (const auto& interface : interfaces) + if (interface != + "xyz.openbmc_project.Network.EthernetInterface") { - if (interface != - "xyz.openbmc_project.Network.EthernetInterface") + continue; + } + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) { - continue; + messages::internalError(asyncResp->res); + return; } - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - }, - service, objectPath, - "org.freedesktop.DBus.Properties", "Set", interface, - "NTPServers", - dbus::utility::DbusVariantType{ntpServers}); - } + }, + service, objectPath, "org.freedesktop.DBus.Properties", + "Set", interface, "NTPServers", + dbus::utility::DbusVariantType{ntpServers}); } } + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -308,45 +303,43 @@ 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) + for (const auto& entry : subtree) + { + if (boost::algorithm::starts_with(entry.first, netBasePath)) { - if (boost::algorithm::starts_with(entry.first, netBasePath)) - { - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec2) { - if (ec2) - { - messages::internalError(asyncResp->res); - return; - } - }, - entry.second.begin()->first, entry.first, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Service.Attributes", - "Running", - dbus::utility::DbusVariantType{protocolEnabled}); - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec2) { - if (ec2) - { - messages::internalError(asyncResp->res); - return; - } - }, - entry.second.begin()->first, entry.first, - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Service.Attributes", - "Enabled", - dbus::utility::DbusVariantType{protocolEnabled}); - } + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec2) { + if (ec2) + { + messages::internalError(asyncResp->res); + return; + } + }, + entry.second.begin()->first, entry.first, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Service.Attributes", "Running", + dbus::utility::DbusVariantType{protocolEnabled}); + + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec2) { + if (ec2) + { + messages::internalError(asyncResp->res); + return; + } + }, + entry.second.begin()->first, entry.first, + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Service.Attributes", "Enabled", + dbus::utility::DbusVariantType{protocolEnabled}); } + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -377,22 +370,21 @@ inline void "xyz.openbmc_project.Time.Synchronization", "TimeSyncMethod", [asyncResp](const boost::system::error_code errorCode, const std::string& timeSyncMethod) { - if (errorCode) - { - return; - } + if (errorCode) + { + return; + } - if (timeSyncMethod == - "xyz.openbmc_project.Time.Synchronization.Method.NTP") - { - asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true; - } - else if (timeSyncMethod == - "xyz.openbmc_project.Time.Synchronization." - "Method.Manual") - { - asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false; - } + if (timeSyncMethod == + "xyz.openbmc_project.Time.Synchronization.Method.NTP") + { + asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = true; + } + else if (timeSyncMethod == "xyz.openbmc_project.Time.Synchronization." + "Method.Manual") + { + asyncResp->res.jsonValue["NTP"]["ProtocolEnabled"] = false; + } }); } @@ -400,22 +392,20 @@ inline void requestRoutesNetworkProtocol(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/") .privileges(redfish::privileges::patchManagerNetworkProtocol) - .methods( - boost::beast::http::verb::patch)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<std::string> newHostName; - std::optional<std::vector<std::string>> ntpServers; - std::optional<bool> ntpEnabled; - std::optional<bool> ipmiEnabled; - std::optional<bool> sshEnabled; + .methods(boost::beast::http::verb::patch)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<std::string> newHostName; + std::optional<std::vector<std::string>> ntpServers; + std::optional<bool> ntpEnabled; + std::optional<bool> ipmiEnabled; + std::optional<bool> sshEnabled; - // clang-format off + // clang-format off if (!json_util::readJsonPatch( req, asyncResp->res, "HostName", newHostName, @@ -426,38 +416,38 @@ inline void requestRoutesNetworkProtocol(App& app) { return; } - // clang-format on + // clang-format on - asyncResp->res.result(boost::beast::http::status::no_content); - if (newHostName) - { - messages::propertyNotWritable(asyncResp->res, "HostName"); - return; - } + asyncResp->res.result(boost::beast::http::status::no_content); + if (newHostName) + { + messages::propertyNotWritable(asyncResp->res, "HostName"); + return; + } - if (ntpEnabled) - { - handleNTPProtocolEnabled(*ntpEnabled, asyncResp); - } - if (ntpServers) - { - stl_utils::removeDuplicate(*ntpServers); - handleNTPServersPatch(asyncResp, *ntpServers); - } + if (ntpEnabled) + { + handleNTPProtocolEnabled(*ntpEnabled, asyncResp); + } + if (ntpServers) + { + stl_utils::removeDuplicate(*ntpServers); + handleNTPServersPatch(asyncResp, *ntpServers); + } - if (ipmiEnabled) - { - handleProtocolEnabled( - *ipmiEnabled, asyncResp, - "/xyz/openbmc_project/control/service/phosphor_2dipmi_2dnet_40"); - } + if (ipmiEnabled) + { + handleProtocolEnabled( + *ipmiEnabled, asyncResp, + "/xyz/openbmc_project/control/service/phosphor_2dipmi_2dnet_40"); + } - if (sshEnabled) - { - handleProtocolEnabled( - *sshEnabled, asyncResp, - "/xyz/openbmc_project/control/service/dropbear"); - } + if (sshEnabled) + { + handleProtocolEnabled( + *sshEnabled, asyncResp, + "/xyz/openbmc_project/control/service/dropbear"); + } }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/") @@ -465,12 +455,12 @@ inline void requestRoutesNetworkProtocol(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->res)) - { - return; - } - getNetworkData(asyncResp, req); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + getNetworkData(asyncResp, req); + }); } } // namespace redfish diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp index 740e393bf4..df01afd820 100644 --- a/redfish-core/lib/pcie.hpp +++ b/redfish-core/lib/pcie.hpp @@ -38,36 +38,35 @@ static inline void [asyncResp, name](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreePathsResponse& pcieDevicePaths) { - if (ec) + if (ec) + { + BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " + << ec.message(); + // Not an error, system just doesn't have PCIe info + return; + } + nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; + pcieDeviceList = nlohmann::json::array(); + for (const std::string& pcieDevicePath : pcieDevicePaths) + { + size_t devStart = pcieDevicePath.rfind('/'); + if (devStart == std::string::npos) { - BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: " - << ec.message(); - // Not an error, system just doesn't have PCIe info - return; + continue; } - nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name]; - pcieDeviceList = nlohmann::json::array(); - for (const std::string& pcieDevicePath : pcieDevicePaths) - { - size_t devStart = pcieDevicePath.rfind('/'); - if (devStart == std::string::npos) - { - continue; - } - std::string devName = pcieDevicePath.substr(devStart + 1); - if (devName.empty()) - { - continue; - } - nlohmann::json::object_t pcieDevice; - pcieDevice["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + devName; - pcieDeviceList.push_back(std::move(pcieDevice)); + std::string devName = pcieDevicePath.substr(devStart + 1); + if (devName.empty()) + { + continue; } - asyncResp->res.jsonValue[name + "@odata.count"] = - pcieDeviceList.size(); - }; + nlohmann::json::object_t pcieDevice; + pcieDevice["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + devName; + pcieDeviceList.push_back(std::move(pcieDevice)); + } + asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size(); + }; crow::connections::systemBus->async_method_call( std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -85,22 +84,21 @@ inline void requestRoutesSystemPCIeDeviceCollection(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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#PCIeDeviceCollection.PCIeDeviceCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices"; - asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; - asyncResp->res.jsonValue["Description"] = - "Collection of PCIe Devices"; - asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); - asyncResp->res.jsonValue["Members@odata.count"] = 0; - getPCIeDeviceList(asyncResp, "Members"); - }); + asyncResp->res.jsonValue["@odata.type"] = + "#PCIeDeviceCollection.PCIeDeviceCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices"; + asyncResp->res.jsonValue["Name"] = "PCIe Device Collection"; + asyncResp->res.jsonValue["Description"] = "Collection of PCIe Devices"; + asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); + asyncResp->res.jsonValue["Members@odata.count"] = 0; + getPCIeDeviceList(asyncResp, "Members"); + }); } inline std::optional<std::string> @@ -146,102 +144,97 @@ inline void requestRoutesSystemPCIeDevice(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/") .privileges(redfish::privileges::getPCIeDevice) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& device) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& device) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + auto getPCIeDeviceCallback = + [asyncResp, device]( + const boost::system::error_code ec, + const dbus::utility::DBusPropertiesMap& pcieDevProperties) { + if (ec) { + BMCWEB_LOG_DEBUG + << "failed to get PCIe Device properties ec: " << ec.value() + << ": " << ec.message(); + if (ec.value() == + boost::system::linux_error::bad_request_descriptor) + { + messages::resourceNotFound(asyncResp->res, "PCIeDevice", + device); + } + else + { + messages::internalError(asyncResp->res); + } return; } - auto getPCIeDeviceCallback = - [asyncResp, device]( - const boost::system::error_code ec, - const dbus::utility::DBusPropertiesMap& pcieDevProperties) { - if (ec) + + asyncResp->res.jsonValue["@odata.type"] = + "#PCIeDevice.v1_4_0.PCIeDevice"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + device; + asyncResp->res.jsonValue["Name"] = "PCIe Device"; + asyncResp->res.jsonValue["Id"] = device; + + asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + device + + "/PCIeFunctions"; + for (const auto& property : pcieDevProperties) + { + const std::string* propertyString = + std::get_if<std::string>(&property.second); + if (property.first == "Manufacturer") + { + if (propertyString == nullptr) { - BMCWEB_LOG_DEBUG - << "failed to get PCIe Device properties ec: " - << ec.value() << ": " << ec.message(); - if (ec.value() == - boost::system::linux_error::bad_request_descriptor) - { - messages::resourceNotFound(asyncResp->res, - "PCIeDevice", device); - } - else - { - messages::internalError(asyncResp->res); - } + messages::internalError(asyncResp->res); return; } - - asyncResp->res.jsonValue["@odata.type"] = - "#PCIeDevice.v1_4_0.PCIeDevice"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + device; - asyncResp->res.jsonValue["Name"] = "PCIe Device"; - asyncResp->res.jsonValue["Id"] = device; - - asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + device + - "/PCIeFunctions"; - for (const auto& property : pcieDevProperties) + asyncResp->res.jsonValue["Manufacturer"] = *propertyString; + } + if (property.first == "DeviceType") + { + if (propertyString == nullptr) + { + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue["DeviceType"] = *propertyString; + } + if (property.first == "GenerationInUse") + { + if (propertyString == nullptr) { - const std::string* propertyString = - std::get_if<std::string>(&property.second); - if (property.first == "Manufacturer") - { - if (propertyString == nullptr) - { - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue["Manufacturer"] = - *propertyString; - } - if (property.first == "DeviceType") - { - if (propertyString == nullptr) - { - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue["DeviceType"] = - *propertyString; - } - if (property.first == "GenerationInUse") - { - if (propertyString == nullptr) - { - messages::internalError(asyncResp->res); - return; - } - std::optional<std::string> generationInUse = - redfishPcieGenerationFromDbus(*propertyString); - if (!generationInUse) - { - messages::internalError(asyncResp->res); - return; - } - if (generationInUse->empty()) - { - // unknown, no need to handle - return; - } - asyncResp->res - .jsonValue["PCIeInterface"]["PCIeType"] = - *generationInUse; - } + messages::internalError(asyncResp->res); + return; + } + std::optional<std::string> generationInUse = + redfishPcieGenerationFromDbus(*propertyString); + if (!generationInUse) + { + messages::internalError(asyncResp->res); + return; + } + if (generationInUse->empty()) + { + // unknown, no need to handle + return; } - }; - std::string escapedPath = std::string(pciePath) + "/" + device; - dbus::utility::escapePathForDbus(escapedPath); - crow::connections::systemBus->async_method_call( - std::move(getPCIeDeviceCallback), pcieService, escapedPath, - "org.freedesktop.DBus.Properties", "GetAll", - pcieDeviceInterface); + asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] = + *generationInUse; + } + } + }; + std::string escapedPath = std::string(pciePath) + "/" + device; + dbus::utility::escapePathForDbus(escapedPath); + crow::connections::systemBus->async_method_call( + std::move(getPCIeDeviceCallback), pcieService, escapedPath, + "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface); }); } @@ -253,87 +246,83 @@ inline void requestRoutesSystemPCIeFunctionCollection(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/") .privileges(redfish::privileges::getPCIeFunctionCollection) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& device) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& device) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + + asyncResp->res.jsonValue["@odata.type"] = + "#PCIeFunctionCollection.PCIeFunctionCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + device + + "/PCIeFunctions"; + asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; + asyncResp->res.jsonValue["Description"] = + "Collection of PCIe Functions for PCIe Device " + device; + + auto getPCIeDeviceCallback = + [asyncResp, device]( + const boost::system::error_code ec, + const dbus::utility::DBusPropertiesMap& pcieDevProperties) { + if (ec) { + BMCWEB_LOG_DEBUG + << "failed to get PCIe Device properties ec: " << ec.value() + << ": " << ec.message(); + if (ec.value() == + boost::system::linux_error::bad_request_descriptor) + { + messages::resourceNotFound(asyncResp->res, "PCIeDevice", + device); + } + else + { + messages::internalError(asyncResp->res); + } return; } - asyncResp->res.jsonValue["@odata.type"] = - "#PCIeFunctionCollection.PCIeFunctionCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + device + - "/PCIeFunctions"; - asyncResp->res.jsonValue["Name"] = "PCIe Function Collection"; - asyncResp->res.jsonValue["Description"] = - "Collection of PCIe Functions for PCIe Device " + device; - - auto getPCIeDeviceCallback = - [asyncResp, device]( - const boost::system::error_code ec, - const dbus::utility::DBusPropertiesMap& pcieDevProperties) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "failed to get PCIe Device properties ec: " - << ec.value() << ": " << ec.message(); - if (ec.value() == - boost::system::linux_error::bad_request_descriptor) - { - messages::resourceNotFound(asyncResp->res, - "PCIeDevice", device); - } - else - { - messages::internalError(asyncResp->res); - } - return; - } - - nlohmann::json& pcieFunctionList = - asyncResp->res.jsonValue["Members"]; - pcieFunctionList = nlohmann::json::array(); - static constexpr const int maxPciFunctionNum = 8; - for (int functionNum = 0; functionNum < maxPciFunctionNum; - functionNum++) + nlohmann::json& pcieFunctionList = + asyncResp->res.jsonValue["Members"]; + pcieFunctionList = nlohmann::json::array(); + static constexpr const int maxPciFunctionNum = 8; + for (int functionNum = 0; functionNum < maxPciFunctionNum; + functionNum++) + { + // Check if this function exists by looking for a + // device ID + std::string devIDProperty = + "Function" + std::to_string(functionNum) + "DeviceId"; + const std::string* property = nullptr; + for (const auto& propEntry : pcieDevProperties) + { + if (propEntry.first == devIDProperty) { - // Check if this function exists by looking for a - // device ID - std::string devIDProperty = - "Function" + std::to_string(functionNum) + - "DeviceId"; - const std::string* property = nullptr; - for (const auto& propEntry : pcieDevProperties) - { - if (propEntry.first == devIDProperty) - { - property = - std::get_if<std::string>(&propEntry.second); - } - } - if (property == nullptr || !property->empty()) - { - return; - } - nlohmann::json::object_t pcieFunction; - pcieFunction["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + device + - "/PCIeFunctions/" + std::to_string(functionNum); - pcieFunctionList.push_back(std::move(pcieFunction)); + property = std::get_if<std::string>(&propEntry.second); } - asyncResp->res.jsonValue["Members@odata.count"] = - pcieFunctionList.size(); - }; - std::string escapedPath = std::string(pciePath) + "/" + device; - dbus::utility::escapePathForDbus(escapedPath); - crow::connections::systemBus->async_method_call( - std::move(getPCIeDeviceCallback), pcieService, escapedPath, - "org.freedesktop.DBus.Properties", "GetAll", - pcieDeviceInterface); + } + if (property == nullptr || !property->empty()) + { + return; + } + nlohmann::json::object_t pcieFunction; + pcieFunction["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + device + + "/PCIeFunctions/" + std::to_string(functionNum); + pcieFunctionList.push_back(std::move(pcieFunction)); + } + asyncResp->res.jsonValue["Members@odata.count"] = + pcieFunctionList.size(); + }; + std::string escapedPath = std::string(pciePath) + "/" + device; + dbus::utility::escapePathForDbus(escapedPath); + crow::connections::systemBus->async_method_call( + std::move(getPCIeDeviceCallback), pcieService, escapedPath, + "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface); }); } @@ -343,124 +332,112 @@ inline void requestRoutesSystemPCIeFunction(App& app) app, "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/") .privileges(redfish::privileges::getPCIeFunction) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& device, - const std::string& function) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& device, const std::string& function) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + auto getPCIeDeviceCallback = + [asyncResp, device, function]( + const boost::system::error_code ec, + const dbus::utility::DBusPropertiesMap& pcieDevProperties) { + if (ec) { + BMCWEB_LOG_DEBUG + << "failed to get PCIe Device properties ec: " << ec.value() + << ": " << ec.message(); + if (ec.value() == + boost::system::linux_error::bad_request_descriptor) + { + messages::resourceNotFound(asyncResp->res, "PCIeDevice", + device); + } + else + { + messages::internalError(asyncResp->res); + } return; } - auto getPCIeDeviceCallback = - [asyncResp, device, function]( - const boost::system::error_code ec, - const dbus::utility::DBusPropertiesMap& pcieDevProperties) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "failed to get PCIe Device properties ec: " - << ec.value() << ": " << ec.message(); - if (ec.value() == - boost::system::linux_error::bad_request_descriptor) - { - messages::resourceNotFound(asyncResp->res, - "PCIeDevice", device); - } - else - { - messages::internalError(asyncResp->res); - } - return; - } - // Check if this function exists by looking for a device - // ID - std::string functionName = "Function" + function; - std::string devIDProperty = functionName + "DeviceId"; + // Check if this function exists by looking for a device + // ID + std::string functionName = "Function" + function; + std::string devIDProperty = functionName + "DeviceId"; - const std::string* devIdProperty = nullptr; - for (const auto& property : pcieDevProperties) - { - if (property.first == devIDProperty) - { - devIdProperty = - std::get_if<std::string>(&property.second); - continue; - } - } - if (devIdProperty == nullptr || !devIdProperty->empty()) - { - messages::resourceNotFound(asyncResp->res, - "PCIeFunction", function); - return; - } + const std::string* devIdProperty = nullptr; + for (const auto& property : pcieDevProperties) + { + if (property.first == devIDProperty) + { + devIdProperty = std::get_if<std::string>(&property.second); + continue; + } + } + if (devIdProperty == nullptr || !devIdProperty->empty()) + { + messages::resourceNotFound(asyncResp->res, "PCIeFunction", + function); + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#PCIeFunction.v1_2_0.PCIeFunction"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + device + - "/PCIeFunctions/" + function; - asyncResp->res.jsonValue["Name"] = "PCIe Function"; - asyncResp->res.jsonValue["Id"] = function; - asyncResp->res.jsonValue["FunctionId"] = - std::stoi(function); - asyncResp->res - .jsonValue["Links"]["PCIeDevice"]["@odata.id"] = - "/redfish/v1/Systems/system/PCIeDevices/" + device; + asyncResp->res.jsonValue["@odata.type"] = + "#PCIeFunction.v1_2_0.PCIeFunction"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + device + + "/PCIeFunctions/" + function; + asyncResp->res.jsonValue["Name"] = "PCIe Function"; + asyncResp->res.jsonValue["Id"] = function; + asyncResp->res.jsonValue["FunctionId"] = std::stoi(function); + asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = + "/redfish/v1/Systems/system/PCIeDevices/" + device; - for (const auto& property : pcieDevProperties) - { - const std::string* strProperty = - std::get_if<std::string>(&property.second); - if (property.first == functionName + "DeviceId") - { - asyncResp->res.jsonValue["DeviceId"] = *strProperty; - } - if (property.first == functionName + "VendorId") - { - asyncResp->res.jsonValue["VendorId"] = *strProperty; - } - if (property.first == functionName + "FunctionType") - { - asyncResp->res.jsonValue["FunctionType"] = - *strProperty; - } - if (property.first == functionName + "DeviceClass") - { - asyncResp->res.jsonValue["DeviceClass"] = - *strProperty; - } - if (property.first == functionName + "ClassCode") - { - asyncResp->res.jsonValue["ClassCode"] = - *strProperty; - } - if (property.first == functionName + "RevisionId") - { - asyncResp->res.jsonValue["RevisionId"] = - *strProperty; - } - if (property.first == functionName + "SubsystemId") - { - asyncResp->res.jsonValue["SubsystemId"] = - *strProperty; - } - if (property.first == - functionName + "SubsystemVendorId") - { - asyncResp->res.jsonValue["SubsystemVendorId"] = - *strProperty; - } - } - }; - std::string escapedPath = std::string(pciePath) + "/" + device; - dbus::utility::escapePathForDbus(escapedPath); - crow::connections::systemBus->async_method_call( - std::move(getPCIeDeviceCallback), pcieService, escapedPath, - "org.freedesktop.DBus.Properties", "GetAll", - pcieDeviceInterface); + for (const auto& property : pcieDevProperties) + { + const std::string* strProperty = + std::get_if<std::string>(&property.second); + if (property.first == functionName + "DeviceId") + { + asyncResp->res.jsonValue["DeviceId"] = *strProperty; + } + if (property.first == functionName + "VendorId") + { + asyncResp->res.jsonValue["VendorId"] = *strProperty; + } + if (property.first == functionName + "FunctionType") + { + asyncResp->res.jsonValue["FunctionType"] = *strProperty; + } + if (property.first == functionName + "DeviceClass") + { + asyncResp->res.jsonValue["DeviceClass"] = *strProperty; + } + if (property.first == functionName + "ClassCode") + { + asyncResp->res.jsonValue["ClassCode"] = *strProperty; + } + if (property.first == functionName + "RevisionId") + { + asyncResp->res.jsonValue["RevisionId"] = *strProperty; + } + if (property.first == functionName + "SubsystemId") + { + asyncResp->res.jsonValue["SubsystemId"] = *strProperty; + } + if (property.first == functionName + "SubsystemVendorId") + { + asyncResp->res.jsonValue["SubsystemVendorId"] = + *strProperty; + } + } + }; + std::string escapedPath = std::string(pciePath) + "/" + device; + dbus::utility::escapePathForDbus(escapedPath); + crow::connections::systemBus->async_method_call( + std::move(getPCIeDeviceCallback), pcieService, escapedPath, + "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface); }); } diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp index d609acb40e..7b2a47ac7a 100644 --- a/redfish-core/lib/power.hpp +++ b/redfish-core/lib/power.hpp @@ -29,9 +29,9 @@ inline void setPowerCapOverride( const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp, std::vector<nlohmann::json>& powerControlCollections) { - auto getChassisPath = [sensorsAsyncResp, powerControlCollections]( - const std::optional<std::string>& - chassisPath) mutable { + auto getChassisPath = + [sensorsAsyncResp, powerControlCollections]( + const std::optional<std::string>& chassisPath) mutable { if (!chassisPath) { BMCWEB_LOG_ERROR << "Don't find valid chassis path "; @@ -76,40 +76,38 @@ inline void setPowerCapOverride( "xyz.openbmc_project.Control.Power.Cap", "PowerCapEnable", [value, sensorsAsyncResp](const boost::system::error_code ec, bool powerCapEnable) { - if (ec) + if (ec) + { + messages::internalError(sensorsAsyncResp->asyncResp->res); + BMCWEB_LOG_ERROR << "powerCapEnable Get handler: Dbus error " + << ec; + return; + } + if (!powerCapEnable) + { + messages::actionNotSupported( + sensorsAsyncResp->asyncResp->res, + "Setting LimitInWatts when PowerLimit feature is disabled"); + BMCWEB_LOG_ERROR << "PowerLimit feature is disabled "; + return; + } + + crow::connections::systemBus->async_method_call( + [sensorsAsyncResp](const boost::system::error_code ec2) { + if (ec2) { + BMCWEB_LOG_DEBUG << "Power Limit Set: Dbus error: " << ec2; messages::internalError(sensorsAsyncResp->asyncResp->res); - BMCWEB_LOG_ERROR - << "powerCapEnable Get handler: Dbus error " << ec; - return; - } - if (!powerCapEnable) - { - messages::actionNotSupported( - sensorsAsyncResp->asyncResp->res, - "Setting LimitInWatts when PowerLimit feature is disabled"); - BMCWEB_LOG_ERROR << "PowerLimit feature is disabled "; return; } - - crow::connections::systemBus->async_method_call( - [sensorsAsyncResp](const boost::system::error_code ec2) { - if (ec2) - { - BMCWEB_LOG_DEBUG << "Power Limit Set: Dbus error: " - << ec2; - messages::internalError( - sensorsAsyncResp->asyncResp->res); - return; - } - sensorsAsyncResp->asyncResp->res.result( - boost::beast::http::status::no_content); - }, - "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/control/host0/power_cap", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.Cap", "PowerCap", - std::variant<uint32_t>(*value)); + sensorsAsyncResp->asyncResp->res.result( + boost::beast::http::status::no_content); + }, + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/power_cap", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.Cap", "PowerCap", + std::variant<uint32_t>(*value)); }); }; getValidChassisPath(sensorsAsyncResp, std::move(getChassisPath)); @@ -119,198 +117,189 @@ inline void requestRoutesPower(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/") .privileges(redfish::privileges::getPower) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& chassisName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["PowerControl"] = nlohmann::json::array(); + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& chassisName) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["PowerControl"] = nlohmann::json::array(); + + auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( + asyncResp, chassisName, sensors::dbus::powerPaths, + sensors::node::power); - auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( - asyncResp, chassisName, sensors::dbus::powerPaths, - sensors::node::power); + getChassisData(sensorAsyncResp); - getChassisData(sensorAsyncResp); + // This callback verifies that the power limit is only provided + // for the chassis that implements the Chassis inventory item. + // This prevents things like power supplies providing the + // chassis power limit - // This callback verifies that the power limit is only provided - // for the chassis that implements the Chassis inventory item. - // This prevents things like power supplies providing the - // chassis power limit + using Mapper = dbus::utility::MapperGetSubTreePathsResponse; + auto chassisHandler = + [sensorAsyncResp](const boost::system::error_code e, + const Mapper& chassisPaths) { + if (e) + { + BMCWEB_LOG_ERROR + << "Power Limit GetSubTreePaths handler Dbus error " << e; + return; + } - using Mapper = dbus::utility::MapperGetSubTreePathsResponse; - auto chassisHandler = [sensorAsyncResp]( - const boost::system::error_code e, - const Mapper& chassisPaths) { - if (e) + bool found = false; + for (const std::string& chassis : chassisPaths) + { + size_t len = std::string::npos; + size_t lastPos = chassis.rfind('/'); + if (lastPos == std::string::npos) { - BMCWEB_LOG_ERROR - << "Power Limit GetSubTreePaths handler Dbus error " - << e; - return; + continue; } - bool found = false; - for (const std::string& chassis : chassisPaths) + if (lastPos == chassis.size() - 1) { - size_t len = std::string::npos; - size_t lastPos = chassis.rfind('/'); + size_t end = lastPos; + lastPos = chassis.rfind('/', lastPos - 1); if (lastPos == std::string::npos) { continue; } - if (lastPos == chassis.size() - 1) - { - size_t end = lastPos; - lastPos = chassis.rfind('/', lastPos - 1); - if (lastPos == std::string::npos) - { - continue; - } - - len = end - (lastPos + 1); - } + len = end - (lastPos + 1); + } - std::string interfaceChassisName = - chassis.substr(lastPos + 1, len); - if (interfaceChassisName == sensorAsyncResp->chassisId) - { - found = true; - break; - } + std::string interfaceChassisName = + chassis.substr(lastPos + 1, len); + if (interfaceChassisName == sensorAsyncResp->chassisId) + { + found = true; + break; } + } - if (!found) + if (!found) + { + BMCWEB_LOG_DEBUG << "Power Limit not present for " + << sensorAsyncResp->chassisId; + return; + } + + auto valueHandler = + [sensorAsyncResp]( + const boost::system::error_code ec, + const dbus::utility::DBusPropertiesMap& properties) { + if (ec) { - BMCWEB_LOG_DEBUG << "Power Limit not present for " - << sensorAsyncResp->chassisId; + messages::internalError(sensorAsyncResp->asyncResp->res); + BMCWEB_LOG_ERROR + << "Power Limit GetAll handler: Dbus error " << ec; return; } - auto valueHandler = - [sensorAsyncResp]( - const boost::system::error_code ec, - const dbus::utility::DBusPropertiesMap& properties) { - if (ec) - { - messages::internalError( - sensorAsyncResp->asyncResp->res); - BMCWEB_LOG_ERROR - << "Power Limit GetAll handler: Dbus error " - << ec; - return; - } + nlohmann::json& tempArray = + sensorAsyncResp->asyncResp->res.jsonValue["PowerControl"]; - nlohmann::json& tempArray = - sensorAsyncResp->asyncResp->res - .jsonValue["PowerControl"]; + // Put multiple "sensors" into a single PowerControl, 0, + // so only create the first one + if (tempArray.empty()) + { + // Mandatory properties odata.id and MemberId + // 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["Name"] = "Chassis Power Control"; + powerControl["MemberId"] = "0"; + tempArray.push_back(std::move(powerControl)); + } - // Put multiple "sensors" into a single PowerControl, 0, - // so only create the first one - if (tempArray.empty()) - { - // Mandatory properties odata.id and MemberId - // 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["Name"] = "Chassis Power Control"; - powerControl["MemberId"] = "0"; - tempArray.push_back(std::move(powerControl)); - } + nlohmann::json& sensorJson = tempArray.back(); + bool enabled = false; + double powerCap = 0.0; + int64_t scale = 0; - nlohmann::json& sensorJson = tempArray.back(); - bool enabled = false; - double powerCap = 0.0; - int64_t scale = 0; + for (const std::pair<std::string, + dbus::utility::DbusVariantType>& property : + properties) + { + if (property.first == "Scale") + { + const int64_t* i = + std::get_if<int64_t>(&property.second); - for (const std::pair<std::string, - dbus::utility::DbusVariantType>& - property : properties) + if (i != nullptr) { - if (property.first == "Scale") - { - const int64_t* i = - std::get_if<int64_t>(&property.second); - - if (i != nullptr) - { - scale = *i; - } - } - else if (property.first == "PowerCap") - { - const double* d = - std::get_if<double>(&property.second); - const int64_t* i = - std::get_if<int64_t>(&property.second); - const uint32_t* u = - std::get_if<uint32_t>(&property.second); - - if (d != nullptr) - { - powerCap = *d; - } - else if (i != nullptr) - { - powerCap = static_cast<double>(*i); - } - else if (u != nullptr) - { - powerCap = *u; - } - } - else if (property.first == "PowerCapEnable") - { - const bool* b = - std::get_if<bool>(&property.second); - - if (b != nullptr) - { - enabled = *b; - } - } + scale = *i; } + } + else if (property.first == "PowerCap") + { + const double* d = std::get_if<double>(&property.second); + const int64_t* i = + std::get_if<int64_t>(&property.second); + const uint32_t* u = + std::get_if<uint32_t>(&property.second); - nlohmann::json& value = - sensorJson["PowerLimit"]["LimitInWatts"]; - - // LimitException is Mandatory attribute as per OCP - // Baseline Profile – v1.0.0, so currently making it - // "NoAction" as default value to make it OCP Compliant. - sensorJson["PowerLimit"]["LimitException"] = "NoAction"; + if (d != nullptr) + { + powerCap = *d; + } + else if (i != nullptr) + { + powerCap = static_cast<double>(*i); + } + else if (u != nullptr) + { + powerCap = *u; + } + } + else if (property.first == "PowerCapEnable") + { + const bool* b = std::get_if<bool>(&property.second); - if (enabled) + if (b != nullptr) { - // Redfish specification indicates PowerLimit should - // be null if the limit is not enabled. - value = powerCap * std::pow(10, scale); + enabled = *b; } - }; + } + } - crow::connections::systemBus->async_method_call( - std::move(valueHandler), "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/control/host0/power_cap", - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Control.Power.Cap"); + nlohmann::json& value = + sensorJson["PowerLimit"]["LimitInWatts"]; + + // LimitException is Mandatory attribute as per OCP + // Baseline Profile – v1.0.0, so currently making it + // "NoAction" as default value to make it OCP Compliant. + sensorJson["PowerLimit"]["LimitException"] = "NoAction"; + + if (enabled) + { + // Redfish specification indicates PowerLimit should + // be null if the limit is not enabled. + value = powerCap * std::pow(10, scale); + } }; crow::connections::systemBus->async_method_call( - std::move(chassisHandler), "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", - "/xyz/openbmc_project/inventory", 0, - std::array<const char*, 2>{ - "xyz.openbmc_project.Inventory.Item.Board", - "xyz.openbmc_project.Inventory.Item.Chassis"}); + std::move(valueHandler), "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/control/host0/power_cap", + "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Control.Power.Cap"); + }; + + crow::connections::systemBus->async_method_call( + std::move(chassisHandler), "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", + "/xyz/openbmc_project/inventory", 0, + std::array<const char*, 2>{ + "xyz.openbmc_project.Inventory.Item.Board", + "xyz.openbmc_project.Inventory.Item.Chassis"}); }); BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Power/") @@ -319,37 +308,36 @@ inline void requestRoutesPower(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& chassisName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( - asyncResp, chassisName, sensors::dbus::powerPaths, - sensors::node::power); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>( + asyncResp, chassisName, sensors::dbus::powerPaths, + sensors::node::power); - std::optional<std::vector<nlohmann::json>> voltageCollections; - std::optional<std::vector<nlohmann::json>> powerCtlCollections; + std::optional<std::vector<nlohmann::json>> voltageCollections; + std::optional<std::vector<nlohmann::json>> powerCtlCollections; - if (!json_util::readJsonPatch( - req, sensorAsyncResp->asyncResp->res, "PowerControl", - powerCtlCollections, "Voltages", voltageCollections)) - { - return; - } + if (!json_util::readJsonPatch(req, sensorAsyncResp->asyncResp->res, + "PowerControl", powerCtlCollections, + "Voltages", voltageCollections)) + { + return; + } - if (powerCtlCollections) - { - setPowerCapOverride(sensorAsyncResp, *powerCtlCollections); - } - if (voltageCollections) - { - std::unordered_map<std::string, std::vector<nlohmann::json>> - allCollections; - allCollections.emplace("Voltages", - *std::move(voltageCollections)); - setSensorsOverride(sensorAsyncResp, allCollections); - } - }); + if (powerCtlCollections) + { + setPowerCapOverride(sensorAsyncResp, *powerCtlCollections); + } + if (voltageCollections) + { + std::unordered_map<std::string, std::vector<nlohmann::json>> + allCollections; + allCollections.emplace("Voltages", *std::move(voltageCollections)); + setSensorsOverride(sensorAsyncResp, allCollections); + } + }); } } // namespace redfish diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp index 1b7fa9ac5f..e4dd77609e 100644 --- a/redfish-core/lib/processor.hpp +++ b/redfish-core/lib/processor.hpp @@ -56,13 +56,13 @@ inline void getProcessorUUID(std::shared_ptr<bmcweb::AsyncResp> aResp, "xyz.openbmc_project.Common.UUID", "UUID", [objPath, aResp{std::move(aResp)}](const boost::system::error_code ec, const std::string& property) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; - } - aResp->res.jsonValue["UUID"] = property; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } + aResp->res.jsonValue["UUID"] = property; }); } @@ -211,45 +211,43 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, [cpuId, service, objPath, aResp{std::move(aResp)}]( const boost::system::error_code ec, const dbus::utility::ManagedObjectType& dbusData) { - if (ec) + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } + aResp->res.jsonValue["Id"] = cpuId; + aResp->res.jsonValue["Name"] = "Processor"; + aResp->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) { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; + getCpuDataByInterface(aResp, object.second); } - aResp->res.jsonValue["Id"] = cpuId; - aResp->res.jsonValue["Name"] = "Processor"; - aResp->res.jsonValue["ProcessorType"] = "CPU"; - - bool slotPresent = false; - std::string corePath = objPath + "/core"; - size_t totalCores = 0; - for (const auto& object : dbusData) + else if (boost::starts_with(object.first.str, corePath)) { - if (object.first.str == objPath) - { - getCpuDataByInterface(aResp, object.second); - } - else if (boost::starts_with(object.first.str, corePath)) + for (const auto& interface : object.second) { - for (const auto& interface : object.second) + if (interface.first == "xyz.openbmc_project.Inventory.Item") { - if (interface.first == - "xyz.openbmc_project.Inventory.Item") + for (const auto& property : interface.second) { - for (const auto& property : interface.second) + if (property.first == "Present") { - if (property.first == "Present") + const bool* present = + std::get_if<bool>(&property.second); + if (present != nullptr) { - const bool* present = - std::get_if<bool>(&property.second); - if (present != nullptr) + if (*present) { - if (*present) - { - slotPresent = true; - totalCores++; - } + slotPresent = true; + totalCores++; } } } @@ -257,20 +255,21 @@ inline void getCpuDataByService(std::shared_ptr<bmcweb::AsyncResp> aResp, } } } - // 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) + } + // 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) + { + if (totalCores == 0) { - if (totalCores == 0) - { - // Slot is not populated, set status end return - aResp->res.jsonValue["Status"]["State"] = "Absent"; - aResp->res.jsonValue["Status"]["Health"] = "OK"; - } - aResp->res.jsonValue["TotalCores"] = totalCores; + // Slot is not populated, set status end return + aResp->res.jsonValue["Status"]["State"] = "Absent"; + aResp->res.jsonValue["Status"]["Health"] = "OK"; } - return; + aResp->res.jsonValue["TotalCores"] = totalCores; + } + return; }, service, "/xyz/openbmc_project/inventory", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -286,82 +285,80 @@ inline void getCpuAssetData(std::shared_ptr<bmcweb::AsyncResp> aResp, const boost::system::error_code ec, const boost::container::flat_map< std::string, dbus::utility::DbusVariantType>& properties) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } - for (const auto& property : properties) + for (const auto& property : properties) + { + if (property.first == "SerialNumber") { - if (property.first == "SerialNumber") + const std::string* sn = + std::get_if<std::string>(&property.second); + if (sn != nullptr && !sn->empty()) { - const std::string* sn = - std::get_if<std::string>(&property.second); - if (sn != nullptr && !sn->empty()) - { - aResp->res.jsonValue["SerialNumber"] = *sn; - } + aResp->res.jsonValue["SerialNumber"] = *sn; } - else if (property.first == "Model") + } + else if (property.first == "Model") + { + const std::string* model = + std::get_if<std::string>(&property.second); + if (model != nullptr && !model->empty()) { - const std::string* model = - std::get_if<std::string>(&property.second); - if (model != nullptr && !model->empty()) - { - aResp->res.jsonValue["Model"] = *model; - } + aResp->res.jsonValue["Model"] = *model; } - else if (property.first == "Manufacturer") + } + else if (property.first == "Manufacturer") + { + + const std::string* mfg = + std::get_if<std::string>(&property.second); + if (mfg != nullptr) { + aResp->res.jsonValue["Manufacturer"] = *mfg; - const std::string* mfg = - std::get_if<std::string>(&property.second); - if (mfg != nullptr) + // Otherwise would be unexpected. + if (mfg->find("Intel") != std::string::npos) { - aResp->res.jsonValue["Manufacturer"] = *mfg; - - // Otherwise would be unexpected. - if (mfg->find("Intel") != std::string::npos) - { - aResp->res.jsonValue["ProcessorArchitecture"] = - "x86"; - aResp->res.jsonValue["InstructionSet"] = "x86-64"; - } - else if (mfg->find("IBM") != std::string::npos) - { - aResp->res.jsonValue["ProcessorArchitecture"] = - "Power"; - aResp->res.jsonValue["InstructionSet"] = "PowerISA"; - } + aResp->res.jsonValue["ProcessorArchitecture"] = "x86"; + aResp->res.jsonValue["InstructionSet"] = "x86-64"; } - } - else if (property.first == "PartNumber") - { - const std::string* partNumber = - std::get_if<std::string>(&property.second); - - if (partNumber == nullptr) + else if (mfg->find("IBM") != std::string::npos) { - messages::internalError(aResp->res); - return; + aResp->res.jsonValue["ProcessorArchitecture"] = "Power"; + aResp->res.jsonValue["InstructionSet"] = "PowerISA"; } - aResp->res.jsonValue["PartNumber"] = *partNumber; } - else if (property.first == "SparePartNumber") + } + else if (property.first == "PartNumber") + { + const std::string* partNumber = + std::get_if<std::string>(&property.second); + + if (partNumber == nullptr) { - const std::string* sparePartNumber = - std::get_if<std::string>(&property.second); + messages::internalError(aResp->res); + return; + } + aResp->res.jsonValue["PartNumber"] = *partNumber; + } + else if (property.first == "SparePartNumber") + { + const std::string* sparePartNumber = + std::get_if<std::string>(&property.second); - if (sparePartNumber == nullptr) - { - messages::internalError(aResp->res); - return; - } - aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; + if (sparePartNumber == nullptr) + { + messages::internalError(aResp->res); + return; } + aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber; } + } }, service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); @@ -377,26 +374,26 @@ inline void getCpuRevisionData(std::shared_ptr<bmcweb::AsyncResp> aResp, const boost::system::error_code ec, const boost::container::flat_map< std::string, dbus::utility::DbusVariantType>& properties) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } - for (const auto& property : properties) + for (const auto& property : properties) + { + if (property.first == "Version") { - if (property.first == "Version") + const std::string* ver = + std::get_if<std::string>(&property.second); + if (ver != nullptr) { - const std::string* ver = - std::get_if<std::string>(&property.second); - if (ver != nullptr) - { - aResp->res.jsonValue["Version"] = *ver; - } - break; + aResp->res.jsonValue["Version"] = *ver; } + break; } + } }, service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Inventory.Decorator.Revision"); @@ -413,48 +410,48 @@ inline void getAcceleratorDataByService( const boost::system::error_code ec, const boost::container::flat_map< std::string, dbus::utility::DbusVariantType>& properties) { - if (ec) + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } + aResp->res.jsonValue["Id"] = acclrtrId; + aResp->res.jsonValue["Name"] = "Processor"; + const bool* accPresent = nullptr; + const bool* accFunctional = nullptr; + + for (const auto& property : properties) + { + if (property.first == "Functional") { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; + accFunctional = std::get_if<bool>(&property.second); } - aResp->res.jsonValue["Id"] = acclrtrId; - aResp->res.jsonValue["Name"] = "Processor"; - const bool* accPresent = nullptr; - const bool* accFunctional = nullptr; - - for (const auto& property : properties) + else if (property.first == "Present") { - if (property.first == "Functional") - { - accFunctional = std::get_if<bool>(&property.second); - } - else if (property.first == "Present") - { - accPresent = std::get_if<bool>(&property.second); - } + accPresent = std::get_if<bool>(&property.second); } + } - std::string state = "Enabled"; - std::string health = "OK"; + std::string state = "Enabled"; + std::string health = "OK"; - if (accPresent != nullptr && !*accPresent) - { - state = "Absent"; - } + if (accPresent != nullptr && !*accPresent) + { + state = "Absent"; + } - if ((accFunctional != nullptr) && !*accFunctional) + if ((accFunctional != nullptr) && !*accFunctional) + { + if (state == "Enabled") { - if (state == "Enabled") - { - health = "Critical"; - } + health = "Critical"; } + } - aResp->res.jsonValue["Status"]["State"] = state; - aResp->res.jsonValue["Status"]["Health"] = health; - aResp->res.jsonValue["ProcessorType"] = "Accelerator"; + aResp->res.jsonValue["Status"]["State"] = state; + aResp->res.jsonValue["Status"]["Health"] = health; + aResp->res.jsonValue["ProcessorType"] = "Accelerator"; }, service, objPath, "org.freedesktop.DBus.Properties", "GetAll", ""); } @@ -530,87 +527,84 @@ inline void getCpuConfigData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, const boost::system::error_code ec, const std::vector<std::pair< std::string, dbus::utility::DbusVariantType>>& properties) { - if (ec) - { - BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " - << ec.message(); - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); + messages::internalError(aResp->res); + return; + } - nlohmann::json& json = aResp->res.jsonValue; + nlohmann::json& json = aResp->res.jsonValue; - for (const auto& [dbusPropName, variantVal] : properties) + for (const auto& [dbusPropName, variantVal] : properties) + { + if (dbusPropName == "AppliedConfig") { - if (dbusPropName == "AppliedConfig") + const sdbusplus::message::object_path* dbusPathWrapper = + std::get_if<sdbusplus::message::object_path>(&variantVal); + if (dbusPathWrapper == nullptr) { - const sdbusplus::message::object_path* dbusPathWrapper = - std::get_if<sdbusplus::message::object_path>( - &variantVal); - if (dbusPathWrapper == nullptr) - { - continue; - } + continue; + } - const std::string& dbusPath = dbusPathWrapper->str; - std::string uri = "/redfish/v1/Systems/system/Processors/" + - cpuId + "/OperatingConfigs"; - nlohmann::json::object_t operatingConfig; - operatingConfig["@odata.id"] = uri; - 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)) + const std::string& dbusPath = dbusPathWrapper->str; + std::string uri = "/redfish/v1/Systems/system/Processors/" + + cpuId + "/OperatingConfigs"; + nlohmann::json::object_t operatingConfig; + operatingConfig["@odata.id"] = uri; + 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. + messages::internalError(aResp->res); + break; + } + uri += '/'; + uri += dbusPath.substr(baseNamePos + 1); + nlohmann::json::object_t appliedOperatingConfig; + appliedOperatingConfig["@odata.id"] = uri; + 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", + [aResp](const boost::system::error_code ec, + const BaseSpeedPrioritySettingsProperty& + baseSpeedList) { + if (ec) { - // If the AppliedConfig was somehow not a valid path, - // skip adding any more properties, since everything - // else is tied to this applied config. + BMCWEB_LOG_WARNING << "D-Bus Property Get error: " + << ec; messages::internalError(aResp->res); - break; + return; } - uri += '/'; - uri += dbusPath.substr(baseNamePos + 1); - nlohmann::json::object_t appliedOperatingConfig; - appliedOperatingConfig["@odata.id"] = uri; - 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", - [aResp](const boost::system::error_code ec, - const BaseSpeedPrioritySettingsProperty& - baseSpeedList) { - if (ec) - { - BMCWEB_LOG_WARNING - << "D-Bus Property Get error: " << ec; - messages::internalError(aResp->res); - return; - } - highSpeedCoreIdsHandler(aResp, baseSpeedList); - }); - } - else if (dbusPropName == "BaseSpeedPriorityEnabled") + highSpeedCoreIdsHandler(aResp, baseSpeedList); + }); + } + else if (dbusPropName == "BaseSpeedPriorityEnabled") + { + const bool* state = std::get_if<bool>(&variantVal); + if (state != nullptr) { - const bool* state = std::get_if<bool>(&variantVal); - if (state != nullptr) - { - json["BaseSpeedPriorityState"] = - *state ? "Enabled" : "Disabled"; - } + json["BaseSpeedPriorityState"] = + *state ? "Enabled" : "Disabled"; } } + } }, service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"); @@ -634,15 +628,15 @@ inline void getCpuLocationCode(std::shared_ptr<bmcweb::AsyncResp> aResp, "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode", [objPath, aResp{std::move(aResp)}](const boost::system::error_code ec, const std::string& property) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->res); + return; + } - aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = - property; + aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] = + property; }); } @@ -664,14 +658,14 @@ inline void getCpuUniqueId(const std::shared_ptr<bmcweb::AsyncResp>& aResp, "xyz.openbmc_project.Inventory.Decorator.UniqueIdentifier", "UniqueIdentifier", [aResp](boost::system::error_code ec, const std::string& id) { - if (ec) - { - BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec; - messages::internalError(aResp->res); - return; - } - aResp->res - .jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = id; + if (ec) + { + BMCWEB_LOG_ERROR << "Failed to read cpu unique id: " << ec; + messages::internalError(aResp->res); + return; + } + aResp->res.jsonValue["ProcessorId"]["ProtectedIdentificationNumber"] = + id; }); } @@ -697,50 +691,50 @@ inline void getProcessorObject(const std::shared_ptr<bmcweb::AsyncResp>& resp, [resp, processorId, handler = std::forward<Handler>(handler)]( boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) mutable { - if (ec) + 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 (!boost::ends_with(objectPath, processorId)) { - BMCWEB_LOG_DEBUG << "DBUS response error: " << ec; - messages::internalError(resp->res); - return; + continue; } - for (const auto& [objectPath, serviceMap] : subtree) - { - // Ignore any objects which don't end with our desired cpu name - if (!boost::ends_with(objectPath, processorId)) - { - 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) + 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::find_first_of( + interfaceList.begin(), interfaceList.end(), + processorInterfaces.begin(), + processorInterfaces.end()) != interfaceList.end()) { - if (std::find_first_of( - interfaceList.begin(), interfaceList.end(), - processorInterfaces.begin(), - processorInterfaces.end()) != interfaceList.end()) - { - found = true; - break; - } + found = true; + break; } + } - if (!found) - { - continue; - } + if (!found) + { + continue; + } - // 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. + // 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(resp, processorId, objectPath, serviceMap); - return; - } - messages::resourceNotFound(resp->res, "Processor", processorId); + handler(resp, processorId, objectPath, serviceMap); + return; + } + messages::resourceNotFound(resp->res, "Processor", processorId); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -826,99 +820,97 @@ inline void crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec, const OperatingConfigProperties& properties) { - if (ec) - { - BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " - << ec.message(); - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_WARNING << "D-Bus error: " << ec << ", " << ec.message(); + messages::internalError(aResp->res); + return; + } - nlohmann::json& json = aResp->res.jsonValue; - for (const auto& [key, variant] : properties) + nlohmann::json& json = aResp->res.jsonValue; + for (const auto& [key, variant] : properties) + { + if (key == "AvailableCoreCount") { - if (key == "AvailableCoreCount") + const size_t* cores = std::get_if<size_t>(&variant); + if (cores != nullptr) { - const size_t* cores = std::get_if<size_t>(&variant); - if (cores != nullptr) - { - json["TotalAvailableCoreCount"] = *cores; - } + json["TotalAvailableCoreCount"] = *cores; } - else if (key == "BaseSpeed") + } + else if (key == "BaseSpeed") + { + const uint32_t* speed = std::get_if<uint32_t>(&variant); + if (speed != nullptr) { - const uint32_t* speed = std::get_if<uint32_t>(&variant); - if (speed != nullptr) - { - json["BaseSpeedMHz"] = *speed; - } + json["BaseSpeedMHz"] = *speed; } - else if (key == "MaxJunctionTemperature") + } + else if (key == "MaxJunctionTemperature") + { + const uint32_t* temp = std::get_if<uint32_t>(&variant); + if (temp != nullptr) { - const uint32_t* temp = std::get_if<uint32_t>(&variant); - if (temp != nullptr) - { - json["MaxJunctionTemperatureCelsius"] = *temp; - } + json["MaxJunctionTemperatureCelsius"] = *temp; } - else if (key == "MaxSpeed") + } + else if (key == "MaxSpeed") + { + const uint32_t* speed = std::get_if<uint32_t>(&variant); + if (speed != nullptr) { - const uint32_t* speed = std::get_if<uint32_t>(&variant); - if (speed != nullptr) - { - json["MaxSpeedMHz"] = *speed; - } + json["MaxSpeedMHz"] = *speed; } - else if (key == "PowerLimit") + } + else if (key == "PowerLimit") + { + const uint32_t* tdp = std::get_if<uint32_t>(&variant); + if (tdp != nullptr) { - const uint32_t* tdp = std::get_if<uint32_t>(&variant); - if (tdp != nullptr) - { - json["TDPWatts"] = *tdp; - } + json["TDPWatts"] = *tdp; } - else if (key == "TurboProfile") + } + else if (key == "TurboProfile") + { + const auto* turboList = + std::get_if<TurboProfileProperty>(&variant); + if (turboList == nullptr) { - const auto* turboList = - std::get_if<TurboProfileProperty>(&variant); - if (turboList == nullptr) - { - continue; - } + continue; + } - nlohmann::json& turboArray = json["TurboProfile"]; - turboArray = nlohmann::json::array(); - for (const auto& [turboSpeed, coreCount] : *turboList) - { - nlohmann::json::object_t turbo; - turbo["ActiveCoreCount"] = coreCount; - turbo["MaxSpeedMHz"] = turboSpeed; - turboArray.push_back(std::move(turbo)); - } + nlohmann::json& turboArray = json["TurboProfile"]; + turboArray = nlohmann::json::array(); + for (const auto& [turboSpeed, coreCount] : *turboList) + { + nlohmann::json::object_t turbo; + turbo["ActiveCoreCount"] = coreCount; + turbo["MaxSpeedMHz"] = turboSpeed; + turboArray.push_back(std::move(turbo)); } - else if (key == "BaseSpeedPrioritySettings") + } + else if (key == "BaseSpeedPrioritySettings") + { + const auto* baseSpeedList = + std::get_if<BaseSpeedPrioritySettingsProperty>(&variant); + if (baseSpeedList == nullptr) { - const auto* baseSpeedList = - std::get_if<BaseSpeedPrioritySettingsProperty>( - &variant); - if (baseSpeedList == nullptr) - { - continue; - } + continue; + } - nlohmann::json& baseSpeedArray = - json["BaseSpeedPrioritySettings"]; - baseSpeedArray = nlohmann::json::array(); - for (const auto& [baseSpeed, coreList] : *baseSpeedList) - { - nlohmann::json::object_t speed; - speed["CoreCount"] = coreList.size(); - speed["CoreIDs"] = coreList; - speed["BaseSpeedMHz"] = baseSpeed; - baseSpeedArray.push_back(std::move(speed)); - } + nlohmann::json& baseSpeedArray = + json["BaseSpeedPrioritySettings"]; + baseSpeedArray = nlohmann::json::array(); + for (const auto& [baseSpeed, coreList] : *baseSpeedList) + { + nlohmann::json::object_t speed; + speed["CoreCount"] = coreList.size(); + speed["CoreIDs"] = coreList; + speed["BaseSpeedMHz"] = baseSpeed; + baseSpeedArray.push_back(std::move(speed)); } } + } }, service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"); @@ -1044,7 +1036,7 @@ inline void patchAppliedOperatingConfig( crow::connections::systemBus->async_method_call( [resp, appliedConfigUri](const boost::system::error_code ec, const sdbusplus::message::message& msg) { - handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); + handleAppliedConfigResponse(resp, appliedConfigUri, ec, msg); }, *controlService, cpuObjectPath, "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig", @@ -1057,63 +1049,61 @@ inline void requestRoutesOperatingConfigCollection(App& app) BMCWEB_ROUTE( app, "/redfish/v1/Systems/system/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& cpuName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& cpuName) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#OperatingConfigCollection.OperatingConfigCollection"; + asyncResp->res.jsonValue["@odata.id"] = req.url; + 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. + crow::connections::systemBus->async_method_call( + [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; } - asyncResp->res.jsonValue["@odata.type"] = - "#OperatingConfigCollection.OperatingConfigCollection"; - asyncResp->res.jsonValue["@odata.id"] = req.url; - 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. - crow::connections::systemBus->async_method_call( - [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 (!boost::ends_with(object, cpuName)) - { - continue; - } + for (const std::string& object : objects) + { + if (!boost::ends_with(object, 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. - collection_util::getCollectionMembers( - asyncResp, - "/redfish/v1/Systems/system/Processors/" + cpuName + - "/OperatingConfigs", - {"xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}, - object.c_str()); - return; - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", - "/xyz/openbmc_project/inventory", 0, - std::array<const char*, 1>{ - "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); + // 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. + collection_util::getCollectionMembers( + asyncResp, + "/redfish/v1/Systems/system/Processors/" + cpuName + + "/OperatingConfigs", + {"xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}, + object.c_str()); + return; + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", + "/xyz/openbmc_project/inventory", 0, + std::array<const char*, 1>{ + "xyz.openbmc_project.Control.Processor.CurrentOperatingConfig"}); }); } @@ -1123,63 +1113,59 @@ inline void requestRoutesOperatingConfig(App& app) app, "/redfish/v1/Systems/system/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& cpuName, - const std::string& configName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& cpuName, const std::string& configName) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + // Ask for all objects implementing OperatingConfig so we can search + // for one with a matching name + crow::connections::systemBus->async_method_call( + [asyncResp, cpuName, configName, reqUrl{req.url}]( + 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; } - // Ask for all objects implementing OperatingConfig so we can search - // for one with a matching name - crow::connections::systemBus->async_method_call( - [asyncResp, cpuName, configName, reqUrl{req.url}]( - 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 (!boost::ends_with(objectPath, expectedEnding) || - serviceMap.empty()) - { - continue; - } + const std::string expectedEnding = cpuName + '/' + configName; + for (const auto& [objectPath, serviceMap] : subtree) + { + // Ignore any configs without matching cpuX/configY + if (!boost::ends_with(objectPath, expectedEnding) || + serviceMap.empty()) + { + continue; + } - nlohmann::json& json = asyncResp->res.jsonValue; - json["@odata.type"] = - "#OperatingConfig.v1_0_0.OperatingConfig"; - json["@odata.id"] = reqUrl; - 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); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", 0, - std::array<const char*, 1>{ - "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); + nlohmann::json& json = asyncResp->res.jsonValue; + json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig"; + json["@odata.id"] = reqUrl; + 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); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", 0, + std::array<const char*, 1>{ + "xyz.openbmc_project.Inventory.Item.Cpu.OperatingConfig"}); }); } @@ -1193,22 +1179,22 @@ inline void requestRoutesProcessorCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#ProcessorCollection.ProcessorCollection"; - asyncResp->res.jsonValue["Name"] = "Processor Collection"; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#ProcessorCollection.ProcessorCollection"; + asyncResp->res.jsonValue["Name"] = "Processor Collection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Processors"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Processors"; - collection_util::getCollectionMembers( - asyncResp, "/redfish/v1/Systems/system/Processors", - std::vector<const char*>(processorInterfaces.begin(), - processorInterfaces.end())); - }); + collection_util::getCollectionMembers( + asyncResp, "/redfish/v1/Systems/system/Processors", + std::vector<const char*>(processorInterfaces.begin(), + processorInterfaces.end())); + }); } inline void requestRoutesProcessor(App& app) @@ -1223,17 +1209,17 @@ inline void requestRoutesProcessor(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& processorId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#Processor.v1_11_0.Processor"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Processors/" + processorId; + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#Processor.v1_11_0.Processor"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Processors/" + processorId; - getProcessorObject(asyncResp, processorId, getProcessorData); - }); + getProcessorObject(asyncResp, processorId, getProcessorData); + }); BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Processors/<str>/") .privileges(redfish::privileges::patchProcessor) @@ -1241,41 +1227,41 @@ inline void requestRoutesProcessor(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& processorId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<nlohmann::json> appliedConfigJson; - if (!json_util::readJsonPatch(req, asyncResp->res, - "AppliedOperatingConfig", - appliedConfigJson)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<nlohmann::json> appliedConfigJson; + if (!json_util::readJsonPatch(req, asyncResp->res, + "AppliedOperatingConfig", + appliedConfigJson)) + { + return; + } - std::string appliedConfigUri; - if (appliedConfigJson) - { - if (!json_util::readJson(*appliedConfigJson, asyncResp->res, - "@odata.id", appliedConfigUri)) - { - return; - } - // Check for 404 and find matching D-Bus object, then run - // property patch handlers if that all succeeds. - getProcessorObject( - asyncResp, processorId, - [appliedConfigUri = std::move(appliedConfigUri)]( - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& processorId, - const std::string& objectPath, - const dbus::utility::MapperServiceMap& serviceMap) { - patchAppliedOperatingConfig(asyncResp, processorId, - appliedConfigUri, - objectPath, serviceMap); - }); - } - }); + std::string appliedConfigUri; + if (appliedConfigJson) + { + if (!json_util::readJson(*appliedConfigJson, asyncResp->res, + "@odata.id", appliedConfigUri)) + { + return; + } + // Check for 404 and find matching D-Bus object, then run + // property patch handlers if that all succeeds. + getProcessorObject( + asyncResp, processorId, + [appliedConfigUri = std::move(appliedConfigUri)]( + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& processorId, + const std::string& objectPath, + const dbus::utility::MapperServiceMap& serviceMap) { + patchAppliedOperatingConfig(asyncResp, processorId, + appliedConfigUri, objectPath, + serviceMap); + }); + } + }); } } // namespace redfish diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp index 7af4ab88af..e050594afa 100644 --- a/redfish-core/lib/redfish_util.hpp +++ b/redfish-core/lib/redfish_util.hpp @@ -57,28 +57,28 @@ void getMainChassisId(std::shared_ptr<bmcweb::AsyncResp> asyncResp, [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; - } - - 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); + 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); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -97,71 +97,69 @@ void getPortStatusAndPath(const std::string& serviceName, [serviceName, callback{std::forward<CallbackFunc>(callback)}]( const boost::system::error_code ec, const std::vector<UnitStruct>& r) { - if (ec) + if (ec) + { + BMCWEB_LOG_ERROR << ec; + // return error code + callback(ec, "", false); + return; + } + + 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) { - BMCWEB_LOG_ERROR << ec; - // return error code - callback(ec, "", false); - return; + continue; } - for (const UnitStruct& unit : r) + // is unitsName end with ".socket" + std::string unitNameEnd = unitName.substr(lastCharPos); + if (unitNameEnd != ".socket") { - // 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) - { - continue; - } - - // is unitsName end with ".socket" - std::string unitNameEnd = unitName.substr(lastCharPos); - if (unitNameEnd != ".socket") - { - continue; - } - - // 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); - - // We are interested in services, which starts with - // mapped service name - if (unitNameStr != serviceName) - { - 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")); - // We found service, return from inner loop. - callback(ec, socketPath, isProtocolEnabled); - return; + continue; } - // no service foudn, throw error - boost::system::error_code ec1 = - boost::system::errc::make_error_code( - boost::system::errc::no_such_process); - // return error code - callback(ec1, "", false); - BMCWEB_LOG_ERROR << ec1; + // 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); + + // We are interested in services, which starts with + // mapped service name + if (unitNameStr != serviceName) + { + 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")); + // We found service, return from inner loop. + callback(ec, socketPath, isProtocolEnabled); + return; + } + + // no service foudn, throw error + boost::system::error_code ec1 = boost::system::errc::make_error_code( + boost::system::errc::no_such_process); + // return error code + callback(ec1, "", false); + BMCWEB_LOG_ERROR << ec1; }, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "ListUnits"); @@ -177,45 +175,45 @@ 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()) + 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) { - // 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; + ec3 = boost::system::errc::make_error_code( + boost::system::errc::result_out_of_range); } - callback(ec, port); + // return error code + callback(ec3, 0); + BMCWEB_LOG_ERROR << ec3; + } + callback(ec, port); }); } diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp index 6f27b8e10c..67e54670b0 100644 --- a/redfish-core/lib/roles.hpp +++ b/redfish-core/lib/roles.hpp @@ -81,31 +81,29 @@ 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->res)) - { - return; - } - nlohmann::json privArray = nlohmann::json::array(); - if (!getAssignedPrivFromRole(roleId, privArray)) - { - messages::resourceNotFound(asyncResp->res, "Role", roleId); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + nlohmann::json privArray = nlohmann::json::array(); + if (!getAssignedPrivFromRole(roleId, privArray)) + { + messages::resourceNotFound(asyncResp->res, "Role", roleId); - return; - } + 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"] = - "/redfish/v1/AccountService/Roles/" + roleId; - asyncResp->res.jsonValue["AssignedPrivileges"] = - std::move(privArray); - }); + 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"] = + "/redfish/v1/AccountService/Roles/" + roleId; + asyncResp->res.jsonValue["AssignedPrivileges"] = std::move(privArray); + }); } inline void requestRoutesRoleCollection(App& app) @@ -115,48 +113,46 @@ 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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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"; + 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"] = - "/redfish/v1/AccountService/Roles/" + role; - memberArray.push_back(std::move(member)); - } - } - asyncResp->res.jsonValue["Members@odata.count"] = - memberArray.size(); - }); + 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"] = + "/redfish/v1/AccountService/Roles/" + role; + memberArray.push_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 c7676db0a7..4c93b140b5 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -349,11 +349,10 @@ void getObjectsWithConnection( "xyz.openbmc_project.Sensor.Value"}; // Response handler for parsing objects subtree - auto respHandler = [callback{std::forward<Callback>(callback)}, - sensorsAsyncResp, sensorNames]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& - subtree) { + auto respHandler = + [callback{std::forward<Callback>(callback)}, sensorsAsyncResp, + sensorNames](const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { BMCWEB_LOG_DEBUG << "getObjectsWithConnection resp_handler enter"; if (ec) { @@ -544,11 +543,10 @@ void getChassis(const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp, const std::array<const char*, 2> interfaces = { "xyz.openbmc_project.Inventory.Item.Board", "xyz.openbmc_project.Inventory.Item.Chassis"}; - auto respHandler = [callback{std::forward<Callback>(callback)}, - sensorsAsyncResp]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreePathsResponse& - chassisPaths) { + auto respHandler = + [callback{std::forward<Callback>(callback)}, sensorsAsyncResp]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreePathsResponse& chassisPaths) { BMCWEB_LOG_DEBUG << "getChassis respHandler enter"; if (ec) { @@ -626,21 +624,20 @@ void getChassis(const std::shared_ptr<SensorsAsyncResp>& sensorsAsyncResp, callback{std::forward<const Callback>(callback)}]( const boost::system::error_code& e, const std::vector<std::string>& nodeSensorList) { - if (e) + if (e) + { + if (e.value() != EBADR) { - if (e.value() != EBADR) - { - messages::internalError( - sensorsAsyncResp->asyncResp->res); - return; - } + messages::internalError(sensorsAsyncResp->asyncResp->res); + return; } - const std::shared_ptr<boost::container::flat_set<std::string>> - culledSensorList = std::make_shared< - boost::container::flat_set<std::string>>(); - reduceSensorList(sensorsAsyncResp, &nodeSensorList, - culledSensorList); - callback(culledSensorList); + } + const std::shared_ptr<boost::container::flat_set<std::string>> + culledSensorList = + std::make_shared<boost::container::flat_set<std::string>>(); + reduceSensorList(sensorsAsyncResp, &nodeSensorList, + culledSensorList); + callback(culledSensorList); }); }; @@ -680,11 +677,10 @@ void getObjectManagerPaths( "org.freedesktop.DBus.ObjectManager"}; // Response handler for GetSubTree DBus method - auto respHandler = [callback{std::forward<Callback>(callback)}, - sensorsAsyncResp]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& - subtree) { + auto respHandler = + [callback{std::forward<Callback>(callback)}, sensorsAsyncResp]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { BMCWEB_LOG_DEBUG << "getObjectManagerPaths respHandler enter"; if (ec) { @@ -1147,193 +1143,177 @@ inline void populateFanRedundancy( [sensorsAsyncResp]( const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& resp) { - if (ec) + if (ec) + { + return; // don't have to have this interface + } + for (const std::pair< + std::string, + std::vector<std::pair<std::string, std::vector<std::string>>>>& + pathPair : resp) + { + const std::string& path = pathPair.first; + const std::vector<std::pair<std::string, std::vector<std::string>>>& + objDict = pathPair.second; + if (objDict.empty()) { - return; // don't have to have this interface + continue; // this should be impossible } - for (const std::pair<std::string, - std::vector<std::pair< - std::string, std::vector<std::string>>>>& - pathPair : resp) - { - const std::string& path = pathPair.first; - const std::vector< - std::pair<std::string, std::vector<std::string>>>& objDict = - pathPair.second; - if (objDict.empty()) + + const std::string& owner = objDict.begin()->first; + sdbusplus::asio::getProperty<std::vector<std::string>>( + *crow::connections::systemBus, + "xyz.openbmc_project.ObjectMapper", path + "/chassis", + "xyz.openbmc_project.Association", "endpoints", + [path, owner, + sensorsAsyncResp](const boost::system::error_code e, + const std::vector<std::string>& endpoints) { + if (e) + { + return; // if they don't have an association we + // can't tell what chassis is + } + auto found = + std::find_if(endpoints.begin(), endpoints.end(), + [sensorsAsyncResp](const std::string& entry) { + return entry.find(sensorsAsyncResp->chassisId) != + std::string::npos; + }); + + if (found == endpoints.end()) { - continue; // this should be impossible + return; } + crow::connections::systemBus->async_method_call( + [path, sensorsAsyncResp]( + const boost::system::error_code& err, + const boost::container::flat_map< + std::string, dbus::utility::DbusVariantType>& ret) { + if (err) + { + return; // don't have to have this + // interface + } + auto findFailures = ret.find("AllowedFailures"); + auto findCollection = ret.find("Collection"); + auto findStatus = ret.find("Status"); + + if (findFailures == ret.end() || + findCollection == ret.end() || findStatus == ret.end()) + { + BMCWEB_LOG_ERROR << "Invalid redundancy interface"; + messages::internalError( + sensorsAsyncResp->asyncResp->res); + return; + } + + const uint8_t* allowedFailures = + std::get_if<uint8_t>(&(findFailures->second)); + const std::vector<std::string>* collection = + std::get_if<std::vector<std::string>>( + &(findCollection->second)); + const std::string* status = + std::get_if<std::string>(&(findStatus->second)); + + if (allowedFailures == nullptr || collection == nullptr || + status == nullptr) + { + + BMCWEB_LOG_ERROR + << "Invalid redundancy interface types"; + 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::replace(name.begin(), name.end(), '_', ' '); + + std::string health; - const std::string& owner = objDict.begin()->first; - sdbusplus::asio::getProperty<std::vector<std::string>>( - *crow::connections::systemBus, - "xyz.openbmc_project.ObjectMapper", path + "/chassis", - "xyz.openbmc_project.Association", "endpoints", - [path, owner, sensorsAsyncResp]( - const boost::system::error_code e, - const std::vector<std::string>& endpoints) { - if (e) + if (boost::ends_with(*status, "Full")) + { + health = "OK"; + } + else if (boost::ends_with(*status, "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 path(item); + std::string itemName = path.filename(); + if (itemName.empty()) { - return; // if they don't have an association we - // can't tell what chassis is + continue; } - auto found = std::find_if( - endpoints.begin(), endpoints.end(), - [sensorsAsyncResp](const std::string& entry) { - return entry.find( - sensorsAsyncResp->chassisId) != - std::string::npos; + /* + todo(ed): merge patch that fixes the names + std::replace(itemName.begin(), + itemName.end(), '_', ' ');*/ + auto schemaItem = + std::find_if(fanRedfish.begin(), fanRedfish.end(), + [itemName](const nlohmann::json& fan) { + return fan["MemberId"] == itemName; }); - - if (found == endpoints.end()) + if (schemaItem != fanRedfish.end()) + { + nlohmann::json::object_t collection; + collection["@odata.id"] = + (*schemaItem)["@odata.id"]; + redfishCollection.emplace_back( + std::move(collection)); + } + else { + BMCWEB_LOG_ERROR << "failed to find fan in schema"; + messages::internalError( + sensorsAsyncResp->asyncResp->res); return; } - crow::connections::systemBus->async_method_call( - [path, sensorsAsyncResp]( - const boost::system::error_code& err, - const boost::container::flat_map< - std::string, - dbus::utility::DbusVariantType>& ret) { - if (err) - { - return; // don't have to have this - // interface - } - auto findFailures = ret.find("AllowedFailures"); - auto findCollection = ret.find("Collection"); - auto findStatus = ret.find("Status"); - - if (findFailures == ret.end() || - findCollection == ret.end() || - findStatus == ret.end()) - { - BMCWEB_LOG_ERROR - << "Invalid redundancy interface"; - messages::internalError( - sensorsAsyncResp->asyncResp->res); - return; - } - - const uint8_t* allowedFailures = - std::get_if<uint8_t>( - &(findFailures->second)); - const std::vector<std::string>* collection = - std::get_if<std::vector<std::string>>( - &(findCollection->second)); - const std::string* status = - std::get_if<std::string>( - &(findStatus->second)); - - if (allowedFailures == nullptr || - collection == nullptr || status == nullptr) - { - - BMCWEB_LOG_ERROR - << "Invalid redundancy interface types"; - 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::replace(name.begin(), name.end(), '_', - ' '); - - std::string health; + } - if (boost::ends_with(*status, "Full")) - { - health = "OK"; - } - else if (boost::ends_with(*status, "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 path(item); - std::string itemName = path.filename(); - if (itemName.empty()) - { - continue; - } - /* - todo(ed): merge patch that fixes the names - std::replace(itemName.begin(), - itemName.end(), '_', ' ');*/ - auto schemaItem = std::find_if( - fanRedfish.begin(), fanRedfish.end(), - [itemName](const nlohmann::json& fan) { - return fan["MemberId"] == itemName; - }); - if (schemaItem != fanRedfish.end()) - { - nlohmann::json::object_t collection; - collection["@odata.id"] = - (*schemaItem)["@odata.id"]; - redfishCollection.emplace_back( - std::move(collection)); - } - 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"]; - size_t minNumNeeded = - collection->empty() - ? 0 - : collection->size() - *allowedFailures; - nlohmann::json& jResp = - sensorsAsyncResp->asyncResp->res - .jsonValue["Redundancy"]; - - nlohmann::json::object_t redundancy; - redundancy["@odata.id"] = - "/redfish/v1/Chassis/" + - sensorsAsyncResp->chassisId + "/" + - sensorsAsyncResp->chassisSubNode + - "#/Redundancy/" + - std::to_string(jResp.size()); - redundancy["@odata.type"] = - "#Redundancy.v1_3_2.Redundancy"; - redundancy["MinNumNeeded"] = minNumNeeded; - redundancy["MemberId"] = name; - redundancy["Mode"] = "N+m"; - redundancy["Name"] = name; - redundancy["RedundancySet"] = redfishCollection; - redundancy["Status"]["Health"] = health; - redundancy["Status"]["State"] = "Enabled"; - - jResp.push_back(std::move(redundancy)); - }, - owner, path, "org.freedesktop.DBus.Properties", - "GetAll", - "xyz.openbmc_project.Control.FanRedundancy"); - }); - } + nlohmann::json::object_t redundancy; + redundancy["@odata.id"] = + "/redfish/v1/Chassis/" + sensorsAsyncResp->chassisId + + "/" + sensorsAsyncResp->chassisSubNode + + "#/Redundancy/" + std::to_string(jResp.size()); + redundancy["@odata.type"] = "#Redundancy.v1_3_2.Redundancy"; + redundancy["MinNumNeeded"] = minNumNeeded; + redundancy["MemberId"] = name; + redundancy["Mode"] = "N+m"; + redundancy["Name"] = name; + redundancy["RedundancySet"] = redfishCollection; + redundancy["Status"]["Health"] = health; + redundancy["Status"]["State"] = "Enabled"; + + jResp.push_back(std::move(redundancy)); + }, + owner, path, "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Control.FanRedundancy"); + }); + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1359,8 +1339,8 @@ inline void { std::sort(entry->begin(), entry->end(), [](nlohmann::json& c1, nlohmann::json& c2) { - return c1["Name"] < c2["Name"]; - }); + return c1["Name"] < c2["Name"]; + }); // add the index counts to the end of each entry size_t count = 0; @@ -1637,12 +1617,11 @@ static void getInventoryItemsData( const std::string& invConnection = *it; // Response handler for GetManagedObjects - auto respHandler = [sensorsAsyncResp, inventoryItems, invConnections, - objectMgrPaths, - callback{std::forward<Callback>(callback)}, - invConnectionsIndex]( - const boost::system::error_code ec, - dbus::utility::ManagedObjectType& resp) { + auto respHandler = + [sensorsAsyncResp, inventoryItems, invConnections, objectMgrPaths, + callback{std::forward<Callback>(callback)}, + invConnectionsIndex](const boost::system::error_code ec, + dbus::utility::ManagedObjectType& resp) { BMCWEB_LOG_DEBUG << "getInventoryItemsData respHandler enter"; if (ec) { @@ -1728,11 +1707,11 @@ static void getInventoryItemsConnections( "xyz.openbmc_project.State.Decorator.OperationalStatus"}; // Response handler for parsing output from GetSubTree - auto respHandler = [callback{std::forward<Callback>(callback)}, - sensorsAsyncResp, inventoryItems]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& - subtree) { + auto respHandler = + [callback{std::forward<Callback>(callback)}, sensorsAsyncResp, + inventoryItems]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { BMCWEB_LOG_DEBUG << "getInventoryItemsConnections respHandler enter"; if (ec) { @@ -1997,47 +1976,47 @@ void getInventoryLedData( [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_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 (boost::ends_with(state, "On")) { - BMCWEB_LOG_ERROR - << "getInventoryLedData respHandler DBus error " << ec; - messages::internalError(sensorsAsyncResp->asyncResp->res); - return; + inventoryItem->ledState = LedState::ON; } - - BMCWEB_LOG_DEBUG << "Led state: " << state; - // Find inventory item with this LED object path - InventoryItem* inventoryItem = - findInventoryItemForLed(*inventoryItems, ledPath); - if (inventoryItem != nullptr) + else if (boost::ends_with(state, "Blink")) { - // Store LED state in InventoryItem - if (boost::ends_with(state, "On")) - { - inventoryItem->ledState = LedState::ON; - } - else if (boost::ends_with(state, "Blink")) - { - inventoryItem->ledState = LedState::BLINK; - } - else if (boost::ends_with(state, "Off")) - { - inventoryItem->ledState = LedState::OFF; - } - else - { - inventoryItem->ledState = LedState::UNKNOWN; - } + inventoryItem->ledState = LedState::BLINK; + } + else if (boost::ends_with(state, "Off")) + { + inventoryItem->ledState = LedState::OFF; } + else + { + inventoryItem->ledState = 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>( @@ -2084,11 +2063,11 @@ void getInventoryLeds( "xyz.openbmc_project.Led.Physical"}; // Response handler for parsing output from GetSubTree - auto respHandler = [callback{std::forward<Callback>(callback)}, - sensorsAsyncResp, inventoryItems]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& - subtree) { + auto respHandler = + [callback{std::forward<Callback>(callback)}, sensorsAsyncResp, + inventoryItems]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { BMCWEB_LOG_DEBUG << "getInventoryLeds respHandler enter"; if (ec) { @@ -2182,10 +2161,10 @@ void getPowerSupplyAttributesData( const std::string& psAttributesConnection = (*it).second; // Response handler for Get DeratingFactor property - auto respHandler = [sensorsAsyncResp, inventoryItems, - callback{std::forward<Callback>(callback)}]( - const boost::system::error_code ec, - const uint32_t value) { + auto respHandler = + [sensorsAsyncResp, inventoryItems, + callback{std::forward<Callback>(callback)}]( + const boost::system::error_code ec, const uint32_t value) { BMCWEB_LOG_DEBUG << "getPowerSupplyAttributesData respHandler enter"; if (ec) { @@ -2268,53 +2247,53 @@ void getPowerSupplyAttributes( inventoryItems]( const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { - 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; - } + 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. - boost::container::flat_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. + boost::container::flat_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"; + }; // Make call to ObjectMapper to find the PowerSupplyAttributes service crow::connections::systemBus->async_method_call( std::move(respHandler), "xyz.openbmc_project.ObjectMapper", @@ -2360,50 +2339,45 @@ static void getInventoryItems( [sensorsAsyncResp, objectMgrPaths, callback{std::forward<Callback>(callback)}]( std::shared_ptr<std::vector<InventoryItem>> inventoryItems) { - BMCWEB_LOG_DEBUG << "getInventoryItemAssociationsCb enter"; - auto getInventoryItemsConnectionsCb = - [sensorsAsyncResp, inventoryItems, objectMgrPaths, - callback{std::forward<const Callback>(callback)}]( - std::shared_ptr<boost::container::flat_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"; - }; - - // 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, objectMgrPaths, - std::move(getInventoryItemsDataCb)); - BMCWEB_LOG_DEBUG << "getInventoryItemsConnectionsCb exit"; + BMCWEB_LOG_DEBUG << "getInventoryItemAssociationsCb enter"; + auto getInventoryItemsConnectionsCb = + [sensorsAsyncResp, inventoryItems, objectMgrPaths, + callback{std::forward<const Callback>(callback)}]( + std::shared_ptr<boost::container::flat_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"; }; - // Get connections that provide inventory item data - getInventoryItemsConnections( - sensorsAsyncResp, inventoryItems, - std::move(getInventoryItemsConnectionsCb)); - BMCWEB_LOG_DEBUG << "getInventoryItemAssociationsCb 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, objectMgrPaths, + 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 associations from sensors to inventory items getInventoryItemAssociations(sensorsAsyncResp, sensorNames, objectMgrPaths, std::move(getInventoryItemAssociationsCb)); @@ -2507,10 +2481,10 @@ inline void getSensorData( for (const std::string& connection : connections) { // Response handler to process managed objects - auto getManagedObjectsCb = [sensorsAsyncResp, sensorNames, - inventoryItems]( - const boost::system::error_code ec, - dbus::utility::ManagedObjectType& resp) { + auto getManagedObjectsCb = + [sensorsAsyncResp, sensorNames, + inventoryItems](const boost::system::error_code ec, + dbus::utility::ManagedObjectType& resp) { BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter"; if (ec) { @@ -2712,40 +2686,37 @@ inline void processSensorList( auto getConnectionCb = [sensorsAsyncResp, sensorNames]( const boost::container::flat_set<std::string>& connections) { - BMCWEB_LOG_DEBUG << "getConnectionCb enter"; - auto getObjectManagerPathsCb = - [sensorsAsyncResp, sensorNames, - connections](const std::shared_ptr<boost::container::flat_map< - std::string, std::string>>& objectMgrPaths) { - BMCWEB_LOG_DEBUG << "getObjectManagerPathsCb enter"; - auto getInventoryItemsCb = - [sensorsAsyncResp, sensorNames, connections, - objectMgrPaths]( - 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, objectMgrPaths, - inventoryItems); - BMCWEB_LOG_DEBUG << "getInventoryItemsCb exit"; - }; - - // Get inventory items associated with sensors - getInventoryItems(sensorsAsyncResp, sensorNames, - objectMgrPaths, - std::move(getInventoryItemsCb)); - - BMCWEB_LOG_DEBUG << "getObjectManagerPathsCb exit"; - }; + BMCWEB_LOG_DEBUG << "getConnectionCb enter"; + auto getObjectManagerPathsCb = + [sensorsAsyncResp, sensorNames, + connections](const std::shared_ptr<boost::container::flat_map< + std::string, std::string>>& objectMgrPaths) { + BMCWEB_LOG_DEBUG << "getObjectManagerPathsCb enter"; + auto getInventoryItemsCb = + [sensorsAsyncResp, sensorNames, connections, objectMgrPaths]( + 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, + objectMgrPaths, inventoryItems); + BMCWEB_LOG_DEBUG << "getInventoryItemsCb exit"; + }; + + // Get inventory items associated with sensors + getInventoryItems(sensorsAsyncResp, sensorNames, objectMgrPaths, + std::move(getInventoryItemsCb)); - // Get mapping from connection names to the DBus object - // paths that implement the ObjectManager interface - getObjectManagerPaths(sensorsAsyncResp, - std::move(getObjectManagerPathsCb)); - BMCWEB_LOG_DEBUG << "getConnectionCb exit"; + BMCWEB_LOG_DEBUG << "getObjectManagerPathsCb exit"; }; + // Get mapping from connection names to the DBus object + // paths that implement the ObjectManager interface + getObjectManagerPaths(sensorsAsyncResp, + std::move(getObjectManagerPathsCb)); + BMCWEB_LOG_DEBUG << "getConnectionCb exit"; + }; + // Get set of connections that provide sensor values getConnections(sensorsAsyncResp, sensorNames, std::move(getConnectionCb)); } @@ -2763,10 +2734,10 @@ inline void [sensorsAsyncResp]( const std::shared_ptr<boost::container::flat_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) { @@ -2855,10 +2826,10 @@ inline void setSensorsOverride( } } - auto getChassisSensorListCb = [sensorAsyncResp, overrideMap]( - const std::shared_ptr< - boost::container::flat_set< - std::string>>& sensorsList) { + auto getChassisSensorListCb = + [sensorAsyncResp, overrideMap]( + const std::shared_ptr<boost::container::flat_set<std::string>>& + sensorsList) { // Match sensor names in the PATCH request to those managed by the // chassis node const std::shared_ptr<boost::container::flat_set<std::string>> @@ -2877,12 +2848,11 @@ inline void setSensorsOverride( } } // Get the connection to which the memberId belongs - auto getObjectsWithConnectionCb = [sensorAsyncResp, overrideMap]( - const boost::container::flat_set< - std::string>& /*connections*/, - const std::set<std::pair< - std::string, std::string>>& - objectsWithConnection) { + auto getObjectsWithConnectionCb = + [sensorAsyncResp, overrideMap]( + const boost::container::flat_set<std::string>& /*connections*/, + const std::set<std::pair<std::string, std::string>>& + objectsWithConnection) { if (objectsWithConnection.size() != overrideMap.size()) { BMCWEB_LOG_INFO @@ -2917,24 +2887,24 @@ inline void setSensorsOverride( } crow::connections::systemBus->async_method_call( [sensorAsyncResp](const boost::system::error_code ec) { - if (ec) + if (ec) + { + if (ec.value() == + boost::system::errc::permission_denied) { - if (ec.value() == - boost::system::errc::permission_denied) - { - BMCWEB_LOG_WARNING - << "Manufacturing mode is not Enabled...can't " - "Override the sensor value. "; + BMCWEB_LOG_WARNING + << "Manufacturing mode is not Enabled...can't " + "Override the sensor value. "; - messages::insufficientPrivilege( - sensorAsyncResp->asyncResp->res); - return; - } - BMCWEB_LOG_DEBUG - << "setOverrideValueStatus DBUS error: " << ec; - messages::internalError( + messages::insufficientPrivilege( sensorAsyncResp->asyncResp->res); + return; } + BMCWEB_LOG_DEBUG + << "setOverrideValueStatus DBUS error: " << ec; + messages::internalError( + sensorAsyncResp->asyncResp->res); + } }, item.second, item.first, "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.Sensor.Value", "Value", @@ -3027,47 +2997,45 @@ inline void requestRoutesSensorCollection(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Sensors/") .privileges(redfish::privileges::getSensorCollection) - .methods( - boost::beast::http::verb::get)([&app]( - const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& aResp, - const std::string& chassisId) { - query_param::QueryCapabilities capabilities = { - .canDelegateExpandLevel = 1, - }; - query_param::Query delegatedQuery; - if (!redfish::setUpRedfishRouteWithDelegation( - app, req, aResp->res, delegatedQuery, capabilities)) - { - return; - } - - if (delegatedQuery.expandType != query_param::ExpandType::None) - { - // we perform efficient expand. - auto asyncResp = std::make_shared<SensorsAsyncResp>( - aResp, chassisId, sensors::dbus::sensorPaths, - sensors::node::sensors, - /*efficientExpand=*/true); - getChassisData(asyncResp); - - BMCWEB_LOG_DEBUG - << "SensorCollection doGet exit via efficient expand handler"; - return; - }; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& aResp, + const std::string& chassisId) { + query_param::QueryCapabilities capabilities = { + .canDelegateExpandLevel = 1, + }; + query_param::Query delegatedQuery; + if (!redfish::setUpRedfishRouteWithDelegation( + app, req, aResp->res, delegatedQuery, capabilities)) + { + return; + } - // if there's no efficient expand available, we use the default - // Query Parameters route + if (delegatedQuery.expandType != query_param::ExpandType::None) + { + // we perform efficient expand. auto asyncResp = std::make_shared<SensorsAsyncResp>( aResp, chassisId, sensors::dbus::sensorPaths, - sensors::node::sensors); + sensors::node::sensors, + /*efficientExpand=*/true); + getChassisData(asyncResp); - // We get all sensors as hyperlinkes in the chassis (this - // implies we reply on the default query parameters handler) - getChassis(asyncResp, - std::bind_front(sensors::getChassisCallback, asyncResp)); - BMCWEB_LOG_DEBUG << "SensorCollection doGet exit"; + BMCWEB_LOG_DEBUG + << "SensorCollection doGet exit via efficient expand handler"; + return; + }; + + // if there's no efficient expand available, we use the default + // Query Parameters route + auto asyncResp = std::make_shared<SensorsAsyncResp>( + aResp, chassisId, sensors::dbus::sensorPaths, + sensors::node::sensors); + + // We get all sensors as hyperlinkes in the chassis (this + // implies we reply on the default query parameters handler) + getChassis(asyncResp, + std::bind_front(sensors::getChassisCallback, asyncResp)); + BMCWEB_LOG_DEBUG << "SensorCollection doGet exit"; }); } @@ -3075,89 +3043,83 @@ inline void requestRoutesSensor(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Sensors/<str>/") .privileges(redfish::privileges::getSensor) - .methods( - boost::beast::http::verb::get)([&app]( - const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& aResp, - const std::string& chassisId, - const std::string& sensorName) { - if (!redfish::setUpRedfishRoute(app, req, aResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& aResp, + const std::string& chassisId, + const std::string& sensorName) { + if (!redfish::setUpRedfishRoute(app, req, aResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "Sensor doGet enter"; + std::shared_ptr<SensorsAsyncResp> asyncResp = + std::make_shared<SensorsAsyncResp>(aResp, chassisId, + std::span<std::string_view>(), + sensors::node::sensors); + + const std::array<const char*, 1> interfaces = { + "xyz.openbmc_project.Sensor.Value"}; + + // Get a list of all of the sensors that implement Sensor.Value + // and get the path and service name associated with the sensor + crow::connections::systemBus->async_method_call( + [asyncResp, sensorName]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + BMCWEB_LOG_DEBUG << "respHandler1 enter"; + if (ec) { + messages::internalError(asyncResp->asyncResp->res); + BMCWEB_LOG_ERROR << "Sensor getSensorPaths resp_handler: " + << "Dbus error " << ec; return; } - BMCWEB_LOG_DEBUG << "Sensor doGet enter"; - std::shared_ptr<SensorsAsyncResp> asyncResp = - std::make_shared<SensorsAsyncResp>( - aResp, chassisId, std::span<std::string_view>(), - sensors::node::sensors); - - const std::array<const char*, 1> interfaces = { - "xyz.openbmc_project.Sensor.Value"}; - - // Get a list of all of the sensors that implement Sensor.Value - // and get the path and service name associated with the sensor - crow::connections::systemBus->async_method_call( - [asyncResp, sensorName]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) { - BMCWEB_LOG_DEBUG << "respHandler1 enter"; - if (ec) - { - messages::internalError(asyncResp->asyncResp->res); - BMCWEB_LOG_ERROR - << "Sensor getSensorPaths resp_handler: " - << "Dbus error " << ec; - return; - } - dbus::utility::MapperGetSubTreeResponse::const_iterator it = - std::find_if( - subtree.begin(), subtree.end(), - [sensorName]( - const std::pair<std::string, - std::vector<std::pair< - std::string, - std::vector<std::string>>>>& - object) { - sdbusplus::message::object_path path( - object.first); - std::string name = path.filename(); - if (name.empty()) - { - BMCWEB_LOG_ERROR << "Invalid sensor path: " - << object.first; - return false; - } + dbus::utility::MapperGetSubTreeResponse::const_iterator it = + std::find_if( + subtree.begin(), subtree.end(), + [sensorName]( + const std::pair< + std::string, + std::vector<std::pair<std::string, + std::vector<std::string>>>>& + object) { + sdbusplus::message::object_path path(object.first); + std::string name = path.filename(); + if (name.empty()) + { + BMCWEB_LOG_ERROR << "Invalid sensor path: " << object.first; + return false; + } - return name == sensorName; - }); + return name == sensorName; + }); - if (it == subtree.end()) - { - BMCWEB_LOG_ERROR << "Could not find path for sensor: " - << sensorName; - messages::resourceNotFound(asyncResp->asyncResp->res, - "Sensor", sensorName); - return; - } - std::string_view sensorPath = (*it).first; - BMCWEB_LOG_DEBUG << "Found sensor path for sensor '" - << sensorName << "': " << sensorPath; - - const std::shared_ptr< - boost::container::flat_set<std::string>> - sensorList = std::make_shared< - boost::container::flat_set<std::string>>(); - - sensorList->emplace(sensorPath); - processSensorList(asyncResp, sensorList); - BMCWEB_LOG_DEBUG << "respHandler1 exit"; - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/sensors", 2, interfaces); + if (it == subtree.end()) + { + BMCWEB_LOG_ERROR << "Could not find path for sensor: " + << sensorName; + messages::resourceNotFound(asyncResp->asyncResp->res, "Sensor", + sensorName); + return; + } + std::string_view sensorPath = (*it).first; + BMCWEB_LOG_DEBUG << "Found sensor path for sensor '" << sensorName + << "': " << sensorPath; + + const std::shared_ptr<boost::container::flat_set<std::string>> + sensorList = + std::make_shared<boost::container::flat_set<std::string>>(); + + sensorList->emplace(sensorPath); + processSensorList(asyncResp, sensorList); + BMCWEB_LOG_DEBUG << "respHandler1 exit"; + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/sensors", 2, interfaces); }); } diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp index 7760b4c93f..eae6fd935f 100644 --- a/redfish-core/lib/service_root.hpp +++ b/redfish-core/lib/service_root.hpp @@ -93,12 +93,12 @@ inline void requestRoutesServiceRoot(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->res)) - { - return; - } - handleServiceRootGet(asyncResp); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + handleServiceRootGet(asyncResp); + }); } } // namespace redfish diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp index ab59c33cf9..998ae6072b 100644 --- a/redfish-core/lib/storage.hpp +++ b/redfish-core/lib/storage.hpp @@ -33,240 +33,224 @@ inline void requestRoutesStorageCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#StorageCollection.StorageCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Storage"; - asyncResp->res.jsonValue["Name"] = "Storage Collection"; - nlohmann::json::array_t members; - nlohmann::json::object_t member; - member["@odata.id"] = "/redfish/v1/Systems/system/Storage/1"; - members.emplace_back(member); - asyncResp->res.jsonValue["Members"] = std::move(members); - asyncResp->res.jsonValue["Members@odata.count"] = 1; - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#StorageCollection.StorageCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Storage"; + asyncResp->res.jsonValue["Name"] = "Storage Collection"; + nlohmann::json::array_t members; + nlohmann::json::object_t member; + member["@odata.id"] = "/redfish/v1/Systems/system/Storage/1"; + members.emplace_back(member); + asyncResp->res.jsonValue["Members"] = std::move(members); + asyncResp->res.jsonValue["Members@odata.count"] = 1; + }); } inline void requestRoutesStorage(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/") .privileges(redfish::privileges::getStorage) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Storage/1"; + asyncResp->res.jsonValue["Name"] = "Storage"; + asyncResp->res.jsonValue["Id"] = "1"; + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + + auto health = std::make_shared<HealthPopulate>(asyncResp); + health->populate(); + + crow::connections::systemBus->async_method_call( + [asyncResp, + health](const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreePathsResponse& + storageList) { + nlohmann::json& storageArray = asyncResp->res.jsonValue["Drives"]; + storageArray = nlohmann::json::array(); + auto& count = asyncResp->res.jsonValue["Drives@odata.count"]; + count = 0; + + if (ec) { + BMCWEB_LOG_ERROR << "Drive mapper call error"; + messages::internalError(asyncResp->res); return; } - asyncResp->res.jsonValue["@odata.type"] = "#Storage.v1_7_1.Storage"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Storage/1"; - asyncResp->res.jsonValue["Name"] = "Storage"; - asyncResp->res.jsonValue["Id"] = "1"; - asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; - auto health = std::make_shared<HealthPopulate>(asyncResp); - health->populate(); + health->inventory.insert(health->inventory.end(), + storageList.begin(), storageList.end()); + + for (const std::string& objpath : storageList) + { + std::size_t lastPos = objpath.rfind('/'); + if (lastPos == std::string::npos || + (objpath.size() <= lastPos + 1)) + { + BMCWEB_LOG_ERROR << "Failed to find '/' in " << objpath; + continue; + } + nlohmann::json::object_t storage; + storage["@odata.id"] = + "/redfish/v1/Systems/system/Storage/1/Drives/" + + objpath.substr(lastPos + 1); + storageArray.push_back(std::move(storage)); + } - crow::connections::systemBus->async_method_call( - [asyncResp, - health](const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreePathsResponse& - storageList) { - nlohmann::json& storageArray = - asyncResp->res.jsonValue["Drives"]; - storageArray = nlohmann::json::array(); - auto& count = - asyncResp->res.jsonValue["Drives@odata.count"]; - count = 0; - - if (ec) + count = storageArray.size(); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", + "/xyz/openbmc_project/inventory", int32_t(0), + std::array<const char*, 1>{ + "xyz.openbmc_project.Inventory.Item.Drive"}); + + crow::connections::systemBus->async_method_call( + [asyncResp, + health](const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec || subtree.empty()) + { + // doesn't have to be there + return; + } + + nlohmann::json& root = + asyncResp->res.jsonValue["StorageControllers"]; + root = nlohmann::json::array(); + for (const auto& [path, interfaceDict] : subtree) + { + std::size_t lastPos = path.rfind('/'); + if (lastPos == std::string::npos || + (path.size() <= lastPos + 1)) + { + BMCWEB_LOG_ERROR << "Failed to find '/' in " << path; + return; + } + + if (interfaceDict.size() != 1) + { + BMCWEB_LOG_ERROR << "Connection size " + << interfaceDict.size() + << ", greater than 1"; + messages::internalError(asyncResp->res); + return; + } + + const std::string& connectionName = interfaceDict.front().first; + + size_t index = root.size(); + nlohmann::json& storageController = + root.emplace_back(nlohmann::json::object()); + + std::string id = path.substr(lastPos + 1); + + storageController["@odata.type"] = + "#Storage.v1_7_0.StorageController"; + storageController["@odata.id"] = + "/redfish/v1/Systems/system/Storage/1#/StorageControllers/" + + std::to_string(index); + storageController["Name"] = id; + storageController["MemberId"] = id; + storageController["Status"]["State"] = "Enabled"; + + sdbusplus::asio::getProperty<bool>( + *crow::connections::systemBus, connectionName, path, + "xyz.openbmc_project.Inventory.Item", "Present", + [asyncResp, index](const boost::system::error_code ec2, + bool enabled) { + // this interface isn't necessary, only check it + // if we get a good return + if (ec2) { - BMCWEB_LOG_ERROR << "Drive mapper call error"; - messages::internalError(asyncResp->res); return; } - - health->inventory.insert(health->inventory.end(), - storageList.begin(), - storageList.end()); - - for (const std::string& objpath : storageList) + if (!enabled) { - std::size_t lastPos = objpath.rfind('/'); - if (lastPos == std::string::npos || - (objpath.size() <= lastPos + 1)) - { - BMCWEB_LOG_ERROR << "Failed to find '/' in " - << objpath; - continue; - } - nlohmann::json::object_t storage; - storage["@odata.id"] = - "/redfish/v1/Systems/system/Storage/1/Drives/" + - objpath.substr(lastPos + 1); - storageArray.push_back(std::move(storage)); + asyncResp->res.jsonValue["StorageControllers"][index] + ["Status"]["State"] = + "Disabled"; } - - count = storageArray.size(); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", - "/xyz/openbmc_project/inventory", int32_t(0), - std::array<const char*, 1>{ - "xyz.openbmc_project.Inventory.Item.Drive"}); - - crow::connections::systemBus->async_method_call( - [asyncResp, health]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec || subtree.empty()) + }); + + crow::connections::systemBus->async_method_call( + [asyncResp, + index](const boost::system::error_code ec2, + const std::vector<std::pair< + std::string, dbus::utility::DbusVariantType>>& + propertiesList) { + if (ec2) { - // doesn't have to be there + // this interface isn't necessary return; } - - nlohmann::json& root = - asyncResp->res.jsonValue["StorageControllers"]; - root = nlohmann::json::array(); - for (const auto& [path, interfaceDict] : subtree) + for (const std::pair<std::string, + dbus::utility::DbusVariantType>& + property : propertiesList) { - std::size_t lastPos = path.rfind('/'); - if (lastPos == std::string::npos || - (path.size() <= lastPos + 1)) + // Store DBus properties that are also + // Redfish properties with same name and a + // string value + const std::string& propertyName = property.first; + nlohmann::json& object = + asyncResp->res + .jsonValue["StorageControllers"][index]; + if ((propertyName == "PartNumber") || + (propertyName == "SerialNumber") || + (propertyName == "Manufacturer") || + (propertyName == "Model")) { - BMCWEB_LOG_ERROR << "Failed to find '/' in " - << path; - return; + const std::string* value = + std::get_if<std::string>(&property.second); + if (value == nullptr) + { + // illegal property + messages::internalError(asyncResp->res); + return; + } + object[propertyName] = *value; } - - if (interfaceDict.size() != 1) - { - BMCWEB_LOG_ERROR << "Connection size " - << interfaceDict.size() - << ", greater than 1"; - messages::internalError(asyncResp->res); - return; - } - - const std::string& connectionName = - interfaceDict.front().first; - - size_t index = root.size(); - nlohmann::json& storageController = - root.emplace_back(nlohmann::json::object()); - - std::string id = path.substr(lastPos + 1); - - storageController["@odata.type"] = - "#Storage.v1_7_0.StorageController"; - storageController["@odata.id"] = - "/redfish/v1/Systems/system/Storage/1#/StorageControllers/" + - std::to_string(index); - storageController["Name"] = id; - storageController["MemberId"] = id; - storageController["Status"]["State"] = "Enabled"; - - sdbusplus::asio::getProperty<bool>( - *crow::connections::systemBus, connectionName, path, - "xyz.openbmc_project.Inventory.Item", "Present", - [asyncResp, - index](const boost::system::error_code ec2, - bool enabled) { - // this interface isn't necessary, only check it - // if we get a good return - if (ec2) - { - return; - } - if (!enabled) - { - asyncResp->res - .jsonValue["StorageControllers"][index] - ["Status"]["State"] = - "Disabled"; - } - }); - - crow::connections::systemBus->async_method_call( - [asyncResp, index]( - const boost::system::error_code ec2, - const std::vector< - std::pair<std::string, - dbus::utility::DbusVariantType>>& - propertiesList) { - if (ec2) - { - // this interface isn't necessary - return; - } - for (const std::pair< - std::string, - dbus::utility::DbusVariantType>& - property : propertiesList) - { - // Store DBus properties that are also - // Redfish properties with same name and a - // string value - const std::string& propertyName = - property.first; - nlohmann::json& object = - asyncResp->res - .jsonValue["StorageControllers"] - [index]; - if ((propertyName == "PartNumber") || - (propertyName == "SerialNumber") || - (propertyName == "Manufacturer") || - (propertyName == "Model")) - { - const std::string* value = - std::get_if<std::string>( - &property.second); - if (value == nullptr) - { - // illegal property - messages::internalError( - asyncResp->res); - return; - } - object[propertyName] = *value; - } - } - }, - connectionName, path, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Inventory.Decorator.Asset"); } + }, + connectionName, path, "org.freedesktop.DBus.Properties", + "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); + } - // this is done after we know the json array will no longer - // be resized, as json::array uses vector underneath and we - // need references to its members that won't change - size_t count = 0; - // Pointer based on |asyncResp->res.jsonValue| - nlohmann::json::json_pointer rootPtr = - "/StorageControllers"_json_pointer; - for (const auto& [path, interfaceDict] : subtree) - { - auto subHealth = std::make_shared<HealthPopulate>( - asyncResp, rootPtr / count / "Status"); - subHealth->inventory.emplace_back(path); - health->inventory.emplace_back(path); - health->children.emplace_back(subHealth); - count++; - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", int32_t(0), - std::array<const char*, 1>{ - "xyz.openbmc_project.Inventory.Item.StorageController"}); + // this is done after we know the json array will no longer + // be resized, as json::array uses vector underneath and we + // need references to its members that won't change + size_t count = 0; + // Pointer based on |asyncResp->res.jsonValue| + nlohmann::json::json_pointer rootPtr = + "/StorageControllers"_json_pointer; + for (const auto& [path, interfaceDict] : subtree) + { + auto subHealth = std::make_shared<HealthPopulate>( + asyncResp, rootPtr / count / "Status"); + subHealth->inventory.emplace_back(path); + health->inventory.emplace_back(path); + health->children.emplace_back(subHealth); + count++; + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", int32_t(0), + std::array<const char*, 1>{ + "xyz.openbmc_project.Inventory.Item.StorageController"}); }); } @@ -279,34 +263,33 @@ inline void getDriveAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::vector< std::pair<std::string, dbus::utility::DbusVariantType>>& propertiesList) { - if (ec) + if (ec) + { + // this interface isn't necessary + return; + } + for (const std::pair<std::string, dbus::utility::DbusVariantType>& + property : propertiesList) + { + // Store DBus properties that are also + // Redfish properties with same name and a + // string value + const std::string& propertyName = property.first; + if ((propertyName == "PartNumber") || + (propertyName == "SerialNumber") || + (propertyName == "Manufacturer") || (propertyName == "Model")) { - // this interface isn't necessary - return; - } - for (const std::pair<std::string, dbus::utility::DbusVariantType>& - property : propertiesList) - { - // Store DBus properties that are also - // Redfish properties with same name and a - // string value - const std::string& propertyName = property.first; - if ((propertyName == "PartNumber") || - (propertyName == "SerialNumber") || - (propertyName == "Manufacturer") || - (propertyName == "Model")) + const std::string* value = + std::get_if<std::string>(&property.second); + if (value == nullptr) { - const std::string* value = - std::get_if<std::string>(&property.second); - if (value == nullptr) - { - // illegal property - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue[propertyName] = *value; + // illegal property + messages::internalError(asyncResp->res); + return; } + asyncResp->res.jsonValue[propertyName] = *value; } + } }, connectionName, path, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset"); @@ -321,17 +304,17 @@ inline void getDrivePresent(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, "xyz.openbmc_project.Inventory.Item", "Present", [asyncResp, path](const boost::system::error_code ec, const bool enabled) { - // this interface isn't necessary, only check it if - // we get a good return - if (ec) - { - return; - } - - if (!enabled) - { - asyncResp->res.jsonValue["Status"]["State"] = "Disabled"; - } + // this interface isn't necessary, only check it if + // we get a good return + if (ec) + { + return; + } + + if (!enabled) + { + asyncResp->res.jsonValue["Status"]["State"] = "Disabled"; + } }); } @@ -343,21 +326,21 @@ 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; - } - - // 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"; - } + // 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"; + } }); } @@ -409,81 +392,78 @@ inline void const std::vector< std::pair<std::string, dbus::utility::DbusVariantType>>& propertiesList) { - if (ec) + if (ec) + { + // this interface isn't required + return; + } + for (const std::pair<std::string, dbus::utility::DbusVariantType>& + property : propertiesList) + { + const std::string& propertyName = property.first; + if (propertyName == "Type") { - // this interface isn't required - return; - } - for (const std::pair<std::string, dbus::utility::DbusVariantType>& - property : propertiesList) - { - const std::string& propertyName = property.first; - if (propertyName == "Type") + const std::string* value = + std::get_if<std::string>(&property.second); + if (value == nullptr) { - 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; - } + // illegal property + BMCWEB_LOG_ERROR << "Illegal property: Type"; + messages::internalError(asyncResp->res); + return; + } - std::optional<std::string> mediaType = - convertDriveType(*value); - if (!mediaType) - { - BMCWEB_LOG_ERROR << "Unsupported DriveType Interface: " - << *value; - messages::internalError(asyncResp->res); - return; - } + std::optional<std::string> mediaType = convertDriveType(*value); + if (!mediaType) + { + BMCWEB_LOG_ERROR << "Unsupported DriveType Interface: " + << *value; + messages::internalError(asyncResp->res); + return; + } - asyncResp->res.jsonValue["MediaType"] = *mediaType; + asyncResp->res.jsonValue["MediaType"] = *mediaType; + } + else if (propertyName == "Capacity") + { + 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; } - else if (propertyName == "Capacity") + if (*capacity == 0) { - 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; + // drive capacity not known + continue; } - else if (propertyName == "Protocol") + + asyncResp->res.jsonValue["CapacityBytes"] = *capacity; + } + else if (propertyName == "Protocol") + { + const std::string* value = + std::get_if<std::string>(&property.second); + if (value == nullptr) { - 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; - } + BMCWEB_LOG_ERROR << "Illegal property: Protocol"; + messages::internalError(asyncResp->res); + return; + } - std::optional<std::string> proto = - convertDriveProtocol(*value); - if (!proto) - { - BMCWEB_LOG_ERROR - << "Unsupported DrivePrototype Interface: " - << *value; - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue["Protocol"] = *proto; + std::optional<std::string> proto = convertDriveProtocol(*value); + if (!proto) + { + BMCWEB_LOG_ERROR << "Unsupported DrivePrototype Interface: " + << *value; + messages::internalError(asyncResp->res); + return; } + asyncResp->res.jsonValue["Protocol"] = *proto; } + } }); } @@ -491,116 +471,104 @@ inline void requestRoutesDrive(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Storage/1/Drives/<str>/") .privileges(redfish::privileges::getDrive) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& driveId) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& driveId) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + crow::connections::systemBus->async_method_call( + [asyncResp, + driveId](const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec) { + BMCWEB_LOG_ERROR << "Drive mapper call error"; + messages::internalError(asyncResp->res); return; } - crow::connections::systemBus->async_method_call( - [asyncResp, driveId]( - const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) - { - BMCWEB_LOG_ERROR << "Drive mapper call error"; - messages::internalError(asyncResp->res); - return; - } - auto drive = std::find_if( - subtree.begin(), subtree.end(), - [&driveId](const std::pair< - std::string, - std::vector<std::pair< - std::string, std::vector<std::string>>>>& - object) { - return sdbusplus::message::object_path(object.first) - .filename() == driveId; - }); - - if (drive == subtree.end()) - { - messages::resourceNotFound(asyncResp->res, "Drive", - driveId); - return; - } + auto drive = std::find_if( + subtree.begin(), subtree.end(), + [&driveId]( + const std::pair< + std::string, + std::vector<std::pair< + std::string, std::vector<std::string>>>>& object) { + return sdbusplus::message::object_path(object.first) + .filename() == driveId; + }); + + if (drive == subtree.end()) + { + messages::resourceNotFound(asyncResp->res, "Drive", driveId); + return; + } - const std::string& path = drive->first; - const std::vector< - std::pair<std::string, std::vector<std::string>>>& - connectionNames = drive->second; - - asyncResp->res.jsonValue["@odata.type"] = - "#Drive.v1_7_0.Drive"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/Storage/1/Drives/" + - driveId; - asyncResp->res.jsonValue["Name"] = driveId; - asyncResp->res.jsonValue["Id"] = driveId; - - if (connectionNames.size() != 1) - { - BMCWEB_LOG_ERROR << "Connection size " - << connectionNames.size() - << ", not equal to 1"; - messages::internalError(asyncResp->res); - return; - } + const std::string& path = drive->first; + const std::vector<std::pair<std::string, std::vector<std::string>>>& + connectionNames = drive->second; - getMainChassisId( - asyncResp, - [](const std::string& chassisId, - const std::shared_ptr<bmcweb::AsyncResp>& aRsp) { - aRsp->res - .jsonValue["Links"]["Chassis"]["@odata.id"] = - "/redfish/v1/Chassis/" + chassisId; - }); + asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/Storage/1/Drives/" + driveId; + asyncResp->res.jsonValue["Name"] = driveId; + asyncResp->res.jsonValue["Id"] = driveId; - // default it to Enabled - asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + if (connectionNames.size() != 1) + { + BMCWEB_LOG_ERROR << "Connection size " << connectionNames.size() + << ", not equal to 1"; + messages::internalError(asyncResp->res); + return; + } - auto health = std::make_shared<HealthPopulate>(asyncResp); - health->inventory.emplace_back(path); - health->populate(); + getMainChassisId( + asyncResp, [](const std::string& chassisId, + const std::shared_ptr<bmcweb::AsyncResp>& aRsp) { + aRsp->res.jsonValue["Links"]["Chassis"]["@odata.id"] = + "/redfish/v1/Chassis/" + chassisId; + }); - const std::string& connectionName = - connectionNames[0].first; + // default it to Enabled + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; - for (const std::string& interface : - connectionNames[0].second) - { - if (interface == - "xyz.openbmc_project.Inventory.Decorator.Asset") - { - getDriveAsset(asyncResp, connectionName, path); - } - else if (interface == - "xyz.openbmc_project.Inventory.Item") - { - getDrivePresent(asyncResp, connectionName, path); - } - else if (interface == "xyz.openbmc_project.State.Drive") - { - getDriveState(asyncResp, connectionName, path); - } - else if (interface == - "xyz.openbmc_project.Inventory.Item.Drive") - { - getDriveItemProperties(asyncResp, connectionName, - path); - } - } - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/inventory", int32_t(0), - std::array<const char*, 1>{ - "xyz.openbmc_project.Inventory.Item.Drive"}); + auto health = std::make_shared<HealthPopulate>(asyncResp); + health->inventory.emplace_back(path); + health->populate(); + + const std::string& connectionName = connectionNames[0].first; + + for (const std::string& interface : connectionNames[0].second) + { + if (interface == + "xyz.openbmc_project.Inventory.Decorator.Asset") + { + getDriveAsset(asyncResp, connectionName, path); + } + else if (interface == "xyz.openbmc_project.Inventory.Item") + { + getDrivePresent(asyncResp, connectionName, path); + } + else if (interface == "xyz.openbmc_project.State.Drive") + { + getDriveState(asyncResp, connectionName, path); + } + else if (interface == + "xyz.openbmc_project.Inventory.Item.Drive") + { + getDriveItemProperties(asyncResp, connectionName, path); + } + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/inventory", int32_t(0), + std::array<const char*, 1>{ + "xyz.openbmc_project.Inventory.Item.Drive"}); }); } } // namespace redfish diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp index b11bb908f1..fdffe6bc9f 100644 --- a/redfish-core/lib/systems.hpp +++ b/redfish-core/lib/systems.hpp @@ -216,13 +216,13 @@ inline void getProcessorSummary(const std::shared_ptr<bmcweb::AsyncResp>& aResp, [aResp, service, path](const boost::system::error_code ec2, const dbus::utility::DBusPropertiesMap& properties) { - if (ec2) - { - BMCWEB_LOG_ERROR << "DBUS response error " << ec2; - messages::internalError(aResp->res); - return; - } - getProcessorProperties(aResp, service, path, properties); + if (ec2) + { + BMCWEB_LOG_ERROR << "DBUS response error " << ec2; + messages::internalError(aResp->res); + return; + } + getProcessorProperties(aResp, service, path, properties); }, service, path, "org.freedesktop.DBus.Properties", "GetAll", "xyz.openbmc_project.Inventory.Item.Cpu"); @@ -246,272 +246,255 @@ inline void [aResp, systemHealth](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + messages::internalError(aResp->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; + BMCWEB_LOG_DEBUG << "Got path: " << path; + const std::vector<std::pair<std::string, std::vector<std::string>>>& + connectionNames = object.second; + if (connectionNames.empty()) { - BMCWEB_LOG_DEBUG << "DBUS response error"; - messages::internalError(aResp->res); - return; + continue; } - // 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; - BMCWEB_LOG_DEBUG << "Got path: " << path; - const std::vector< - std::pair<std::string, std::vector<std::string>>>& - connectionNames = object.second; - if (connectionNames.empty()) - { - continue; - } - auto memoryHealth = std::make_shared<HealthPopulate>( - aResp, "/MemorySummary/Status"_json_pointer); + auto memoryHealth = std::make_shared<HealthPopulate>( + aResp, "/MemorySummary/Status"_json_pointer); - auto cpuHealth = std::make_shared<HealthPopulate>( - aResp, "/ProcessorSummary/Status"_json_pointer); + auto cpuHealth = std::make_shared<HealthPopulate>( + aResp, "/ProcessorSummary/Status"_json_pointer); - systemHealth->children.emplace_back(memoryHealth); - systemHealth->children.emplace_back(cpuHealth); + systemHealth->children.emplace_back(memoryHealth); + systemHealth->children.emplace_back(cpuHealth); - // This is not system, so check if it's cpu, dimm, UUID or - // BiosVer - for (const auto& connection : connectionNames) + // This is not system, so check if it's cpu, dimm, UUID or + // BiosVer + for (const auto& connection : connectionNames) + { + for (const auto& interfaceName : connection.second) { - for (const auto& interfaceName : connection.second) + if (interfaceName == + "xyz.openbmc_project.Inventory.Item.Dimm") { - if (interfaceName == - "xyz.openbmc_project.Inventory.Item.Dimm") - { - BMCWEB_LOG_DEBUG - << "Found Dimm, now get its properties."; - - crow::connections::systemBus->async_method_call( - [aResp, service{connection.first}, - path](const boost::system::error_code ec2, - const dbus::utility::DBusPropertiesMap& - properties) { - if (ec2) + BMCWEB_LOG_DEBUG + << "Found Dimm, now get its properties."; + + crow::connections::systemBus->async_method_call( + [aResp, service{connection.first}, + path](const boost::system::error_code ec2, + const dbus::utility::DBusPropertiesMap& + properties) { + if (ec2) + { + BMCWEB_LOG_ERROR << "DBUS response error " + << ec2; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Got " << properties.size() + << " Dimm properties."; + + if (!properties.empty()) + { + for (const std::pair< + std::string, + dbus::utility::DbusVariantType>& + property : properties) + { + if (property.first != "MemorySizeInKB") { - BMCWEB_LOG_ERROR - << "DBUS response error " << ec2; - messages::internalError(aResp->res); - return; + continue; } - BMCWEB_LOG_DEBUG << "Got " - << properties.size() - << " Dimm properties."; - - if (!properties.empty()) + const uint32_t* value = + std::get_if<uint32_t>(&property.second); + if (value == nullptr) { - for (const std::pair< - std::string, - dbus::utility:: - DbusVariantType>& - property : properties) - { - if (property.first != - "MemorySizeInKB") - { - continue; - } - const uint32_t* value = - std::get_if<uint32_t>( - &property.second); - if (value == nullptr) - { - BMCWEB_LOG_DEBUG - << "Find incorrect type of MemorySize"; - continue; - } - nlohmann::json& totalMemory = - aResp->res.jsonValue - ["MemorySummary"] - ["TotalSystemMemoryGiB"]; - uint64_t* preValue = - totalMemory - .get_ptr<uint64_t*>(); - if (preValue == nullptr) - { - continue; - } - aResp->res.jsonValue - ["MemorySummary"] - ["TotalSystemMemoryGiB"] = - *value / (1024 * 1024) + - *preValue; - aResp->res - .jsonValue["MemorySummary"] - ["Status"]["State"] = - "Enabled"; - } + BMCWEB_LOG_DEBUG + << "Find incorrect type of MemorySize"; + continue; } - else + nlohmann::json& totalMemory = + aResp->res + .jsonValue["MemorySummary"] + ["TotalSystemMemoryGiB"]; + uint64_t* preValue = + totalMemory.get_ptr<uint64_t*>(); + if (preValue == nullptr) { - sdbusplus::asio::getProperty<bool>( - *crow::connections::systemBus, - service, path, - "xyz.openbmc_project.State." - "Decorator.OperationalStatus", - "Functional", - [aResp]( - const boost::system::error_code - ec3, - bool dimmState) { - if (ec3) - { - BMCWEB_LOG_ERROR - << "DBUS response error " - << ec3; - return; - } - updateDimmProperties(aResp, - dimmState); - }); + continue; } - }, - connection.first, path, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Inventory.Item.Dimm"); - - memoryHealth->inventory.emplace_back(path); - } - else if (interfaceName == - "xyz.openbmc_project.Inventory.Item.Cpu") - { - BMCWEB_LOG_DEBUG - << "Found Cpu, now get its properties."; - - getProcessorSummary(aResp, connection.first, path); - - cpuHealth->inventory.emplace_back(path); - } - else if (interfaceName == - "xyz.openbmc_project.Common.UUID") - { - BMCWEB_LOG_DEBUG - << "Found UUID, now get its properties."; - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec3, - const dbus::utility::DBusPropertiesMap& - properties) { + aResp->res + .jsonValue["MemorySummary"] + ["TotalSystemMemoryGiB"] = + *value / (1024 * 1024) + *preValue; + aResp->res.jsonValue["MemorySummary"] + ["Status"]["State"] = + "Enabled"; + } + } + else + { + sdbusplus::asio::getProperty<bool>( + *crow::connections::systemBus, service, + path, + "xyz.openbmc_project.State." + "Decorator.OperationalStatus", + "Functional", + [aResp](const boost::system::error_code ec3, + bool dimmState) { if (ec3) { - BMCWEB_LOG_DEBUG + BMCWEB_LOG_ERROR << "DBUS response error " << ec3; - messages::internalError(aResp->res); return; } - BMCWEB_LOG_DEBUG << "Got " - << properties.size() - << " UUID properties."; - for (const std::pair< - std::string, - dbus::utility::DbusVariantType>& - property : properties) + updateDimmProperties(aResp, dimmState); + }); + } + }, + connection.first, path, + "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Inventory.Item.Dimm"); + + memoryHealth->inventory.emplace_back(path); + } + else if (interfaceName == + "xyz.openbmc_project.Inventory.Item.Cpu") + { + BMCWEB_LOG_DEBUG + << "Found Cpu, now get its properties."; + + getProcessorSummary(aResp, connection.first, path); + + cpuHealth->inventory.emplace_back(path); + } + else if (interfaceName == "xyz.openbmc_project.Common.UUID") + { + BMCWEB_LOG_DEBUG + << "Found UUID, now get its properties."; + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec3, + const dbus::utility::DBusPropertiesMap& + properties) { + if (ec3) + { + BMCWEB_LOG_DEBUG << "DBUS response error " + << ec3; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Got " << properties.size() + << " UUID properties."; + for (const std::pair< + std::string, + dbus::utility::DbusVariantType>& property : + properties) + { + if (property.first == "UUID") + { + const std::string* value = + std::get_if<std::string>( + &property.second); + + if (value != nullptr) { - if (property.first == "UUID") + std::string valueStr = *value; + if (valueStr.size() == 32) { - const std::string* value = - std::get_if<std::string>( - &property.second); - - if (value != nullptr) - { - std::string valueStr = *value; - if (valueStr.size() == 32) - { - valueStr.insert(8, 1, '-'); - valueStr.insert(13, 1, '-'); - valueStr.insert(18, 1, '-'); - valueStr.insert(23, 1, '-'); - } - BMCWEB_LOG_DEBUG << "UUID = " - << valueStr; - aResp->res.jsonValue["UUID"] = - valueStr; - } + valueStr.insert(8, 1, '-'); + valueStr.insert(13, 1, '-'); + valueStr.insert(18, 1, '-'); + valueStr.insert(23, 1, '-'); } + BMCWEB_LOG_DEBUG << "UUID = " + << valueStr; + aResp->res.jsonValue["UUID"] = valueStr; } - }, - connection.first, path, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Common.UUID"); - } - else if (interfaceName == - "xyz.openbmc_project.Inventory.Item.System") - { - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec2, - const dbus::utility::DBusPropertiesMap& - propertiesList) { - if (ec2) - { - // doesn't have to include this - // interface - return; - } - BMCWEB_LOG_DEBUG - << "Got " << propertiesList.size() - << " properties for system"; - for (const std::pair< - std::string, - dbus::utility::DbusVariantType>& - property : propertiesList) + } + } + }, + connection.first, path, + "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Common.UUID"); + } + else if (interfaceName == + "xyz.openbmc_project.Inventory.Item.System") + { + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec2, + const dbus::utility::DBusPropertiesMap& + propertiesList) { + if (ec2) + { + // doesn't have to include this + // interface + return; + } + BMCWEB_LOG_DEBUG << "Got " << propertiesList.size() + << " properties for system"; + for (const std::pair< + std::string, + dbus::utility::DbusVariantType>& property : + propertiesList) + { + const std::string& propertyName = + property.first; + if ((propertyName == "PartNumber") || + (propertyName == "SerialNumber") || + (propertyName == "Manufacturer") || + (propertyName == "Model") || + (propertyName == "SubModel")) + { + const std::string* value = + std::get_if<std::string>( + &property.second); + if (value != nullptr) { - const std::string& propertyName = - property.first; - if ((propertyName == "PartNumber") || - (propertyName == "SerialNumber") || - (propertyName == "Manufacturer") || - (propertyName == "Model") || - (propertyName == "SubModel")) - { - const std::string* value = - std::get_if<std::string>( - &property.second); - if (value != nullptr) - { - aResp->res - .jsonValue[propertyName] = - *value; - } - } + aResp->res.jsonValue[propertyName] = + *value; } + } + } - // Grab the bios version - fw_util::populateFirmwareInformation( - aResp, fw_util::biosPurpose, - "BiosVersion", false); - }, - connection.first, path, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Inventory.Decorator.Asset"); - - sdbusplus::asio::getProperty<std::string>( - *crow::connections::systemBus, connection.first, - path, - "xyz.openbmc_project.Inventory.Decorator." - "AssetTag", - "AssetTag", - [aResp](const boost::system::error_code ec2, - const std::string& value) { - if (ec2) - { - // doesn't have to include this - // interface - return; - } + // Grab the bios version + fw_util::populateFirmwareInformation( + aResp, fw_util::biosPurpose, "BiosVersion", + false); + }, + connection.first, path, + "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Inventory.Decorator.Asset"); + + sdbusplus::asio::getProperty<std::string>( + *crow::connections::systemBus, connection.first, + path, + "xyz.openbmc_project.Inventory.Decorator." + "AssetTag", + "AssetTag", + [aResp](const boost::system::error_code ec2, + const std::string& value) { + if (ec2) + { + // doesn't have to include this + // interface + return; + } - aResp->res.jsonValue["AssetTag"] = value; - }); - } + aResp->res.jsonValue["AssetTag"] = value; + }); } } } + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -542,58 +525,57 @@ inline void getHostState(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "CurrentHostState", [aResp](const boost::system::error_code ec, const std::string& hostState) { - if (ec) + if (ec) + { + if (ec == boost::system::errc::host_unreachable) { - 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(aResp->res); + // 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(aResp->res); + return; + } - BMCWEB_LOG_DEBUG << "Host state: " << hostState; - // Verify Host State - if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "Enabled"; - } - else if (hostState == - "xyz.openbmc_project.State.Host.HostState.Quiesced") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "Quiesced"; - } - else if (hostState == - "xyz.openbmc_project.State.Host.HostState.DiagnosticMode") - { - aResp->res.jsonValue["PowerState"] = "On"; - aResp->res.jsonValue["Status"]["State"] = "InTest"; - } - else if ( - hostState == - "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning") - { - aResp->res.jsonValue["PowerState"] = "PoweringOn"; - aResp->res.jsonValue["Status"]["State"] = "Starting"; - } - else if ( - hostState == - "xyz.openbmc_project.State.Host.HostState.TransitioningToOff") - { - aResp->res.jsonValue["PowerState"] = "PoweringOff"; - aResp->res.jsonValue["Status"]["State"] = "Disabled"; - } - else - { - aResp->res.jsonValue["PowerState"] = "Off"; - aResp->res.jsonValue["Status"]["State"] = "Disabled"; - } + BMCWEB_LOG_DEBUG << "Host state: " << hostState; + // Verify Host State + if (hostState == "xyz.openbmc_project.State.Host.HostState.Running") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "Enabled"; + } + else if (hostState == + "xyz.openbmc_project.State.Host.HostState.Quiesced") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "Quiesced"; + } + else if (hostState == + "xyz.openbmc_project.State.Host.HostState.DiagnosticMode") + { + aResp->res.jsonValue["PowerState"] = "On"; + aResp->res.jsonValue["Status"]["State"] = "InTest"; + } + else if ( + hostState == + "xyz.openbmc_project.State.Host.HostState.TransitioningToRunning") + { + aResp->res.jsonValue["PowerState"] = "PoweringOn"; + aResp->res.jsonValue["Status"]["State"] = "Starting"; + } + else if (hostState == + "xyz.openbmc_project.State.Host.HostState.TransitioningToOff") + { + aResp->res.jsonValue["PowerState"] = "PoweringOff"; + aResp->res.jsonValue["Status"]["State"] = "Disabled"; + } + else + { + aResp->res.jsonValue["PowerState"] = "Off"; + aResp->res.jsonValue["Status"]["State"] = "Disabled"; + } }); } @@ -832,17 +814,17 @@ inline void getBootProgress(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "xyz.openbmc_project.State.Boot.Progress", "BootProgress", [aResp](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; - aResp->res.jsonValue["BootProgress"]["LastState"] = - dbusToRfBootProgress(bootProgressStr); + aResp->res.jsonValue["BootProgress"]["LastState"] = + dbusToRfBootProgress(bootProgressStr); }); } @@ -862,27 +844,26 @@ inline void getBootOverrideType(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "xyz.openbmc_project.Control.Boot.Type", "BootType", [aResp](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; - aResp->res - .jsonValue["Boot"] - ["BootSourceOverrideMode@Redfish.AllowableValues"] = { - "Legacy", "UEFI"}; + aResp->res.jsonValue["Boot"] + ["BootSourceOverrideMode@Redfish.AllowableValues"] = + {"Legacy", "UEFI"}; - auto rfType = dbusToRfBootType(bootType); - if (rfType.empty()) - { - messages::internalError(aResp->res); - return; - } + auto rfType = dbusToRfBootType(bootType); + if (rfType.empty()) + { + messages::internalError(aResp->res); + return; + } - aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType; + aResp->res.jsonValue["Boot"]["BootSourceOverrideMode"] = rfType; }); } @@ -902,30 +883,30 @@ inline void getBootOverrideMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "xyz.openbmc_project.Control.Boot.Mode", "BootMode", [aResp](const boost::system::error_code ec, const std::string& bootModeStr) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } - BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr; + BMCWEB_LOG_DEBUG << "Boot mode: " << bootModeStr; - aResp->res - .jsonValue["Boot"] - ["BootSourceOverrideTarget@Redfish.AllowableValues"] = - {"None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"}; + aResp->res + .jsonValue["Boot"] + ["BootSourceOverrideTarget@Redfish.AllowableValues"] = { + "None", "Pxe", "Hdd", "Cd", "Diags", "BiosSetup", "Usb"}; - if (bootModeStr != - "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular") + if (bootModeStr != + "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular") + { + auto rfMode = dbusToRfBootMode(bootModeStr); + if (!rfMode.empty()) { - auto rfMode = dbusToRfBootMode(bootModeStr); - if (!rfMode.empty()) - { - aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = - rfMode; - } + aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = + rfMode; } + } }); } @@ -946,25 +927,24 @@ inline void "xyz.openbmc_project.Control.Boot.Source", "BootSource", [aResp](const boost::system::error_code ec, const std::string& bootSourceStr) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } - BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr; + BMCWEB_LOG_DEBUG << "Boot source: " << bootSourceStr; - auto rfSource = dbusToRfBootSource(bootSourceStr); - if (!rfSource.empty()) - { - aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = - rfSource; - } + auto rfSource = dbusToRfBootSource(bootSourceStr); + if (!rfSource.empty()) + { + aResp->res.jsonValue["Boot"]["BootSourceOverrideTarget"] = rfSource; + } - // Get BootMode as BootSourceOverrideTarget is constructed - // from both BootSource and BootMode - getBootOverrideMode(aResp); + // Get BootMode as BootSourceOverrideTarget is constructed + // from both BootSource and BootMode + getBootOverrideMode(aResp); }); } @@ -995,23 +975,22 @@ inline void "/xyz/openbmc_project/control/host0/boot/one_time", "xyz.openbmc_project.Object.Enable", "Enabled", [aResp](const boost::system::error_code ec, bool oneTimeSetting) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } - if (oneTimeSetting) - { - aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = - "Once"; - } - else - { - aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = - "Continuous"; - } + if (oneTimeSetting) + { + aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = "Once"; + } + else + { + aResp->res.jsonValue["Boot"]["BootSourceOverrideEnabled"] = + "Continuous"; + } }); } @@ -1032,14 +1011,14 @@ inline void "xyz.openbmc_project.Object.Enable", "Enabled", [aResp](const boost::system::error_code ec, const bool bootOverrideEnable) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } - processBootOverrideEnable(aResp, bootOverrideEnable); + processBootOverrideEnable(aResp, bootOverrideEnable); }); } @@ -1080,19 +1059,19 @@ inline void getLastResetTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "/xyz/openbmc_project/state/chassis0", "xyz.openbmc_project.State.Chassis", "LastStateChangeTime", [aResp](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 - aResp->res.jsonValue["LastResetTime"] = - crow::utility::getDateTimeUint(lastResetTimeStamp); + // Convert to ISO 8601 standard + aResp->res.jsonValue["LastResetTime"] = + crow::utility::getDateTimeUint(lastResetTimeStamp); }); } @@ -1112,59 +1091,55 @@ inline void getAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp) "/xyz/openbmc_project/control/host0/auto_reboot", "xyz.openbmc_project.Control.Boot.RebootPolicy", "AutoReboot", [aResp](const boost::system::error_code ec, bool autoRebootEnabled) { - if (ec) - { - BMCWEB_LOG_DEBUG << "D-BUS response error " << ec; - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "D-BUS response error " << ec; + return; + } - BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled; - if (autoRebootEnabled) - { - aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = - "RetryAttempts"; - // If AutomaticRetry (AutoReboot) is enabled see how many - // attempts are left - sdbusplus::asio::getProperty<uint32_t>( - *crow::connections::systemBus, - "xyz.openbmc_project.State.Host", - "/xyz/openbmc_project/state/host0", - "xyz.openbmc_project.Control.Boot.RebootAttempts", - "AttemptsLeft", - [aResp](const boost::system::error_code ec2, - const uint32_t autoRebootAttemptsLeft) { - if (ec2) - { - BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2; - return; - } - - BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: " - << autoRebootAttemptsLeft; - - aResp->res - .jsonValue["Boot"] - ["RemainingAutomaticRetryAttempts"] = - autoRebootAttemptsLeft; - }); - } - else - { - aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = - "Disabled"; - } + BMCWEB_LOG_DEBUG << "Auto Reboot: " << autoRebootEnabled; + if (autoRebootEnabled) + { + aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = + "RetryAttempts"; + // If AutomaticRetry (AutoReboot) is enabled see how many + // attempts are left + sdbusplus::asio::getProperty<uint32_t>( + *crow::connections::systemBus, "xyz.openbmc_project.State.Host", + "/xyz/openbmc_project/state/host0", + "xyz.openbmc_project.Control.Boot.RebootAttempts", + "AttemptsLeft", + [aResp](const boost::system::error_code ec2, + const uint32_t autoRebootAttemptsLeft) { + if (ec2) + { + BMCWEB_LOG_DEBUG << "D-BUS response error " << ec2; + return; + } + + BMCWEB_LOG_DEBUG << "Auto Reboot Attempts Left: " + << autoRebootAttemptsLeft; - // Not on D-Bus. Hardcoded here: - // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71 - aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3; - - // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways, - // and RetryAttempts. OpenBMC only supports Disabled and - // RetryAttempts. - aResp->res - .jsonValue["Boot"] - ["AutomaticRetryConfig@Redfish.AllowableValues"] = { - "Disabled", "RetryAttempts"}; + aResp->res + .jsonValue["Boot"]["RemainingAutomaticRetryAttempts"] = + autoRebootAttemptsLeft; + }); + } + else + { + aResp->res.jsonValue["Boot"]["AutomaticRetryConfig"] = "Disabled"; + } + + // Not on D-Bus. Hardcoded here: + // https://github.com/openbmc/phosphor-state-manager/blob/1dbbef42675e94fb1f78edb87d6b11380260535a/meson_options.txt#L71 + aResp->res.jsonValue["Boot"]["AutomaticRetryAttempts"] = 3; + + // "AutomaticRetryConfig" can be 3 values, Disabled, RetryAlways, + // and RetryAttempts. OpenBMC only supports Disabled and + // RetryAttempts. + aResp->res.jsonValue["Boot"] + ["AutomaticRetryConfig@Redfish.AllowableValues"] = { + "Disabled", "RetryAttempts"}; }); } @@ -1185,31 +1160,31 @@ inline void "/xyz/openbmc_project/control/host0/power_restore_policy", "xyz.openbmc_project.Control.Power.RestorePolicy", "PowerRestorePolicy", [aResp](const boost::system::error_code ec, const std::string& policy) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + return; + } - const boost::container::flat_map<std::string, std::string> policyMaps = { - {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn", - "AlwaysOn"}, - {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff", - "AlwaysOff"}, - {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore", - "LastState"}, - // Return `AlwaysOff` when power restore policy set to "None" - {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None", - "AlwaysOff"}}; - - auto policyMapsIt = policyMaps.find(policy); - if (policyMapsIt == policyMaps.end()) - { - messages::internalError(aResp->res); - return; - } + const boost::container::flat_map<std::string, std::string> policyMaps = { + {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn", + "AlwaysOn"}, + {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff", + "AlwaysOff"}, + {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore", + "LastState"}, + // Return `AlwaysOff` when power restore policy set to "None" + {"xyz.openbmc_project.Control.Power.RestorePolicy.Policy.None", + "AlwaysOff"}}; + + auto policyMapsIt = policyMaps.find(policy); + if (policyMapsIt == policyMaps.end()) + { + messages::internalError(aResp->res); + return; + } - aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second; + aResp->res.jsonValue["PowerRestorePolicy"] = policyMapsIt->second; }); } @@ -1229,70 +1204,68 @@ inline void getTrustedModuleRequiredToBoot( crow::connections::systemBus->async_method_call( [aResp](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(aResp->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(aResp->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", + [aResp](const boost::system::error_code ec, bool tpmRequired) { 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 + BMCWEB_LOG_DEBUG << "D-BUS response error on TPM.Policy Get" + << ec; + messages::internalError(aResp->res); return; } - /* When there is more than one TPMEnable object... */ - if (subtree.size() > 1) + if (tpmRequired) { - BMCWEB_LOG_DEBUG - << "DBUS response has more than 1 TPM Enable object:" - << subtree.size(); - // Throw an internal Error and return - messages::internalError(aResp->res); - return; + aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] = + "Required"; } - - // Make sure the Dbus response map has a service and objectPath - // field - if (subtree[0].first.empty() || subtree[0].second.size() != 1) + else { - BMCWEB_LOG_DEBUG << "TPM.Policy mapper error!"; - messages::internalError(aResp->res); - return; + aResp->res.jsonValue["Boot"]["TrustedModuleRequiredToBoot"] = + "Disabled"; } - - 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", - [aResp](const boost::system::error_code ec, bool tpmRequired) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "D-BUS response error on TPM.Policy Get" << ec; - messages::internalError(aResp->res); - return; - } - - if (tpmRequired) - { - aResp->res - .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] = - "Required"; - } - else - { - aResp->res - .jsonValue["Boot"]["TrustedModuleRequiredToBoot"] = - "Disabled"; - } - }); + }); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1317,66 +1290,66 @@ inline void setTrustedModuleRequiredToBoot( crow::connections::systemBus->async_method_call( [aResp, tpmRequired](const boost::system::error_code ec, dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "DBUS response error on TPM.Policy GetSubTree" << ec; - messages::internalError(aResp->res); - return; - } - if (subtree.empty()) - { - messages::propertyValueNotInList(aResp->res, "ComputerSystem", - "TrustedModuleRequiredToBoot"); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error on TPM.Policy GetSubTree" + << ec; + messages::internalError(aResp->res); + return; + } + if (subtree.empty()) + { + messages::propertyValueNotInList(aResp->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(aResp->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(aResp->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(aResp->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(aResp->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()) + if (serv.empty()) + { + BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!"; + messages::internalError(aResp->res); + return; + } + + // Valid TPM Enable object found, now setting the value + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) { - BMCWEB_LOG_DEBUG << "TPM.Policy service mapper error!"; + BMCWEB_LOG_DEBUG + << "DBUS response error: Set TrustedModuleRequiredToBoot" + << ec; messages::internalError(aResp->res); return; } - - // Valid TPM Enable object found, now setting the value - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "DBUS response error: Set TrustedModuleRequiredToBoot" - << ec; - messages::internalError(aResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done."; - }, - serv, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable", - dbus::utility::DbusVariantType(tpmRequired)); + BMCWEB_LOG_DEBUG << "Set TrustedModuleRequiredToBoot done."; + }, + serv, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.TPM.Policy", "TPMEnable", + dbus::utility::DbusVariantType(tpmRequired)); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1427,18 +1400,18 @@ inline void setBootType(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + if (ec.value() == boost::asio::error::host_unreachable) { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - if (ec.value() == boost::asio::error::host_unreachable) - { - messages::resourceNotFound(aResp->res, "Set", "BootType"); - return; - } - messages::internalError(aResp->res); + messages::resourceNotFound(aResp->res, "Set", "BootType"); return; } - BMCWEB_LOG_DEBUG << "Boot type update done."; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Boot type update done."; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/boot", @@ -1496,13 +1469,13 @@ inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Boot override enable update done."; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Boot override enable update done."; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/boot", @@ -1522,13 +1495,13 @@ inline void setBootEnable(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Boot one_time update done."; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Boot one_time update done."; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/boot/one_time", @@ -1576,13 +1549,13 @@ inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Boot source update done."; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Boot source update done."; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/boot", @@ -1592,13 +1565,13 @@ inline void setBootModeOrSource(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - BMCWEB_LOG_DEBUG << "Boot mode update done."; + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + BMCWEB_LOG_DEBUG << "Boot mode update done."; }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/boot", @@ -1645,56 +1618,56 @@ inline void setAssetTag(const std::shared_ptr<bmcweb::AsyncResp>& aResp, [aResp, 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(aResp->res); - return; - } - if (subtree.empty()) - { - BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!"; - messages::internalError(aResp->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(aResp->res); - return; - } - if (subtree[0].first.empty() || subtree[0].second.size() != 1) - { - BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!"; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec; + messages::internalError(aResp->res); + return; + } + if (subtree.empty()) + { + BMCWEB_LOG_DEBUG << "Can't find system D-Bus object!"; + messages::internalError(aResp->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(aResp->res); + return; + } + if (subtree[0].first.empty() || subtree[0].second.size() != 1) + { + BMCWEB_LOG_DEBUG << "Asset Tag Set mapper error!"; + messages::internalError(aResp->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()) + if (service.empty()) + { + BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!"; + messages::internalError(aResp->res); + return; + } + + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec2) { + if (ec2) { - BMCWEB_LOG_DEBUG << "Asset Tag Set service mapper error!"; + BMCWEB_LOG_DEBUG << "D-Bus response error on AssetTag Set " + << ec2; messages::internalError(aResp->res); return; } - - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec2) { - if (ec2) - { - BMCWEB_LOG_DEBUG - << "D-Bus response error on AssetTag Set " << ec2; - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag", - dbus::utility::DbusVariantType(assetTag)); + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Inventory.Decorator.AssetTag", "AssetTag", + dbus::utility::DbusVariantType(assetTag)); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -1739,11 +1712,11 @@ inline void setAutomaticRetry(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(aResp->res); - return; - } + if (ec) + { + messages::internalError(aResp->res); + return; + } }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/auto_reboot", @@ -1788,11 +1761,11 @@ inline void crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(aResp->res); - return; - } + if (ec) + { + messages::internalError(aResp->res); + return; + } }, "xyz.openbmc_project.Settings", "/xyz/openbmc_project/control/host0/power_restore_policy", @@ -1815,57 +1788,57 @@ inline void getProvisioningStatus(std::shared_ptr<bmcweb::AsyncResp> aResp) crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec, const dbus::utility::DBusPropertiesMap& propertiesList) { - nlohmann::json& oemPFR = - aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"]; - aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] = - "#OemComputerSystem.OpenBmc"; - oemPFR["@odata.type"] = "#OemComputerSystem.FirmwareProvisioning"; + nlohmann::json& oemPFR = + aResp->res.jsonValue["Oem"]["OpenBmc"]["FirmwareProvisioning"]; + aResp->res.jsonValue["Oem"]["OpenBmc"]["@odata.type"] = + "#OemComputerSystem.OpenBmc"; + oemPFR["@odata.type"] = "#OemComputerSystem.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"] = "NotProvisioned"; + return; + } - const bool* provState = nullptr; - const bool* lockState = nullptr; - for (const std::pair<std::string, dbus::utility::DbusVariantType>& - property : propertiesList) + const bool* provState = nullptr; + const bool* lockState = nullptr; + for (const std::pair<std::string, dbus::utility::DbusVariantType>& + property : propertiesList) + { + if (property.first == "UfmProvisioned") { - if (property.first == "UfmProvisioned") - { - provState = std::get_if<bool>(&property.second); - } - else if (property.first == "UfmLocked") - { - lockState = std::get_if<bool>(&property.second); - } + provState = std::get_if<bool>(&property.second); } - - if ((provState == nullptr) || (lockState == nullptr)) + else if (property.first == "UfmLocked") { - BMCWEB_LOG_DEBUG << "Unable to get PFR attributes."; - messages::internalError(aResp->res); - return; + lockState = std::get_if<bool>(&property.second); } + } - if (*provState == true) + if ((provState == nullptr) || (lockState == nullptr)) + { + BMCWEB_LOG_DEBUG << "Unable to get PFR attributes."; + messages::internalError(aResp->res); + return; + } + + if (*provState == true) + { + if (*lockState == true) { - if (*lockState == true) - { - oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked"; - } - else - { - oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked"; - } + oemPFR["ProvisioningStatus"] = "ProvisionedAndLocked"; } else { - oemPFR["ProvisioningStatus"] = "NotProvisioned"; + oemPFR["ProvisioningStatus"] = "ProvisionedButNotLocked"; } + } + else + { + oemPFR["ProvisioningStatus"] = "NotProvisioned"; + } }, "xyz.openbmc_project.PFR.Manager", "/xyz/openbmc_project/pfr", "org.freedesktop.DBus.Properties", "GetAll", @@ -1927,64 +1900,64 @@ inline void getPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp) crow::connections::systemBus->async_method_call( [aResp](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(aResp->res); + return; + } + if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) + { + BMCWEB_LOG_DEBUG << "Power.Mode mapper error!"; + messages::internalError(aResp->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(aResp->res); + return; + } + // Valid Power Mode object found, now read the current value + sdbusplus::asio::getProperty<std::string>( + *crow::connections::systemBus, service, path, + "xyz.openbmc_project.Control.Power.Mode", "PowerMode", + [aResp](const boost::system::error_code ec, + const std::string& pmode) { 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(); + BMCWEB_LOG_DEBUG << "DBUS response error on PowerMode Get: " + << ec; messages::internalError(aResp->res); return; } - if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) - { - BMCWEB_LOG_DEBUG << "Power.Mode mapper error!"; - messages::internalError(aResp->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(aResp->res); - return; - } - // Valid Power Mode object found, now read the current value - sdbusplus::asio::getProperty<std::string>( - *crow::connections::systemBus, service, path, - "xyz.openbmc_project.Control.Power.Mode", "PowerMode", - [aResp](const boost::system::error_code ec, - const std::string& pmode) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "DBUS response error on PowerMode Get: " << ec; - messages::internalError(aResp->res); - return; - } - aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = - {"Static", "MaximumPerformance", "PowerSaving"}; + aResp->res.jsonValue["PowerMode@Redfish.AllowableValues"] = { + "Static", "MaximumPerformance", "PowerSaving"}; - BMCWEB_LOG_DEBUG << "Current power mode: " << pmode; - translatePowerMode(aResp, pmode); - }); + BMCWEB_LOG_DEBUG << "Current power mode: " << pmode; + translatePowerMode(aResp, pmode); + }); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -2051,61 +2024,61 @@ inline void setPowerMode(const std::shared_ptr<bmcweb::AsyncResp>& aResp, [aResp, powerMode](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, but user attempted to patch + messages::internalError(aResp->res); + return; + } + if (subtree.empty()) + { + // This is an optional D-Bus object, but user attempted to patch + messages::resourceNotFound(aResp->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(aResp->res); + return; + } + if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) + { + BMCWEB_LOG_DEBUG << "Power.Mode mapper error!"; + messages::internalError(aResp->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(aResp->res); + return; + } + + BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> " + << path; + + // Set the Power Mode property + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { if (ec) { - BMCWEB_LOG_DEBUG - << "DBUS response error on Power.Mode GetSubTree " << ec; - // This is an optional D-Bus object, but user attempted to patch messages::internalError(aResp->res); return; } - if (subtree.empty()) - { - // This is an optional D-Bus object, but user attempted to patch - messages::resourceNotFound(aResp->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(aResp->res); - return; - } - if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) - { - BMCWEB_LOG_DEBUG << "Power.Mode mapper error!"; - messages::internalError(aResp->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(aResp->res); - return; - } - - BMCWEB_LOG_DEBUG << "Setting power mode(" << powerMode << ") -> " - << path; - - // Set the Power Mode property - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.Mode", "PowerMode", - dbus::utility::DbusVariantType(powerMode)); + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.Mode", "PowerMode", + dbus::utility::DbusVariantType(powerMode)); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -2188,55 +2161,55 @@ inline void crow::connections::systemBus->async_method_call( [aResp](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 " << properties.size() << " wdt prop."; + BMCWEB_LOG_DEBUG << "Got " << properties.size() << " wdt prop."; - nlohmann::json& hostWatchdogTimer = - aResp->res.jsonValue["HostWatchdogTimer"]; + nlohmann::json& hostWatchdogTimer = + aResp->res.jsonValue["HostWatchdogTimer"]; - // watchdog service is running/enabled - hostWatchdogTimer["Status"]["State"] = "Enabled"; + // watchdog service is running/enabled + hostWatchdogTimer["Status"]["State"] = "Enabled"; - for (const auto& property : properties) + for (const auto& property : properties) + { + BMCWEB_LOG_DEBUG << "prop=" << property.first; + if (property.first == "Enabled") { - BMCWEB_LOG_DEBUG << "prop=" << property.first; - if (property.first == "Enabled") - { - const bool* state = std::get_if<bool>(&property.second); - - if (state == nullptr) - { - messages::internalError(aResp->res); - return; - } + const bool* state = std::get_if<bool>(&property.second); - hostWatchdogTimer["FunctionEnabled"] = *state; + if (state == nullptr) + { + messages::internalError(aResp->res); + return; } - else if (property.first == "ExpireAction") + + hostWatchdogTimer["FunctionEnabled"] = *state; + } + else if (property.first == "ExpireAction") + { + const std::string* s = + std::get_if<std::string>(&property.second); + if (s == nullptr) { - const std::string* s = - std::get_if<std::string>(&property.second); - if (s == nullptr) - { - messages::internalError(aResp->res); - return; - } + messages::internalError(aResp->res); + return; + } - std::string action = dbusToRfWatchdogAction(*s); - if (action.empty()) - { - messages::internalError(aResp->res); - return; - } - hostWatchdogTimer["TimeoutAction"] = action; + std::string action = dbusToRfWatchdogAction(*s); + if (action.empty()) + { + messages::internalError(aResp->res); + return; } + hostWatchdogTimer["TimeoutAction"] = action; } + } }, "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0", "org.freedesktop.DBus.Properties", "GetAll", @@ -2274,12 +2247,12 @@ inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp, crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } }, "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0", @@ -2292,12 +2265,12 @@ inline void setWDTProperties(const std::shared_ptr<bmcweb::AsyncResp>& aResp, { crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } }, "xyz.openbmc_project.Watchdog", "/xyz/openbmc_project/watchdog/host0", @@ -2404,68 +2377,66 @@ inline void getIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp) crow::connections::systemBus->async_method_call( [aResp](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec) + { + BMCWEB_LOG_DEBUG + << "DBUS response error on Power.IdlePowerSaver GetSubTree " + << ec; + messages::internalError(aResp->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(aResp->res); + return; + } + if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) + { + BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!"; + messages::internalError(aResp->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(aResp->res); + return; + } + + // Valid IdlePowerSaver object found, now read the current values + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec, + ipsPropertiesType& properties) { if (ec) { - BMCWEB_LOG_DEBUG - << "DBUS response error on Power.IdlePowerSaver GetSubTree " - << ec; - messages::internalError(aResp->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(aResp->res); - return; - } - if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) - { - BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!"; + BMCWEB_LOG_ERROR + << "DBUS response error on IdlePowerSaver GetAll: " << ec; messages::internalError(aResp->res); return; } - const std::string& path = subtree[0].first; - const std::string& service = subtree[0].second.begin()->first; - if (service.empty()) + + if (!parseIpsProperties(aResp, properties)) { - BMCWEB_LOG_DEBUG - << "Power.IdlePowerSaver service mapper error!"; messages::internalError(aResp->res); return; } - - // Valid IdlePowerSaver object found, now read the current values - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec, - ipsPropertiesType& properties) { - if (ec) - { - BMCWEB_LOG_ERROR - << "DBUS response error on IdlePowerSaver GetAll: " - << ec; - messages::internalError(aResp->res); - return; - } - - if (!parseIpsProperties(aResp, properties)) - { - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Control.Power.IdlePowerSaver"); + }, + service, path, "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Control.Power.IdlePowerSaver"); }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -2505,133 +2476,132 @@ inline void setIdlePowerSaver(const std::shared_ptr<bmcweb::AsyncResp>& aResp, [aResp, ipsEnable, ipsEnterUtil, ipsEnterTime, ipsExitUtil, ipsExitTime](const boost::system::error_code ec, const dbus::utility::MapperGetSubTreeResponse& subtree) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "DBUS response error on Power.IdlePowerSaver GetSubTree " - << ec; - messages::internalError(aResp->res); - return; - } - if (subtree.empty()) - { - // This is an optional D-Bus object, but user attempted to patch - messages::resourceNotFound(aResp->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(aResp->res); - return; - } - if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) - { - BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!"; - messages::internalError(aResp->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(aResp->res); - return; - } + if (ec) + { + BMCWEB_LOG_DEBUG + << "DBUS response error on Power.IdlePowerSaver GetSubTree " + << ec; + messages::internalError(aResp->res); + return; + } + if (subtree.empty()) + { + // This is an optional D-Bus object, but user attempted to patch + messages::resourceNotFound(aResp->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(aResp->res); + return; + } + if ((subtree[0].first.empty()) || (subtree[0].second.size() != 1)) + { + BMCWEB_LOG_DEBUG << "Power.IdlePowerSaver mapper error!"; + messages::internalError(aResp->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(aResp->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) - { - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.IdlePowerSaver", - "Enabled", dbus::utility::DbusVariantType(*ipsEnable)); - } - if (ipsEnterUtil) - { - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.IdlePowerSaver", - "EnterUtilizationPercent", - dbus::utility::DbusVariantType(*ipsEnterUtil)); - } - if (ipsEnterTime) - { - // Convert from seconds into milliseconds for DBus - const uint64_t timeMilliseconds = *ipsEnterTime * 1000; - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.IdlePowerSaver", - "EnterDwellTime", - dbus::utility::DbusVariantType(timeMilliseconds)); - } - if (ipsExitUtil) - { - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.IdlePowerSaver", - "ExitUtilizationPercent", - dbus::utility::DbusVariantType(*ipsExitUtil)); - } - if (ipsExitTime) - { - // Convert from seconds into milliseconds for DBus - const uint64_t timeMilliseconds = *ipsExitTime * 1000; - crow::connections::systemBus->async_method_call( - [aResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(aResp->res); - return; - } - }, - service, path, "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Control.Power.IdlePowerSaver", - "ExitDwellTime", - dbus::utility::DbusVariantType(timeMilliseconds)); - } + if (ipsEnable) + { + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.IdlePowerSaver", "Enabled", + dbus::utility::DbusVariantType(*ipsEnable)); + } + if (ipsEnterUtil) + { + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.IdlePowerSaver", + "EnterUtilizationPercent", + dbus::utility::DbusVariantType(*ipsEnterUtil)); + } + if (ipsEnterTime) + { + // Convert from seconds into milliseconds for DBus + const uint64_t timeMilliseconds = *ipsEnterTime * 1000; + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.IdlePowerSaver", + "EnterDwellTime", + dbus::utility::DbusVariantType(timeMilliseconds)); + } + if (ipsExitUtil) + { + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.IdlePowerSaver", + "ExitUtilizationPercent", + dbus::utility::DbusVariantType(*ipsExitUtil)); + } + if (ipsExitTime) + { + // Convert from seconds into milliseconds for DBus + const uint64_t timeMilliseconds = *ipsExitTime * 1000; + crow::connections::systemBus->async_method_call( + [aResp](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(aResp->res); + return; + } + }, + service, path, "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Control.Power.IdlePowerSaver", + "ExitDwellTime", + dbus::utility::DbusVariantType(timeMilliseconds)); + } }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -2653,44 +2623,39 @@ inline void requestRoutesSystemsCollection(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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#ComputerSystemCollection.ComputerSystemCollection"; - asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems"; - asyncResp->res.jsonValue["Name"] = "Computer System Collection"; - - 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*/) { - nlohmann::json& ifaceArray = - asyncResp->res.jsonValue["Members"]; - ifaceArray = nlohmann::json::array(); - auto& count = - asyncResp->res.jsonValue["Members@odata.count"]; - - nlohmann::json::object_t system; - system["@odata.id"] = "/redfish/v1/Systems/system"; - ifaceArray.push_back(std::move(system)); - count = ifaceArray.size(); - if (!ec) - { - BMCWEB_LOG_DEBUG << "Hypervisor is available"; - nlohmann::json::object_t hypervisor; - hypervisor["@odata.id"] = - "/redfish/v1/Systems/hypervisor"; - ifaceArray.push_back(std::move(hypervisor)); - count = ifaceArray.size(); - } - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#ComputerSystemCollection.ComputerSystemCollection"; + asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems"; + asyncResp->res.jsonValue["Name"] = "Computer System Collection"; + + 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*/) { + nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; + ifaceArray = nlohmann::json::array(); + auto& count = asyncResp->res.jsonValue["Members@odata.count"]; + + nlohmann::json::object_t system; + system["@odata.id"] = "/redfish/v1/Systems/system"; + ifaceArray.push_back(std::move(system)); + count = ifaceArray.size(); + if (!ec) + { + BMCWEB_LOG_DEBUG << "Hypervisor is available"; + nlohmann::json::object_t hypervisor; + hypervisor["@odata.id"] = "/redfish/v1/Systems/hypervisor"; + ifaceArray.push_back(std::move(hypervisor)); + count = ifaceArray.size(); + } }); + }); } /** @@ -2706,13 +2671,13 @@ 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); } @@ -2730,124 +2695,119 @@ inline void requestRoutesSystemActionsReset(App& app) BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset/") .privileges(redfish::privileges::postComputerSystem) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::string resetType; - if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", - resetType)) - { - return; - } + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::string resetType; + if (!json_util::readJsonAction(req, asyncResp->res, "ResetType", + resetType)) + { + return; + } - // Get the command and host vs. chassis - std::string command; - bool hostCommand = true; - if ((resetType == "On") || (resetType == "ForceOn")) - { - command = "xyz.openbmc_project.State.Host.Transition.On"; - hostCommand = true; - } - else if (resetType == "ForceOff") - { - command = "xyz.openbmc_project.State.Chassis.Transition.Off"; - hostCommand = false; - } - else if (resetType == "ForceRestart") - { - command = - "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot"; - hostCommand = true; - } - else if (resetType == "GracefulShutdown") - { - command = "xyz.openbmc_project.State.Host.Transition.Off"; - hostCommand = true; - } - else if (resetType == "GracefulRestart") - { - command = - "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot"; - hostCommand = true; - } - else if (resetType == "PowerCycle") - { - command = "xyz.openbmc_project.State.Host.Transition.Reboot"; - hostCommand = true; - } - else if (resetType == "Nmi") - { - doNMI(asyncResp); - return; - } - else - { - messages::actionParameterUnknown(asyncResp->res, "Reset", - resetType); - return; - } + // Get the command and host vs. chassis + std::string command; + bool hostCommand = true; + if ((resetType == "On") || (resetType == "ForceOn")) + { + command = "xyz.openbmc_project.State.Host.Transition.On"; + hostCommand = true; + } + else if (resetType == "ForceOff") + { + command = "xyz.openbmc_project.State.Chassis.Transition.Off"; + hostCommand = false; + } + else if (resetType == "ForceRestart") + { + command = + "xyz.openbmc_project.State.Host.Transition.ForceWarmReboot"; + hostCommand = true; + } + else if (resetType == "GracefulShutdown") + { + command = "xyz.openbmc_project.State.Host.Transition.Off"; + hostCommand = true; + } + else if (resetType == "GracefulRestart") + { + command = + "xyz.openbmc_project.State.Host.Transition.GracefulWarmReboot"; + hostCommand = true; + } + else if (resetType == "PowerCycle") + { + command = "xyz.openbmc_project.State.Host.Transition.Reboot"; + hostCommand = true; + } + else if (resetType == "Nmi") + { + doNMI(asyncResp); + return; + } + else + { + messages::actionParameterUnknown(asyncResp->res, "Reset", + resetType); + return; + } - if (hostCommand) - { - crow::connections::systemBus->async_method_call( - [asyncResp, resetType](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - if (ec.value() == - boost::asio::error::invalid_argument) - { - messages::actionParameterNotSupported( - asyncResp->res, resetType, "Reset"); - } - else - { - messages::internalError(asyncResp->res); - } - return; - } - messages::success(asyncResp->res); - }, - "xyz.openbmc_project.State.Host", - "/xyz/openbmc_project/state/host0", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.State.Host", "RequestedHostTransition", - dbus::utility::DbusVariantType{command}); - } - else - { - crow::connections::systemBus->async_method_call( - [asyncResp, resetType](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; - if (ec.value() == - boost::asio::error::invalid_argument) - { - messages::actionParameterNotSupported( - asyncResp->res, resetType, "Reset"); - } - else - { - messages::internalError(asyncResp->res); - } - return; - } - messages::success(asyncResp->res); - }, - "xyz.openbmc_project.State.Chassis", - "/xyz/openbmc_project/state/chassis0", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.State.Chassis", - "RequestedPowerTransition", - dbus::utility::DbusVariantType{command}); - } + if (hostCommand) + { + crow::connections::systemBus->async_method_call( + [asyncResp, resetType](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + if (ec.value() == boost::asio::error::invalid_argument) + { + messages::actionParameterNotSupported( + asyncResp->res, resetType, "Reset"); + } + else + { + messages::internalError(asyncResp->res); + } + return; + } + messages::success(asyncResp->res); + }, + "xyz.openbmc_project.State.Host", + "/xyz/openbmc_project/state/host0", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.State.Host", "RequestedHostTransition", + dbus::utility::DbusVariantType{command}); + } + else + { + crow::connections::systemBus->async_method_call( + [asyncResp, resetType](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + if (ec.value() == boost::asio::error::invalid_argument) + { + messages::actionParameterNotSupported( + asyncResp->res, resetType, "Reset"); + } + else + { + messages::internalError(asyncResp->res); + } + return; + } + messages::success(asyncResp->res); + }, + "xyz.openbmc_project.State.Chassis", + "/xyz/openbmc_project/state/chassis0", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.State.Chassis", "RequestedPowerTransition", + dbus::utility::DbusVariantType{command}); + } }); } @@ -2862,134 +2822,127 @@ inline void requestRoutesSystems(App& app) */ BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/") .privileges(redfish::privileges::getComputerSystem) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#ComputerSystem.v1_16_0.ComputerSystem"; - asyncResp->res.jsonValue["Name"] = "system"; - asyncResp->res.jsonValue["Id"] = "system"; - asyncResp->res.jsonValue["SystemType"] = "Physical"; - asyncResp->res.jsonValue["Description"] = "Computer System"; - asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0; - asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] = - "Disabled"; - asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = - uint64_t(0); - asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] = - "Disabled"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system"; - - asyncResp->res.jsonValue["Processors"]["@odata.id"] = - "/redfish/v1/Systems/system/Processors"; - asyncResp->res.jsonValue["Memory"]["@odata.id"] = - "/redfish/v1/Systems/system/Memory"; - asyncResp->res.jsonValue["Storage"]["@odata.id"] = - "/redfish/v1/Systems/system/Storage"; - - asyncResp->res - .jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] = - "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"; - asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] - ["@Redfish.ActionInfo"] = - "/redfish/v1/Systems/system/ResetActionInfo"; - - asyncResp->res.jsonValue["LogServices"]["@odata.id"] = - "/redfish/v1/Systems/system/LogServices"; - asyncResp->res.jsonValue["Bios"]["@odata.id"] = - "/redfish/v1/Systems/system/Bios"; - - nlohmann::json::array_t managedBy; - nlohmann::json& manager = managedBy.emplace_back(); - manager["@odata.id"] = "/redfish/v1/Managers/bmc"; - asyncResp->res.jsonValue["Links"]["ManagedBy"] = - std::move(managedBy); - asyncResp->res.jsonValue["Status"]["Health"] = "OK"; - asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; - - // Fill in SerialConsole info - asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = - 15; - asyncResp->res - .jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = true; - - // TODO (Gunnar): Should look for obmc-console-ssh@2200.service - asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = - true; - asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200; - asyncResp->res - .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] = - "Press ~. to exit console"; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#ComputerSystem.v1_16_0.ComputerSystem"; + asyncResp->res.jsonValue["Name"] = "system"; + asyncResp->res.jsonValue["Id"] = "system"; + asyncResp->res.jsonValue["SystemType"] = "Physical"; + asyncResp->res.jsonValue["Description"] = "Computer System"; + asyncResp->res.jsonValue["ProcessorSummary"]["Count"] = 0; + asyncResp->res.jsonValue["ProcessorSummary"]["Status"]["State"] = + "Disabled"; + asyncResp->res.jsonValue["MemorySummary"]["TotalSystemMemoryGiB"] = + uint64_t(0); + asyncResp->res.jsonValue["MemorySummary"]["Status"]["State"] = + "Disabled"; + asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Systems/system"; + + asyncResp->res.jsonValue["Processors"]["@odata.id"] = + "/redfish/v1/Systems/system/Processors"; + asyncResp->res.jsonValue["Memory"]["@odata.id"] = + "/redfish/v1/Systems/system/Memory"; + asyncResp->res.jsonValue["Storage"]["@odata.id"] = + "/redfish/v1/Systems/system/Storage"; + + asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"]["target"] = + "/redfish/v1/Systems/system/Actions/ComputerSystem.Reset"; + asyncResp->res.jsonValue["Actions"]["#ComputerSystem.Reset"] + ["@Redfish.ActionInfo"] = + "/redfish/v1/Systems/system/ResetActionInfo"; + + asyncResp->res.jsonValue["LogServices"]["@odata.id"] = + "/redfish/v1/Systems/system/LogServices"; + asyncResp->res.jsonValue["Bios"]["@odata.id"] = + "/redfish/v1/Systems/system/Bios"; + + nlohmann::json::array_t managedBy; + nlohmann::json& manager = managedBy.emplace_back(); + manager["@odata.id"] = "/redfish/v1/Managers/bmc"; + asyncResp->res.jsonValue["Links"]["ManagedBy"] = std::move(managedBy); + asyncResp->res.jsonValue["Status"]["Health"] = "OK"; + asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; + + // Fill in SerialConsole info + asyncResp->res.jsonValue["SerialConsole"]["MaxConcurrentSessions"] = 15; + asyncResp->res.jsonValue["SerialConsole"]["IPMI"]["ServiceEnabled"] = + true; + + // TODO (Gunnar): Should look for obmc-console-ssh@2200.service + asyncResp->res.jsonValue["SerialConsole"]["SSH"]["ServiceEnabled"] = + true; + asyncResp->res.jsonValue["SerialConsole"]["SSH"]["Port"] = 2200; + asyncResp->res + .jsonValue["SerialConsole"]["SSH"]["HotKeySequenceDisplay"] = + "Press ~. to exit console"; #ifdef BMCWEB_ENABLE_KVM - // Fill in GraphicalConsole info - asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = - true; - asyncResp->res - .jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = 4; - asyncResp->res.jsonValue["GraphicalConsole"] - ["ConnectTypesSupported"] = {"KVMIP"}; + // Fill in GraphicalConsole info + asyncResp->res.jsonValue["GraphicalConsole"]["ServiceEnabled"] = true; + asyncResp->res.jsonValue["GraphicalConsole"]["MaxConcurrentSessions"] = + 4; + asyncResp->res + .jsonValue["GraphicalConsole"]["ConnectTypesSupported"] = {"KVMIP"}; #endif // BMCWEB_ENABLE_KVM - constexpr const std::array<const char*, 4> inventoryForSystems = { - "xyz.openbmc_project.Inventory.Item.Dimm", - "xyz.openbmc_project.Inventory.Item.Cpu", - "xyz.openbmc_project.Inventory.Item.Drive", - "xyz.openbmc_project.Inventory.Item.StorageController"}; + constexpr const std::array<const char*, 4> inventoryForSystems = { + "xyz.openbmc_project.Inventory.Item.Dimm", + "xyz.openbmc_project.Inventory.Item.Cpu", + "xyz.openbmc_project.Inventory.Item.Drive", + "xyz.openbmc_project.Inventory.Item.StorageController"}; - auto health = std::make_shared<HealthPopulate>(asyncResp); - crow::connections::systemBus->async_method_call( - [health](const boost::system::error_code ec, - const std::vector<std::string>& resp) { - if (ec) - { - // no inventory - return; - } + auto health = std::make_shared<HealthPopulate>(asyncResp); + crow::connections::systemBus->async_method_call( + [health](const boost::system::error_code ec, + const std::vector<std::string>& resp) { + if (ec) + { + // no inventory + return; + } - health->inventory = resp; - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", - int32_t(0), inventoryForSystems); - - health->populate(); - - 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"] = "/redfish/v1/Chassis/" + chassisId; - aRsp->res.jsonValue["Links"]["Chassis"] = - std::move(chassisArray); - }); + health->inventory = resp; + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", + int32_t(0), inventoryForSystems); + + health->populate(); + + 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"] = "/redfish/v1/Chassis/" + chassisId; + aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray); + }); - getLocationIndicatorActive(asyncResp); - // TODO (Gunnar): Remove IndicatorLED after enough time has passed - getIndicatorLedState(asyncResp); - getComputerSystem(asyncResp, health); - getHostState(asyncResp); - getBootProperties(asyncResp); - getBootProgress(asyncResp); - getPCIeDeviceList(asyncResp, "PCIeDevices"); - getHostWatchdogTimer(asyncResp); - getPowerRestorePolicy(asyncResp); - getAutomaticRetry(asyncResp); - getLastResetTime(asyncResp); + getLocationIndicatorActive(asyncResp); + // TODO (Gunnar): Remove IndicatorLED after enough time has passed + getIndicatorLedState(asyncResp); + getComputerSystem(asyncResp, health); + getHostState(asyncResp); + getBootProperties(asyncResp); + getBootProgress(asyncResp); + getPCIeDeviceList(asyncResp, "PCIeDevices"); + getHostWatchdogTimer(asyncResp); + getPowerRestorePolicy(asyncResp); + getAutomaticRetry(asyncResp); + getLastResetTime(asyncResp); #ifdef BMCWEB_ENABLE_REDFISH_PROVISIONING_FEATURE - getProvisioningStatus(asyncResp); + getProvisioningStatus(asyncResp); #endif - getTrustedModuleRequiredToBoot(asyncResp); - getPowerMode(asyncResp); - getIdlePowerSaver(asyncResp); + getTrustedModuleRequiredToBoot(asyncResp); + getPowerMode(asyncResp); + getIdlePowerSaver(asyncResp); }); BMCWEB_ROUTE(app, "/redfish/v1/Systems/system/") @@ -2997,29 +2950,29 @@ inline void requestRoutesSystems(App& app) .methods(boost::beast::http::verb::patch)( [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - std::optional<bool> locationIndicatorActive; - std::optional<std::string> indicatorLed; - std::optional<std::string> assetTag; - std::optional<std::string> powerRestorePolicy; - std::optional<std::string> powerMode; - std::optional<bool> wdtEnable; - std::optional<std::string> wdtTimeOutAction; - std::optional<std::string> bootSource; - std::optional<std::string> bootType; - std::optional<std::string> bootEnable; - std::optional<std::string> bootAutomaticRetry; - std::optional<bool> bootTrustedModuleRequired; - std::optional<bool> ipsEnable; - std::optional<uint8_t> ipsEnterUtil; - std::optional<uint64_t> ipsEnterTime; - std::optional<uint8_t> ipsExitUtil; - std::optional<uint64_t> ipsExitTime; - - // clang-format off + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::optional<bool> locationIndicatorActive; + std::optional<std::string> indicatorLed; + std::optional<std::string> assetTag; + std::optional<std::string> powerRestorePolicy; + std::optional<std::string> powerMode; + std::optional<bool> wdtEnable; + std::optional<std::string> wdtTimeOutAction; + std::optional<std::string> bootSource; + std::optional<std::string> bootType; + std::optional<std::string> bootEnable; + std::optional<std::string> bootAutomaticRetry; + std::optional<bool> bootTrustedModuleRequired; + std::optional<bool> ipsEnable; + std::optional<uint8_t> ipsEnterUtil; + std::optional<uint64_t> ipsEnterTime; + std::optional<uint8_t> ipsExitUtil; + std::optional<uint64_t> ipsExitTime; + + // clang-format off if (!json_util::readJsonPatch( req, asyncResp->res, "IndicatorLED", indicatorLed, @@ -3042,70 +2995,67 @@ inline void requestRoutesSystems(App& app) { return; } - // clang-format on + // clang-format on - asyncResp->res.result(boost::beast::http::status::no_content); + asyncResp->res.result(boost::beast::http::status::no_content); - if (assetTag) - { - setAssetTag(asyncResp, *assetTag); - } + if (assetTag) + { + setAssetTag(asyncResp, *assetTag); + } - if (wdtEnable || wdtTimeOutAction) - { - setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction); - } + if (wdtEnable || wdtTimeOutAction) + { + setWDTProperties(asyncResp, wdtEnable, wdtTimeOutAction); + } - if (bootSource || bootType || bootEnable) - { - setBootProperties(asyncResp, bootSource, bootType, - bootEnable); - } - if (bootAutomaticRetry) - { - setAutomaticRetry(asyncResp, *bootAutomaticRetry); - } + if (bootSource || bootType || bootEnable) + { + setBootProperties(asyncResp, bootSource, bootType, bootEnable); + } + if (bootAutomaticRetry) + { + setAutomaticRetry(asyncResp, *bootAutomaticRetry); + } - if (bootTrustedModuleRequired) - { - setTrustedModuleRequiredToBoot(asyncResp, - *bootTrustedModuleRequired); - } + if (bootTrustedModuleRequired) + { + setTrustedModuleRequiredToBoot(asyncResp, + *bootTrustedModuleRequired); + } - if (locationIndicatorActive) - { - setLocationIndicatorActive(asyncResp, - *locationIndicatorActive); - } + if (locationIndicatorActive) + { + setLocationIndicatorActive(asyncResp, *locationIndicatorActive); + } - // TODO (Gunnar): Remove IndicatorLED after enough time has - // passed - if (indicatorLed) - { - setIndicatorLedState(asyncResp, *indicatorLed); - asyncResp->res.addHeader( - boost::beast::http::field::warning, - "299 - \"IndicatorLED is deprecated. Use " - "LocationIndicatorActive instead.\""); - } + // TODO (Gunnar): Remove IndicatorLED after enough time has + // passed + if (indicatorLed) + { + setIndicatorLedState(asyncResp, *indicatorLed); + asyncResp->res.addHeader(boost::beast::http::field::warning, + "299 - \"IndicatorLED is deprecated. Use " + "LocationIndicatorActive instead.\""); + } - if (powerRestorePolicy) - { - setPowerRestorePolicy(asyncResp, *powerRestorePolicy); - } + if (powerRestorePolicy) + { + setPowerRestorePolicy(asyncResp, *powerRestorePolicy); + } - if (powerMode) - { - setPowerMode(asyncResp, *powerMode); - } + if (powerMode) + { + setPowerMode(asyncResp, *powerMode); + } - if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || - ipsExitTime) - { - setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, - ipsEnterTime, ipsExitUtil, ipsExitTime); - } - }); + if (ipsEnable || ipsEnterUtil || ipsEnterTime || ipsExitUtil || + ipsExitTime) + { + setIdlePowerSaver(asyncResp, ipsEnable, ipsEnterUtil, ipsEnterTime, + ipsExitUtil, ipsExitTime); + } + }); } /** @@ -3122,29 +3072,29 @@ inline void requestRoutesSystemResetActionInfo(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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Systems/system/ResetActionInfo"; - asyncResp->res.jsonValue["@odata.type"] = - "#ActionInfo.v1_1_2.ActionInfo"; - asyncResp->res.jsonValue["Name"] = "Reset Action Info"; - asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; - asyncResp->res.jsonValue["Parameters"]["Name"] = "ResetType"; - asyncResp->res.jsonValue["Parameters"]["Required"] = true; - asyncResp->res.jsonValue["Parameters"]["DataType"] = "String"; - asyncResp->res.jsonValue["Parameters"]["AllowableValues"] = { - "On", - "ForceOff", - "ForceOn", - "ForceRestart", - "GracefulRestart", - "GracefulShutdown", - "PowerCycle", - "Nmi"}; - }); + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Systems/system/ResetActionInfo"; + asyncResp->res.jsonValue["@odata.type"] = + "#ActionInfo.v1_1_2.ActionInfo"; + asyncResp->res.jsonValue["Name"] = "Reset Action Info"; + asyncResp->res.jsonValue["Id"] = "ResetActionInfo"; + asyncResp->res.jsonValue["Parameters"]["Name"] = "ResetType"; + asyncResp->res.jsonValue["Parameters"]["Required"] = true; + asyncResp->res.jsonValue["Parameters"]["DataType"] = "String"; + asyncResp->res.jsonValue["Parameters"]["AllowableValues"] = { + "On", + "ForceOff", + "ForceOn", + "ForceRestart", + "GracefulRestart", + "GracefulShutdown", + "PowerCycle", + "Nmi"}; + }); } } // namespace redfish diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp index 0c2eee410a..fc334a93a1 100644 --- a/redfish-core/lib/task.hpp +++ b/redfish-core/lib/task.hpp @@ -169,26 +169,26 @@ 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::message 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::message 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(const std::string_view state, size_t index) @@ -272,24 +272,24 @@ struct TaskData : std::enable_shared_from_this<TaskData> static_cast<sdbusplus::bus::bus&>(*crow::connections::systemBus), matchStr, [self = shared_from_this()](sdbusplus::message::message& 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); @@ -325,39 +325,37 @@ inline void requestRoutesTaskMonitor(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& strParam) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - auto find = std::find_if( - task::tasks.begin(), task::tasks.end(), - [&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, "Monitor", - strParam); - return; - } - std::shared_ptr<task::TaskData>& ptr = *find; - // monitor expires after 204 - if (ptr->gave204) - { - messages::resourceNotFound(asyncResp->res, "Monitor", - strParam); - return; - } - ptr->populateResp(asyncResp->res); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + auto find = std::find_if( + task::tasks.begin(), task::tasks.end(), + [&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, "Monitor", strParam); + return; + } + std::shared_ptr<task::TaskData>& ptr = *find; + // monitor expires after 204 + if (ptr->gave204) + { + messages::resourceNotFound(asyncResp->res, "Monitor", strParam); + return; + } + ptr->populateResp(asyncResp->res); + }); } inline void requestRoutesTask(App& app) @@ -368,70 +366,63 @@ 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->res)) - { - return; - } - auto find = std::find_if( - task::tasks.begin(), task::tasks.end(), - [&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, "Tasks", - strParam); - return; - } - - 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"] = - crow::utility::getDateTimeStdtime(ptr->startTime); - if (ptr->endTime) - { - asyncResp->res.jsonValue["EndTime"] = - crow::utility::getDateTimeStdtime(*(ptr->endTime)); - } - asyncResp->res.jsonValue["TaskStatus"] = ptr->status; - asyncResp->res.jsonValue["Messages"] = ptr->messages; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/TaskService/Tasks/" + strParam; - if (!ptr->gave204) - { - asyncResp->res.jsonValue["TaskMonitor"] = - "/redfish/v1/TaskService/Tasks/" + strParam + - "/Monitor"; - } - 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->res)) + { + return; + } + auto find = std::find_if( + task::tasks.begin(), task::tasks.end(), + [&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, "Tasks", strParam); + return; + } + + 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"] = + crow::utility::getDateTimeStdtime(ptr->startTime); + if (ptr->endTime) + { + asyncResp->res.jsonValue["EndTime"] = + crow::utility::getDateTimeStdtime(*(ptr->endTime)); + } + asyncResp->res.jsonValue["TaskStatus"] = ptr->status; + asyncResp->res.jsonValue["Messages"] = ptr->messages; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/TaskService/Tasks/" + strParam; + if (!ptr->gave204) + { + asyncResp->res.jsonValue["TaskMonitor"] = + "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor"; + } + 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; + }); } inline void requestRoutesTaskCollection(App& app) @@ -441,31 +432,29 @@ 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->res)) - { - 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 - } - members.emplace_back(nlohmann::json{ - {"@odata.id", "/redfish/v1/TaskService/Tasks/" + - std::to_string(task->index)}}); - } - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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 + } + members.emplace_back( + nlohmann::json{{"@odata.id", "/redfish/v1/TaskService/Tasks/" + + std::to_string(task->index)}}); + } + }); } inline void requestRoutesTaskService(App& app) @@ -475,31 +464,28 @@ 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->res)) - { - 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"] = - crow::utility::getDateTimeOffsetNow().first; - asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = - "Oldest"; - - asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = - true; - - auto health = std::make_shared<HealthPopulate>(asyncResp); - health->populate(); - 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->res)) + { + 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"] = + crow::utility::getDateTimeOffsetNow().first; + asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest"; + + asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true; + + auto health = std::make_shared<HealthPopulate>(asyncResp); + health->populate(); + asyncResp->res.jsonValue["Status"]["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 7cdc497a65..a5cc4c7c5a 100644 --- a/redfish-core/lib/telemetry_service.hpp +++ b/redfish-core/lib/telemetry_service.hpp @@ -34,45 +34,44 @@ inline void handleTelemetryServiceGet( crow::connections::systemBus->async_method_call( [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"] = "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"] = "Enabled"; - const size_t* maxReports = nullptr; - const uint64_t* minInterval = nullptr; - for (const auto& [key, var] : ret) + const size_t* maxReports = nullptr; + const uint64_t* minInterval = nullptr; + for (const auto& [key, var] : ret) + { + if (key == "MaxReports") { - if (key == "MaxReports") - { - maxReports = std::get_if<size_t>(&var); - } - else if (key == "MinInterval") - { - minInterval = std::get_if<uint64_t>(&var); - } + maxReports = std::get_if<size_t>(&var); } - if (maxReports == nullptr || minInterval == nullptr) + else if (key == "MinInterval") { - BMCWEB_LOG_ERROR - << "Property type mismatch or property is missing"; - messages::internalError(asyncResp->res); - return; + minInterval = std::get_if<uint64_t>(&var); } + } + if (maxReports == nullptr || minInterval == nullptr) + { + BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; + messages::internalError(asyncResp->res); + return; + } - asyncResp->res.jsonValue["MaxReports"] = *maxReports; - asyncResp->res.jsonValue["MinCollectionInterval"] = - time_utils::toDurationString(std::chrono::milliseconds( - static_cast<time_t>(*minInterval))); + asyncResp->res.jsonValue["MaxReports"] = *maxReports; + asyncResp->res.jsonValue["MinCollectionInterval"] = + time_utils::toDurationString( + std::chrono::milliseconds(static_cast<time_t>(*minInterval))); }, telemetry::service, "/xyz/openbmc_project/Telemetry/Reports", "org.freedesktop.DBus.Properties", "GetAll", diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp index e58e86fa4b..021134b8d4 100644 --- a/redfish-core/lib/thermal.hpp +++ b/redfish-core/lib/thermal.hpp @@ -32,18 +32,18 @@ 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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + 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, + sensors::node::thermal); - // 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,45 +51,43 @@ 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->res)) - { - return; - } + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - std::optional<std::vector<nlohmann::json>> - temperatureCollections; - std::optional<std::vector<nlohmann::json>> fanCollections; - std::unordered_map<std::string, std::vector<nlohmann::json>> - allCollections; + std::optional<std::vector<nlohmann::json>> temperatureCollections; + std::optional<std::vector<nlohmann::json>> fanCollections; + std::unordered_map<std::string, std::vector<nlohmann::json>> + 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, + sensors::node::thermal); - 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/trigger.hpp b/redfish-core/lib/trigger.hpp index cdd58b830e..1c5739ad6a 100644 --- a/redfish-core/lib/trigger.hpp +++ b/redfish-core/lib/trigger.hpp @@ -286,20 +286,19 @@ 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->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#TriggersCollection.TriggersCollection"; - asyncResp->res.jsonValue["@odata.id"] = telemetry::triggerUri; - asyncResp->res.jsonValue["Name"] = "Triggers Collection"; - const std::vector<const char*> interfaces{ - telemetry::triggerInterface}; - collection_util::getCollectionMembers( - asyncResp, telemetry::triggerUri, interfaces, - "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService"); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#TriggersCollection.TriggersCollection"; + asyncResp->res.jsonValue["@odata.id"] = telemetry::triggerUri; + asyncResp->res.jsonValue["Name"] = "Triggers Collection"; + const std::vector<const char*> interfaces{telemetry::triggerInterface}; + collection_util::getCollectionMembers( + asyncResp, telemetry::triggerUri, interfaces, + "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService"); + }); } inline void requestRoutesTrigger(App& app) @@ -310,40 +309,37 @@ 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->res)) - { - return; - } - crow::connections::systemBus->async_method_call( - [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); - } - }, - telemetry::service, telemetry::getDbusTriggerPath(id), - "org.freedesktop.DBus.Properties", "GetAll", - telemetry::triggerInterface); - }); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + crow::connections::systemBus->async_method_call( + [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); + } + }, + telemetry::service, telemetry::getDbusTriggerPath(id), + "org.freedesktop.DBus.Properties", "GetAll", + telemetry::triggerInterface); + }); BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/<str>/") .privileges(redfish::privileges::deleteTriggers) @@ -351,35 +347,32 @@ 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->res)) - { - 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->res)) + { + 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 c8b13816ed..da9e1de49b 100644 --- a/redfish-core/lib/update_service.hpp +++ b/redfish-core/lib/update_service.hpp @@ -47,11 +47,11 @@ inline static void activateImage(const std::string& objPath, BMCWEB_LOG_DEBUG << "Activate image for " << objPath << " " << service; crow::connections::systemBus->async_method_call( [](const boost::system::error_code errorCode) { - if (errorCode) - { - BMCWEB_LOG_DEBUG << "error_code = " << errorCode; - BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); - } + if (errorCode) + { + BMCWEB_LOG_DEBUG << "error_code = " << errorCode; + BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); + } }, service, objPath, "org.freedesktop.DBus.Properties", "Set", "xyz.openbmc_project.Software.Activation", "RequestedActivation", @@ -86,174 +86,162 @@ static void const std::vector< std::pair<std::string, std::vector<std::string>>>& objInfo) mutable { - if (errorCode) + if (errorCode) + { + BMCWEB_LOG_DEBUG << "error_code = " << errorCode; + BMCWEB_LOG_DEBUG << "error msg = " << errorCode.message(); + if (asyncResp) { - BMCWEB_LOG_DEBUG << "error_code = " << errorCode; - BMCWEB_LOG_DEBUG << "error msg = " - << errorCode.message(); - if (asyncResp) - { - messages::internalError(asyncResp->res); - } - cleanUp(); - return; + messages::internalError(asyncResp->res); } - // Ensure we only got one service back - if (objInfo.size() != 1) + cleanUp(); + return; + } + // Ensure we only got one service back + if (objInfo.size() != 1) + { + BMCWEB_LOG_ERROR << "Invalid Object Size " + << objInfo.size(); + if (asyncResp) { - BMCWEB_LOG_ERROR << "Invalid Object Size " - << objInfo.size(); - if (asyncResp) + messages::internalError(asyncResp->res); + } + cleanUp(); + return; + } + // cancel timer only when + // xyz.openbmc_project.Software.Activation interface + // is added + fwAvailableTimer = nullptr; + + activateImage(objPath.str, objInfo[0].first); + if (asyncResp) + { + std::shared_ptr<task::TaskData> task = + task::TaskData::createTask( + [](boost::system::error_code ec, + sdbusplus::message::message& msg, + const std::shared_ptr<task::TaskData>& + taskData) { + if (ec) { - messages::internalError(asyncResp->res); + return task::completed; } - cleanUp(); - return; - } - // cancel timer only when - // xyz.openbmc_project.Software.Activation interface - // is added - fwAvailableTimer = nullptr; - activateImage(objPath.str, objInfo[0].first); - if (asyncResp) - { - std::shared_ptr<task::TaskData> task = - task::TaskData::createTask( - [](boost::system::error_code ec, - sdbusplus::message::message& msg, - const std::shared_ptr<task::TaskData>& - taskData) { - if (ec) + std::string iface; + dbus::utility::DBusPropertiesMap values; + + std::string index = std::to_string(taskData->index); + msg.read(iface, values); + + if (iface == "xyz.openbmc_project.Software.Activation") + { + std::string* state = nullptr; + for (const auto& property : values) + { + if (property.first == "Activation") + { + const std::string* state = + std::get_if<std::string>( + &property.second); + if (state == nullptr) { + taskData->messages.emplace_back( + messages::internalError()); return task::completed; } + } + } - std::string iface; - dbus::utility::DBusPropertiesMap values; + if (state == nullptr) + { + return !task::completed; + } - std::string index = - std::to_string(taskData->index); - msg.read(iface, values); + if (boost::ends_with(*state, "Invalid") || + boost::ends_with(*state, "Failed")) + { + taskData->state = "Exception"; + taskData->status = "Warning"; + taskData->messages.emplace_back( + messages::taskAborted(index)); + return task::completed; + } - if (iface == - "xyz.openbmc_project.Software.Activation") - { - std::string* state = nullptr; - for (const auto& property : values) - { - if (property.first == "Activation") - { - const std::string* state = - std::get_if<std::string>( - &property.second); - if (state == nullptr) - { - taskData->messages - .emplace_back( - messages:: - internalError()); - return task::completed; - } - } - } - - if (state == nullptr) - { - return !task::completed; - } - - if (boost::ends_with(*state, - "Invalid") || - boost::ends_with(*state, "Failed")) - { - taskData->state = "Exception"; - taskData->status = "Warning"; - taskData->messages.emplace_back( - messages::taskAborted(index)); - return task::completed; - } - - if (boost::ends_with(*state, "Staged")) - { - taskData->state = "Stopping"; - taskData->messages.emplace_back( - messages::taskPaused(index)); - - // its staged, set a long timer to - // allow them time to complete the - // update (probably cycle the - // system) if this expires then - // task will be cancelled - taskData->extendTimer( - std::chrono::hours(5)); - return !task::completed; - } - - if (boost::ends_with(*state, "Active")) - { - taskData->messages.emplace_back( - messages::taskCompletedOK( - index)); - taskData->state = "Completed"; - return task::completed; - } - } - else if ( - iface == - "xyz.openbmc_project.Software.ActivationProgress") - { + if (boost::ends_with(*state, "Staged")) + { + taskData->state = "Stopping"; + taskData->messages.emplace_back( + messages::taskPaused(index)); + + // its staged, set a long timer to + // allow them time to complete the + // update (probably cycle the + // system) if this expires then + // task will be cancelled + taskData->extendTimer(std::chrono::hours(5)); + return !task::completed; + } + + if (boost::ends_with(*state, "Active")) + { + taskData->messages.emplace_back( + messages::taskCompletedOK(index)); + taskData->state = "Completed"; + return task::completed; + } + } + else if ( + iface == + "xyz.openbmc_project.Software.ActivationProgress") + { - const uint8_t* progress = nullptr; - for (const auto& property : values) - { - if (property.first == "Progress") - { - const std::string* progress = - std::get_if<std::string>( - &property.second); - if (progress == nullptr) - { - taskData->messages - .emplace_back( - messages:: - internalError()); - return task::completed; - } - } - } - - if (progress == nullptr) - { - return !task::completed; - } - taskData->percentComplete = - static_cast<int>(*progress); + const uint8_t* progress = nullptr; + for (const auto& property : values) + { + if (property.first == "Progress") + { + const std::string* progress = + std::get_if<std::string>( + &property.second); + if (progress == nullptr) + { taskData->messages.emplace_back( - messages::taskProgressChanged( - index, static_cast<size_t>( - *progress))); - - // if we're getting status updates it's - // still alive, update timer - taskData->extendTimer( - std::chrono::minutes(5)); + messages::internalError()); + return task::completed; } + } + } - // as firmware update often results in a - // reboot, the task may never "complete" - // unless it is an error - - return !task::completed; - }, - "type='signal',interface='org.freedesktop.DBus.Properties'," - "member='PropertiesChanged',path='" + - objPath.str + "'"); - task->startTimer(std::chrono::minutes(5)); - task->populateResp(asyncResp->res); - task->payload.emplace(std::move(payload)); - } - fwUpdateInProgress = false; + if (progress == nullptr) + { + return !task::completed; + } + taskData->percentComplete = + static_cast<int>(*progress); + taskData->messages.emplace_back( + messages::taskProgressChanged( + index, static_cast<size_t>(*progress))); + + // if we're getting status updates it's + // still alive, update timer + taskData->extendTimer(std::chrono::minutes(5)); + } + + // as firmware update often results in a + // reboot, the task may never "complete" + // unless it is an error + + return !task::completed; + }, + "type='signal',interface='org.freedesktop.DBus.Properties'," + "member='PropertiesChanged',path='" + + objPath.str + "'"); + task->startTimer(std::chrono::minutes(5)); + task->populateResp(asyncResp->res); + task->payload.emplace(std::move(payload)); + } + fwUpdateInProgress = false; }, "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", @@ -288,29 +276,28 @@ static void monitorForSoftwareAvailable( fwAvailableTimer->async_wait( [asyncResp](const boost::system::error_code& ec) { - cleanUp(); - if (ec == boost::asio::error::operation_aborted) - { - // expected, we were canceled before the timer completed. - return; - } - BMCWEB_LOG_ERROR - << "Timed out waiting for firmware object being created"; - BMCWEB_LOG_ERROR - << "FW image may has already been uploaded to server"; - if (ec) - { - BMCWEB_LOG_ERROR << "Async_wait failed" << ec; - return; - } - if (asyncResp) - { - redfish::messages::internalError(asyncResp->res); - } - }); + cleanUp(); + if (ec == boost::asio::error::operation_aborted) + { + // expected, we were canceled before the timer completed. + return; + } + BMCWEB_LOG_ERROR + << "Timed out waiting for firmware object being created"; + BMCWEB_LOG_ERROR << "FW image may has already been uploaded to server"; + if (ec) + { + BMCWEB_LOG_ERROR << "Async_wait failed" << ec; + return; + } + if (asyncResp) + { + redfish::messages::internalError(asyncResp->res); + } + }); task::Payload payload(req); - auto callback = [asyncResp, - payload](sdbusplus::message::message& m) mutable { + auto callback = + [asyncResp, payload](sdbusplus::message::message& m) mutable { BMCWEB_LOG_DEBUG << "Match fired"; softwareInterfaceAdded(asyncResp, m, std::move(payload)); }; @@ -329,80 +316,79 @@ static void monitorForSoftwareAvailable( "member='InterfacesAdded'," "path='/xyz/openbmc_project/logging'", [asyncResp, url](sdbusplus::message::message& m) { - std::vector< - std::pair<std::string, dbus::utility::DBusPropertiesMap>> - interfacesProperties; - sdbusplus::message::object_path objPath; - m.read(objPath, interfacesProperties); - BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; - for (const std::pair<std::string, dbus::utility::DBusPropertiesMap>& - interface : interfacesProperties) + std::vector<std::pair<std::string, dbus::utility::DBusPropertiesMap>> + interfacesProperties; + sdbusplus::message::object_path objPath; + m.read(objPath, interfacesProperties); + BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; + for (const std::pair<std::string, dbus::utility::DBusPropertiesMap>& + interface : interfacesProperties) + { + if (interface.first == "xyz.openbmc_project.Logging.Entry") { - if (interface.first == "xyz.openbmc_project.Logging.Entry") + for (const std::pair<std::string, + dbus::utility::DbusVariantType>& value : + interface.second) { - for (const std::pair<std::string, - dbus::utility::DbusVariantType>& - value : interface.second) + if (value.first != "Message") { - if (value.first != "Message") - { - continue; - } - const std::string* type = - std::get_if<std::string>(&value.second); - if (type == nullptr) - { - // if this was our message, timeout will cover it - return; - } - fwAvailableTimer = nullptr; - if (*type == - "xyz.openbmc_project.Software.Image.Error.UnTarFailure") - { - redfish::messages::invalidUpload( - asyncResp->res, url, "Invalid archive"); - } - else if (*type == - "xyz.openbmc_project.Software.Image.Error." - "ManifestFileFailure") - { - redfish::messages::invalidUpload( - asyncResp->res, url, "Invalid manifest"); - } - else if ( - *type == - "xyz.openbmc_project.Software.Image.Error.ImageFailure") - { - redfish::messages::invalidUpload( - asyncResp->res, url, "Invalid image format"); - } - else if ( - *type == - "xyz.openbmc_project.Software.Version.Error.AlreadyExists") - { - redfish::messages::invalidUpload( - asyncResp->res, url, - "Image version already exists"); - - redfish::messages::resourceAlreadyExists( - asyncResp->res, - "UpdateService.v1_5_0.UpdateService", "Version", - "uploaded version"); - } - else if ( - *type == - "xyz.openbmc_project.Software.Image.Error.BusyFailure") - { - redfish::messages::resourceExhaustion( - asyncResp->res, url); - } - else - { - redfish::messages::internalError(asyncResp->res); - } + continue; + } + const std::string* type = + std::get_if<std::string>(&value.second); + if (type == nullptr) + { + // if this was our message, timeout will cover it + return; + } + fwAvailableTimer = nullptr; + if (*type == + "xyz.openbmc_project.Software.Image.Error.UnTarFailure") + { + redfish::messages::invalidUpload(asyncResp->res, url, + "Invalid archive"); + } + else if (*type == + "xyz.openbmc_project.Software.Image.Error." + "ManifestFileFailure") + { + redfish::messages::invalidUpload(asyncResp->res, url, + "Invalid manifest"); + } + else if ( + *type == + "xyz.openbmc_project.Software.Image.Error.ImageFailure") + { + redfish::messages::invalidUpload( + asyncResp->res, url, "Invalid image format"); + } + else if ( + *type == + "xyz.openbmc_project.Software.Version.Error.AlreadyExists") + { + redfish::messages::invalidUpload( + asyncResp->res, url, + "Image version already exists"); + + redfish::messages::resourceAlreadyExists( + asyncResp->res, + "UpdateService.v1_5_0.UpdateService", "Version", + "uploaded version"); + } + else if ( + *type == + "xyz.openbmc_project.Software.Image.Error.BusyFailure") + { + redfish::messages::resourceExhaustion(asyncResp->res, + url); + } + else + { + redfish::messages::internalError(asyncResp->res); } } } + } }); } @@ -415,125 +401,121 @@ inline void requestRoutesUpdateServiceActionsSimpleUpdate(App& app) BMCWEB_ROUTE( app, "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate/") .privileges(redfish::privileges::postUpdateService) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } - std::optional<std::string> transferProtocol; - std::string imageURI; + std::optional<std::string> transferProtocol; + std::string imageURI; - BMCWEB_LOG_DEBUG << "Enter UpdateService.SimpleUpdate doPost"; + BMCWEB_LOG_DEBUG << "Enter UpdateService.SimpleUpdate doPost"; - // User can pass in both TransferProtocol and ImageURI parameters or - // they can pass in just the ImageURI with the transfer protocol - // embedded within it. - // 1) TransferProtocol:TFTP ImageURI:1.1.1.1/myfile.bin - // 2) ImageURI:tftp://1.1.1.1/myfile.bin + // User can pass in both TransferProtocol and ImageURI parameters or + // they can pass in just the ImageURI with the transfer protocol + // embedded within it. + // 1) TransferProtocol:TFTP ImageURI:1.1.1.1/myfile.bin + // 2) ImageURI:tftp://1.1.1.1/myfile.bin - if (!json_util::readJsonAction(req, asyncResp->res, - "TransferProtocol", transferProtocol, - "ImageURI", imageURI)) - { - BMCWEB_LOG_DEBUG - << "Missing TransferProtocol or ImageURI parameter"; - return; - } - if (!transferProtocol) - { - // Must be option 2 - // Verify ImageURI has transfer protocol in it - size_t separator = imageURI.find(':'); - if ((separator == std::string::npos) || - ((separator + 1) > imageURI.size())) - { - messages::actionParameterValueTypeError( - asyncResp->res, imageURI, "ImageURI", - "UpdateService.SimpleUpdate"); - BMCWEB_LOG_ERROR << "ImageURI missing transfer protocol: " - << imageURI; - return; - } - transferProtocol = imageURI.substr(0, separator); - // Ensure protocol is upper case for a common comparison path - // below - boost::to_upper(*transferProtocol); - BMCWEB_LOG_DEBUG << "Encoded transfer protocol " - << *transferProtocol; - - // Adjust imageURI to not have the protocol on it for parsing - // below - // ex. tftp://1.1.1.1/myfile.bin -> 1.1.1.1/myfile.bin - imageURI = imageURI.substr(separator + 3); - BMCWEB_LOG_DEBUG << "Adjusted imageUri " << imageURI; - } - - // OpenBMC currently only supports TFTP - if (*transferProtocol != "TFTP") - { - messages::actionParameterNotSupported( - asyncResp->res, "TransferProtocol", - "UpdateService.SimpleUpdate"); - BMCWEB_LOG_ERROR << "Request incorrect protocol parameter: " - << *transferProtocol; - return; - } - - // Format should be <IP or Hostname>/<file> for imageURI - size_t separator = imageURI.find('/'); + if (!json_util::readJsonAction(req, asyncResp->res, "TransferProtocol", + transferProtocol, "ImageURI", imageURI)) + { + BMCWEB_LOG_DEBUG + << "Missing TransferProtocol or ImageURI parameter"; + return; + } + if (!transferProtocol) + { + // Must be option 2 + // Verify ImageURI has transfer protocol in it + size_t separator = imageURI.find(':'); if ((separator == std::string::npos) || ((separator + 1) > imageURI.size())) { messages::actionParameterValueTypeError( asyncResp->res, imageURI, "ImageURI", "UpdateService.SimpleUpdate"); - BMCWEB_LOG_ERROR << "Invalid ImageURI: " << imageURI; + BMCWEB_LOG_ERROR << "ImageURI missing transfer protocol: " + << imageURI; return; } + transferProtocol = imageURI.substr(0, separator); + // Ensure protocol is upper case for a common comparison path + // below + boost::to_upper(*transferProtocol); + BMCWEB_LOG_DEBUG << "Encoded transfer protocol " + << *transferProtocol; + + // Adjust imageURI to not have the protocol on it for parsing + // below + // ex. tftp://1.1.1.1/myfile.bin -> 1.1.1.1/myfile.bin + imageURI = imageURI.substr(separator + 3); + BMCWEB_LOG_DEBUG << "Adjusted imageUri " << imageURI; + } - std::string tftpServer = imageURI.substr(0, separator); - std::string fwFile = imageURI.substr(separator + 1); - BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile; - - // Setup callback for when new software detected - // Give TFTP 10 minutes to complete - monitorForSoftwareAvailable( - asyncResp, req, - "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate", - 600); + // OpenBMC currently only supports TFTP + if (*transferProtocol != "TFTP") + { + messages::actionParameterNotSupported(asyncResp->res, + "TransferProtocol", + "UpdateService.SimpleUpdate"); + BMCWEB_LOG_ERROR << "Request incorrect protocol parameter: " + << *transferProtocol; + return; + } - // 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); + // Format should be <IP or Hostname>/<file> for imageURI + size_t separator = imageURI.find('/'); + if ((separator == std::string::npos) || + ((separator + 1) > imageURI.size())) + { + messages::actionParameterValueTypeError( + asyncResp->res, imageURI, "ImageURI", + "UpdateService.SimpleUpdate"); + BMCWEB_LOG_ERROR << "Invalid ImageURI: " << imageURI; + return; + } - // 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", fwFile, - tftpServer); + std::string tftpServer = imageURI.substr(0, separator); + std::string fwFile = imageURI.substr(separator + 1); + BMCWEB_LOG_DEBUG << "Server: " << tftpServer + " File: " << fwFile; + + // 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", fwFile, tftpServer); - BMCWEB_LOG_DEBUG << "Exit UpdateService.SimpleUpdate doPost"; + BMCWEB_LOG_DEBUG << "Exit UpdateService.SimpleUpdate doPost"; }); } @@ -565,168 +547,158 @@ inline void requestRoutesUpdateService(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") .privileges(redfish::privileges::getUpdateService) - .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - asyncResp->res.jsonValue["@odata.type"] = - "#UpdateService.v1_5_0.UpdateService"; - asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService"; - asyncResp->res.jsonValue["Id"] = "UpdateService"; - asyncResp->res.jsonValue["Description"] = - "Service for Software Update"; - asyncResp->res.jsonValue["Name"] = "Update Service"; + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#UpdateService.v1_5_0.UpdateService"; + asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/UpdateService"; + asyncResp->res.jsonValue["Id"] = "UpdateService"; + asyncResp->res.jsonValue["Description"] = "Service for Software Update"; + asyncResp->res.jsonValue["Name"] = "Update Service"; #ifdef BMCWEB_ENABLE_REDFISH_UPDATESERVICE_OLD_POST_URL - // See note about later on in this file about why this is neccesary - // This is "Wrong" per the standard, but is done temporarily to - // avoid noise in failing tests as people transition to having this - // option disabled - asyncResp->res.addHeader(boost::beast::http::field::allow, - "GET, PATCH, HEAD"); + // See note about later on in this file about why this is neccesary + // This is "Wrong" per the standard, but is done temporarily to + // avoid noise in failing tests as people transition to having this + // option disabled + asyncResp->res.addHeader(boost::beast::http::field::allow, + "GET, PATCH, HEAD"); #endif - asyncResp->res.jsonValue["HttpPushUri"] = - "/redfish/v1/UpdateService/update"; + asyncResp->res.jsonValue["HttpPushUri"] = + "/redfish/v1/UpdateService/update"; - // UpdateService cannot be disabled - asyncResp->res.jsonValue["ServiceEnabled"] = true; - asyncResp->res.jsonValue["FirmwareInventory"]["@odata.id"] = - "/redfish/v1/UpdateService/FirmwareInventory"; - // Get the MaxImageSizeBytes - asyncResp->res.jsonValue["MaxImageSizeBytes"] = - bmcwebHttpReqBodyLimitMb * 1024 * 1024; + // UpdateService cannot be disabled + asyncResp->res.jsonValue["ServiceEnabled"] = true; + asyncResp->res.jsonValue["FirmwareInventory"]["@odata.id"] = + "/redfish/v1/UpdateService/FirmwareInventory"; + // Get the MaxImageSizeBytes + asyncResp->res.jsonValue["MaxImageSizeBytes"] = + bmcwebHttpReqBodyLimitMb * 1024 * 1024; #ifdef BMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE - // Update Actions object. - nlohmann::json& updateSvcSimpleUpdate = - asyncResp->res - .jsonValue["Actions"]["#UpdateService.SimpleUpdate"]; - updateSvcSimpleUpdate["target"] = - "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate"; - updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] = - {"TFTP"}; + // Update Actions object. + nlohmann::json& updateSvcSimpleUpdate = + asyncResp->res.jsonValue["Actions"]["#UpdateService.SimpleUpdate"]; + updateSvcSimpleUpdate["target"] = + "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate"; + updateSvcSimpleUpdate["TransferProtocol@Redfish.AllowableValues"] = { + "TFTP"}; #endif - // Get the current ApplyTime value - sdbusplus::asio::getProperty<std::string>( - *crow::connections::systemBus, "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/software/apply_time", - "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime", - [asyncResp](const boost::system::error_code ec, - const std::string& applyTime) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error " << ec; - messages::internalError(asyncResp->res); - return; - } + // Get the current ApplyTime value + sdbusplus::asio::getProperty<std::string>( + *crow::connections::systemBus, "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/software/apply_time", + "xyz.openbmc_project.Software.ApplyTime", "RequestedApplyTime", + [asyncResp](const boost::system::error_code ec, + const std::string& applyTime) { + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error " << ec; + messages::internalError(asyncResp->res); + return; + } - // Store the ApplyTime Value - if (applyTime == "xyz.openbmc_project.Software.ApplyTime." - "RequestedApplyTimes.Immediate") - { - asyncResp->res - .jsonValue["HttpPushUriOptions"] - ["HttpPushUriApplyTime"]["ApplyTime"] = - "Immediate"; - } - else if (applyTime == - "xyz.openbmc_project.Software.ApplyTime." - "RequestedApplyTimes.OnReset") - { - asyncResp->res - .jsonValue["HttpPushUriOptions"] - ["HttpPushUriApplyTime"]["ApplyTime"] = - "OnReset"; - } - }); + // Store the ApplyTime Value + if (applyTime == "xyz.openbmc_project.Software.ApplyTime." + "RequestedApplyTimes.Immediate") + { + asyncResp->res.jsonValue["HttpPushUriOptions"] + ["HttpPushUriApplyTime"]["ApplyTime"] = + "Immediate"; + } + else if (applyTime == "xyz.openbmc_project.Software.ApplyTime." + "RequestedApplyTimes.OnReset") + { + asyncResp->res.jsonValue["HttpPushUriOptions"] + ["HttpPushUriApplyTime"]["ApplyTime"] = + "OnReset"; + } + }); }); BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") .privileges(redfish::privileges::patchUpdateService) - .methods( - boost::beast::http::verb::patch)([&app](const crow::Request& req, - const std::shared_ptr< - bmcweb::AsyncResp>& - asyncResp) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - BMCWEB_LOG_DEBUG << "doPatch..."; + .methods(boost::beast::http::verb::patch)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + BMCWEB_LOG_DEBUG << "doPatch..."; + + std::optional<nlohmann::json> pushUriOptions; + if (!json_util::readJsonPatch(req, asyncResp->res, "HttpPushUriOptions", + pushUriOptions)) + { + return; + } - std::optional<nlohmann::json> pushUriOptions; - if (!json_util::readJsonPatch(req, asyncResp->res, - "HttpPushUriOptions", pushUriOptions)) + if (pushUriOptions) + { + std::optional<nlohmann::json> pushUriApplyTime; + if (!json_util::readJson(*pushUriOptions, asyncResp->res, + "HttpPushUriApplyTime", pushUriApplyTime)) { return; } - if (pushUriOptions) + if (pushUriApplyTime) { - std::optional<nlohmann::json> pushUriApplyTime; - if (!json_util::readJson(*pushUriOptions, asyncResp->res, - "HttpPushUriApplyTime", - pushUriApplyTime)) + std::optional<std::string> applyTime; + if (!json_util::readJson(*pushUriApplyTime, asyncResp->res, + "ApplyTime", applyTime)) { return; } - if (pushUriApplyTime) + if (applyTime) { - std::optional<std::string> applyTime; - if (!json_util::readJson(*pushUriApplyTime, asyncResp->res, - "ApplyTime", applyTime)) + std::string applyTimeNewVal; + if (applyTime == "Immediate") + { + applyTimeNewVal = + "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.Immediate"; + } + else if (applyTime == "OnReset") { + applyTimeNewVal = + "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset"; + } + else + { + BMCWEB_LOG_INFO + << "ApplyTime value is not in the list of acceptable values"; + messages::propertyValueNotInList( + asyncResp->res, *applyTime, "ApplyTime"); return; } - if (applyTime) - { - std::string applyTimeNewVal; - if (applyTime == "Immediate") - { - applyTimeNewVal = - "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.Immediate"; - } - else if (applyTime == "OnReset") - { - applyTimeNewVal = - "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset"; - } - else + // Set the requested image apply time value + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec) { + if (ec) { - BMCWEB_LOG_INFO - << "ApplyTime value is not in the list of acceptable values"; - messages::propertyValueNotInList( - asyncResp->res, *applyTime, "ApplyTime"); + BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; + messages::internalError(asyncResp->res); return; } - - // Set the requested image apply time value - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR - << "D-Bus responses error: " << ec; - messages::internalError(asyncResp->res); - return; - } - messages::success(asyncResp->res); - }, - "xyz.openbmc_project.Settings", - "/xyz/openbmc_project/software/apply_time", - "org.freedesktop.DBus.Properties", "Set", - "xyz.openbmc_project.Software.ApplyTime", - "RequestedApplyTime", - dbus::utility::DbusVariantType{applyTimeNewVal}); - } + messages::success(asyncResp->res); + }, + "xyz.openbmc_project.Settings", + "/xyz/openbmc_project/software/apply_time", + "org.freedesktop.DBus.Properties", "Set", + "xyz.openbmc_project.Software.ApplyTime", + "RequestedApplyTime", + dbus::utility::DbusVariantType{applyTimeNewVal}); } } + } }); // The "old" behavior of the update service URI causes redfish-service validator @@ -740,16 +712,14 @@ inline void requestRoutesUpdateService(App& app) #ifdef BMCWEB_ENABLE_REDFISH_UPDATESERVICE_OLD_POST_URL BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/") .privileges(redfish::privileges::postUpdateService) - .methods( - boost::beast::http::verb:: - post)([&app]( - const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { - asyncResp->res.addHeader( - boost::beast::http::field::warning, - "299 - \"POST to /redfish/v1/UpdateService is deprecated. Use " - "the value contained within HttpPushUri.\""); - handleUpdateServicePost(app, req, asyncResp); + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { + asyncResp->res.addHeader( + boost::beast::http::field::warning, + "299 - \"POST to /redfish/v1/UpdateService is deprecated. Use " + "the value contained within HttpPushUri.\""); + handleUpdateServicePost(app, req, asyncResp); }); #endif BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/update/") @@ -765,64 +735,59 @@ inline void requestRoutesSoftwareInventoryCollection(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->res)) + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + asyncResp->res.jsonValue["@odata.type"] = + "#SoftwareInventoryCollection.SoftwareInventoryCollection"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/UpdateService/FirmwareInventory"; + asyncResp->res.jsonValue["Name"] = "Software Inventory Collection"; + + crow::connections::systemBus->async_method_call( + [asyncResp]( + const boost::system::error_code ec, + const dbus::utility::MapperGetSubTreeResponse& subtree) { + if (ec) + { + messages::internalError(asyncResp->res); + return; + } + asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); + asyncResp->res.jsonValue["Members@odata.count"] = 0; + + for (const auto& obj : subtree) + { + sdbusplus::message::object_path path(obj.first); + std::string swId = path.filename(); + if (swId.empty()) { + messages::internalError(asyncResp->res); + BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!"; return; } - asyncResp->res.jsonValue["@odata.type"] = - "#SoftwareInventoryCollection.SoftwareInventoryCollection"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/UpdateService/FirmwareInventory"; - asyncResp->res.jsonValue["Name"] = - "Software Inventory Collection"; - - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& - subtree) { - if (ec) - { - messages::internalError(asyncResp->res); - return; - } - asyncResp->res.jsonValue["Members"] = - nlohmann::json::array(); - asyncResp->res.jsonValue["Members@odata.count"] = 0; - for (const auto& obj : subtree) - { - sdbusplus::message::object_path path(obj.first); - std::string swId = path.filename(); - if (swId.empty()) - { - messages::internalError(asyncResp->res); - BMCWEB_LOG_DEBUG << "Can't parse firmware ID!!"; - return; - } - - nlohmann::json& members = - asyncResp->res.jsonValue["Members"]; - nlohmann::json::object_t member; - member["@odata.id"] = - "/redfish/v1/UpdateService/FirmwareInventory/" + - swId; - members.push_back(std::move(member)); - asyncResp->res.jsonValue["Members@odata.count"] = - members.size(); - } - }, - // Note that only firmware levels associated with a device - // are stored under /xyz/openbmc_project/software therefore - // to ensure only real FirmwareInventory items are returned, - // this full object path must be used here as input to - // mapper - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", - "/xyz/openbmc_project/software", static_cast<int32_t>(0), - std::array<const char*, 1>{ - "xyz.openbmc_project.Software.Version"}); - }); + nlohmann::json& members = asyncResp->res.jsonValue["Members"]; + nlohmann::json::object_t member; + member["@odata.id"] = + "/redfish/v1/UpdateService/FirmwareInventory/" + swId; + members.push_back(std::move(member)); + asyncResp->res.jsonValue["Members@odata.count"] = + members.size(); + } + }, + // Note that only firmware levels associated with a device + // are stored under /xyz/openbmc_project/software therefore + // to ensure only real FirmwareInventory items are returned, + // this full object path must be used here as input to + // mapper + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", + "/xyz/openbmc_project/software", static_cast<int32_t>(0), + std::array<const char*, 1>{"xyz.openbmc_project.Software.Version"}); + }); } /* Fill related item links (i.e. bmc, bios) in for inventory */ inline static void @@ -855,154 +820,143 @@ inline void requestRoutesSoftwareInventory(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/") .privileges(redfish::privileges::getSoftwareInventory) - .methods( - boost::beast::http::verb:: - get)([&app](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& param) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + .methods(boost::beast::http::verb::get)( + [&app](const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& param) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + std::shared_ptr<std::string> swId = + std::make_shared<std::string>(param); + + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/UpdateService/FirmwareInventory/" + *swId; + + crow::connections::systemBus->async_method_call( + [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; } - std::shared_ptr<std::string> swId = - std::make_shared<std::string>(param); - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/UpdateService/FirmwareInventory/" + *swId; + // 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 (!boost::ends_with(obj.first, *swId)) + { + continue; + } - crow::connections::systemBus->async_method_call( - [asyncResp, - swId](const boost::system::error_code ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) { - BMCWEB_LOG_DEBUG << "doGet callback..."; - if (ec) + if (obj.second.empty()) + { + continue; + } + + found = true; + fw_util::getFwStatus(asyncResp, swId, obj.second[0].first); + + crow::connections::systemBus->async_method_call( + [asyncResp, swId](const boost::system::error_code errorCode, + const dbus::utility::DBusPropertiesMap& + propertiesList) { + if (errorCode) { 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) + const std::string* swInvPurpose = nullptr; + const std::string* version = nullptr; + for (const auto& property : propertiesList) { - if (!boost::ends_with(obj.first, *swId)) + if (property.first == "Purpose") { - continue; + swInvPurpose = + std::get_if<std::string>(&property.second); } - - if (obj.second.empty()) + if (property.first == "Version") { - continue; + version = + std::get_if<std::string>(&property.second); } + } - found = true; - fw_util::getFwStatus(asyncResp, swId, - obj.second[0].first); - - crow::connections::systemBus->async_method_call( - [asyncResp, - swId](const boost::system::error_code errorCode, - const dbus::utility::DBusPropertiesMap& - propertiesList) { - if (errorCode) - { - messages::internalError(asyncResp->res); - return; - } - const std::string* swInvPurpose = nullptr; - const std::string* version = nullptr; - for (const auto& property : propertiesList) - { - if (property.first == "Purpose") - { - swInvPurpose = std::get_if<std::string>( - &property.second); - } - if (property.first == "Version") - { - version = std::get_if<std::string>( - &property.second); - } - } - - if (swInvPurpose == nullptr) - { - BMCWEB_LOG_DEBUG - << "Can't find property \"Purpose\"!"; - messages::internalError(asyncResp->res); - return; - } - - BMCWEB_LOG_DEBUG << "swInvPurpose = " - << *swInvPurpose; + if (swInvPurpose == nullptr) + { + BMCWEB_LOG_DEBUG << "Can't find property \"Purpose\"!"; + messages::internalError(asyncResp->res); + return; + } - if (version == nullptr) - { - BMCWEB_LOG_DEBUG - << "Can't find property \"Version\"!"; + BMCWEB_LOG_DEBUG << "swInvPurpose = " << *swInvPurpose; - messages::internalError(asyncResp->res); + if (version == nullptr) + { + BMCWEB_LOG_DEBUG << "Can't find property \"Version\"!"; - 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; - } + messages::internalError(asyncResp->res); - std::string formatDesc = - swInvPurpose->substr(endDesc); - asyncResp->res.jsonValue["Description"] = - formatDesc + " image"; - getRelatedItems(asyncResp, *swInvPurpose); - }, - obj.second[0].first, obj.first, - "org.freedesktop.DBus.Properties", "GetAll", - "xyz.openbmc_project.Software.Version"); + return; } - if (!found) + 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) { - BMCWEB_LOG_ERROR << "Input swID " << *swId - << " not found!"; - messages::resourceMissingAtURI( - asyncResp->res, - crow::utility::urlFromPieces( - "redfish", "v1", "UpdateService", - "FirmwareInventory", *swId)); + messages::internalError(asyncResp->res); + return; + } + endDesc++; + if (endDesc >= swInvPurpose->size()) + { + messages::internalError(asyncResp->res); 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; - fw_util::getFwUpdateableStatus(asyncResp, swId); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", - static_cast<int32_t>(0), - std::array<const char*, 1>{ - "xyz.openbmc_project.Software.Version"}); + std::string formatDesc = swInvPurpose->substr(endDesc); + asyncResp->res.jsonValue["Description"] = + formatDesc + " image"; + getRelatedItems(asyncResp, *swInvPurpose); + }, + obj.second[0].first, obj.first, + "org.freedesktop.DBus.Properties", "GetAll", + "xyz.openbmc_project.Software.Version"); + } + if (!found) + { + BMCWEB_LOG_ERROR << "Input swID " << *swId << " not found!"; + messages::resourceMissingAtURI( + asyncResp->res, crow::utility::urlFromPieces( + "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; + fw_util::getFwUpdateableStatus(asyncResp, swId); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", + static_cast<int32_t>(0), + std::array<const char*, 1>{"xyz.openbmc_project.Software.Version"}); }); } diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp index e94e233964..31bc7b682c 100644 --- a/redfish-core/lib/virtual_media.hpp +++ b/redfish-core/lib/virtual_media.hpp @@ -179,32 +179,32 @@ inline void getVmResourceList(std::shared_ptr<bmcweb::AsyncResp> aResp, [name, aResp{std::move(aResp)}](const boost::system::error_code ec, dbus::utility::ManagedObjectType& subtree) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - return; - } - nlohmann::json& members = aResp->res.jsonValue["Members"]; - members = nlohmann::json::array(); + if (ec) + { + BMCWEB_LOG_DEBUG << "DBUS response error"; + return; + } + nlohmann::json& members = aResp->res.jsonValue["Members"]; + members = nlohmann::json::array(); - for (const auto& object : subtree) + for (const auto& object : subtree) + { + nlohmann::json item; + std::string path = object.first.filename(); + if (path.empty()) { - nlohmann::json item; - std::string path = object.first.filename(); - if (path.empty()) - { - continue; - } + continue; + } - std::string id = "/redfish/v1/Managers/"; - id += name; - id += "/VirtualMedia/"; - id += path; + std::string id = "/redfish/v1/Managers/"; + id += name; + id += "/VirtualMedia/"; + id += path; - item["@odata.id"] = std::move(id); - members.emplace_back(std::move(item)); - } - aResp->res.jsonValue["Members@odata.count"] = members.size(); + item["@odata.id"] = std::move(id); + members.emplace_back(std::move(item)); + } + aResp->res.jsonValue["Members@odata.count"] = members.size(); }, service, "/xyz/openbmc_project/VirtualMedia", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -223,66 +223,66 @@ inline void getVmData(const std::shared_ptr<bmcweb::AsyncResp>& aResp, [resName, name, aResp](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) + for (const auto& item : subtree) + { + std::string thispath = item.first.filename(); + if (thispath.empty()) { - std::string thispath = item.first.filename(); - if (thispath.empty()) - { - continue; - } + continue; + } - if (thispath != resName) - { - continue; - } + if (thispath != resName) + { + continue; + } - // "Legacy"/"Proxy" - auto mode = item.first.parent_path(); - // "VirtualMedia" - auto type = mode.parent_path(); - if (mode.filename().empty() || type.filename().empty()) - { - continue; - } + // "Legacy"/"Proxy" + auto mode = item.first.parent_path(); + // "VirtualMedia" + auto type = mode.parent_path(); + if (mode.filename().empty() || type.filename().empty()) + { + continue; + } - if (type.filename() != "VirtualMedia") - { - continue; - } + if (type.filename() != "VirtualMedia") + { + continue; + } - aResp->res.jsonValue = vmItemTemplate(name, resName); - std::string actionsId = "/redfish/v1/Managers/"; - actionsId += name; - actionsId += "/VirtualMedia/"; - actionsId += resName; - actionsId += "/Actions"; + aResp->res.jsonValue = vmItemTemplate(name, resName); + std::string actionsId = "/redfish/v1/Managers/"; + actionsId += name; + actionsId += "/VirtualMedia/"; + actionsId += resName; + actionsId += "/Actions"; - // Check if dbus path is Legacy type - if (mode.filename() == "Legacy") - { - aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] - ["target"] = - actionsId + "/VirtualMedia.InsertMedia"; - } + // Check if dbus path is Legacy type + if (mode.filename() == "Legacy") + { + aResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"] + ["target"] = + actionsId + "/VirtualMedia.InsertMedia"; + } - vmParseInterfaceObject(item.second, aResp); + vmParseInterfaceObject(item.second, aResp); - aResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"] - ["target"] = - actionsId + "/VirtualMedia.EjectMedia"; + aResp->res + .jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] = + actionsId + "/VirtualMedia.EjectMedia"; - return; - } + return; + } - messages::resourceNotFound( - aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); + messages::resourceNotFound( + aResp->res, "#VirtualMedia.v1_3_0.VirtualMedia", resName); }, service, "/xyz/openbmc_project/VirtualMedia", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); @@ -677,11 +677,11 @@ inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, // Pack secret auto secret = credentials.pack( [](const auto& user, const auto& pass, auto& buff) { - std::copy(user.begin(), user.end(), std::back_inserter(buff)); - buff.push_back('\0'); - std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); - buff.push_back('\0'); - }); + std::copy(user.begin(), user.end(), std::back_inserter(buff)); + buff.push_back('\0'); + std::copy(pass.begin(), pass.end(), std::back_inserter(buff)); + buff.push_back('\0'); + }); // Open pipe secretPipe = std::make_shared<SecurePipe>( @@ -691,27 +691,27 @@ inline void doMountVmLegacy(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, // Pass secret over pipe secretPipe->asyncWrite( [asyncResp](const boost::system::error_code& ec, std::size_t) { - if (ec) - { - BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; - messages::internalError(asyncResp->res); - } - }); + if (ec) + { + BMCWEB_LOG_ERROR << "Failed to pass secret: " << ec; + messages::internalError(asyncResp->res); + } + }); } 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); - } - else if (!success) - { - BMCWEB_LOG_ERROR << "Service responded with error"; - messages::generalError(asyncResp->res); - } + if (ec) + { + BMCWEB_LOG_ERROR << "Bad D-Bus request error: " << ec; + messages::internalError(asyncResp->res); + } + else if (!success) + { + BMCWEB_LOG_ERROR << "Service responded with error"; + messages::generalError(asyncResp->res); + } }, service, "/xyz/openbmc_project/VirtualMedia/Legacy/" + name, "xyz.openbmc_project.VirtualMedia.Legacy", "Mount", imageUrl, rw, @@ -733,13 +733,13 @@ inline void doVmAction(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"); @@ -748,13 +748,13 @@ inline void doVmAction(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"); @@ -782,136 +782,125 @@ inline void requestNBDVirtualMediaRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& name, const std::string& resName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (name != "bmc") + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (name != "bmc") + { + messages::resourceNotFound(asyncResp->res, "VirtualMedia.Insert", + resName); + + return; + } + InsertMediaActionParams actionParams; + + // Read obligatory parameters (url of + // image) + if (!json_util::readJsonAction( + req, asyncResp->res, "Image", actionParams.imageUrl, + "WriteProtected", actionParams.writeProtected, "UserName", + actionParams.userName, "Password", actionParams.password, + "Inserted", actionParams.inserted, "TransferMethod", + actionParams.transferMethod, "TransferProtocolType", + actionParams.transferProtocolType)) + { + BMCWEB_LOG_DEBUG << "Image is not provided"; + return; + } + + bool paramsValid = validateParams( + asyncResp->res, actionParams.imageUrl, actionParams.inserted, + actionParams.transferMethod, actionParams.transferProtocolType); + + if (!paramsValid) + { + return; + } + + crow::connections::systemBus->async_method_call( + [asyncResp, 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::internalError(asyncResp->res); + + return; + } + std::string service = getObjectType.begin()->first; + BMCWEB_LOG_DEBUG << "GetObjectType: " << service; + + crow::connections::systemBus->async_method_call( + [service, resName, actionParams, + asyncResp](const boost::system::error_code ec, + dbus::utility::ManagedObjectType& subtree) mutable { + if (ec) { - messages::resourceNotFound(asyncResp->res, - "VirtualMedia.Insert", resName); + BMCWEB_LOG_DEBUG << "DBUS response error"; return; } - InsertMediaActionParams actionParams; - - // Read obligatory parameters (url of - // image) - if (!json_util::readJsonAction( - req, asyncResp->res, "Image", actionParams.imageUrl, - "WriteProtected", actionParams.writeProtected, - "UserName", actionParams.userName, "Password", - actionParams.password, "Inserted", - actionParams.inserted, "TransferMethod", - actionParams.transferMethod, "TransferProtocolType", - actionParams.transferProtocolType)) + + for (const auto& object : subtree) { - BMCWEB_LOG_DEBUG << "Image is not provided"; - return; - } + const std::string& path = + static_cast<const std::string&>(object.first); - bool paramsValid = validateParams( - asyncResp->res, actionParams.imageUrl, - actionParams.inserted, actionParams.transferMethod, - actionParams.transferProtocolType); + std::size_t lastIndex = path.rfind('/'); + if (lastIndex == std::string::npos) + { + continue; + } - if (!paramsValid) - { - return; - } + lastIndex += 1; - crow::connections::systemBus->async_method_call( - [asyncResp, actionParams, - resName](const boost::system::error_code ec, - const dbus::utility::MapperGetObject& - getObjectType) mutable { - if (ec) + if (path.substr(lastIndex) == resName) + { + lastIndex = path.rfind("Proxy"); + if (lastIndex != std::string::npos) { - BMCWEB_LOG_ERROR - << "ObjectMapper::GetObject call failed: " - << ec; - messages::internalError(asyncResp->res); + // Not possible in proxy mode + BMCWEB_LOG_DEBUG << "InsertMedia not " + "allowed in proxy mode"; + messages::resourceNotFound( + asyncResp->res, "VirtualMedia.InsertMedia", + resName); return; } - std::string service = getObjectType.begin()->first; - BMCWEB_LOG_DEBUG << "GetObjectType: " << service; - - crow::connections::systemBus->async_method_call( - [service, resName, actionParams, - asyncResp](const boost::system::error_code ec, - dbus::utility::ManagedObjectType& - subtree) mutable { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - - return; - } - - for (const auto& object : subtree) - { - const std::string& path = - static_cast<const std::string&>( - object.first); - - std::size_t lastIndex = path.rfind('/'); - if (lastIndex == std::string::npos) - { - continue; - } - - lastIndex += 1; - - if (path.substr(lastIndex) == resName) - { - lastIndex = path.rfind("Proxy"); - if (lastIndex != std::string::npos) - { - // Not possible in proxy mode - BMCWEB_LOG_DEBUG - << "InsertMedia not " - "allowed in proxy mode"; - messages::resourceNotFound( - asyncResp->res, - "VirtualMedia.InsertMedia", - resName); - - return; - } - - lastIndex = path.rfind("Legacy"); - if (lastIndex == std::string::npos) - { - continue; - } - - // manager is irrelevant for - // VirtualMedia dbus calls - doMountVmLegacy( - asyncResp, service, resName, - actionParams.imageUrl, - !(*actionParams.writeProtected), - std::move(*actionParams.userName), - std::move(*actionParams.password)); - - return; - } - } - BMCWEB_LOG_DEBUG << "Parent item not found"; - messages::resourceNotFound( - asyncResp->res, "VirtualMedia", resName); - }, - service, "/xyz/openbmc_project/VirtualMedia", - "org.freedesktop.DBus.ObjectManager", - "GetManagedObjects"); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", - "/xyz/openbmc_project/VirtualMedia", - std::array<const char*, 0>()); - }); + + lastIndex = path.rfind("Legacy"); + if (lastIndex == std::string::npos) + { + continue; + } + + // manager is irrelevant for + // VirtualMedia dbus calls + doMountVmLegacy(asyncResp, service, resName, + actionParams.imageUrl, + !(*actionParams.writeProtected), + std::move(*actionParams.userName), + std::move(*actionParams.password)); + + return; + } + } + BMCWEB_LOG_DEBUG << "Parent item not found"; + messages::resourceNotFound(asyncResp->res, "VirtualMedia", + resName); + }, + service, "/xyz/openbmc_project/VirtualMedia", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", + "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); + }); BMCWEB_ROUTE( app, @@ -921,142 +910,133 @@ inline void requestNBDVirtualMediaRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& name, const std::string& resName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (name != "bmc") + { + messages::resourceNotFound(asyncResp->res, "VirtualMedia.Eject", + resName); + + return; + } + + crow::connections::systemBus->async_method_call( + [asyncResp, + 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); + + return; + } + std::string service = getObjectType.begin()->first; + BMCWEB_LOG_DEBUG << "GetObjectType: " << service; + + crow::connections::systemBus->async_method_call( + [resName, service, asyncResp{asyncResp}]( + const boost::system::error_code ec, + dbus::utility::ManagedObjectType& subtree) { + if (ec) { + BMCWEB_LOG_DEBUG << "DBUS response error"; + return; } - if (name != "bmc") + + for (const auto& object : subtree) { - messages::resourceNotFound(asyncResp->res, - "VirtualMedia.Eject", resName); + const std::string& path = + static_cast<const std::string&>(object.first); - return; - } + std::size_t lastIndex = path.rfind('/'); + if (lastIndex == std::string::npos) + { + continue; + } + + lastIndex += 1; - crow::connections::systemBus->async_method_call( - [asyncResp, resName]( - const boost::system::error_code ec, - const dbus::utility::MapperGetObject& getObjectType) { - if (ec) + if (path.substr(lastIndex) == resName) + { + lastIndex = path.rfind("Proxy"); + if (lastIndex != std::string::npos) { - BMCWEB_LOG_ERROR - << "ObjectMapper::GetObject call failed: " - << ec; - messages::internalError(asyncResp->res); + // Proxy mode + doVmAction(asyncResp, service, resName, false); + } - return; + lastIndex = path.rfind("Legacy"); + if (lastIndex != std::string::npos) + { + // Legacy mode + doVmAction(asyncResp, service, resName, true); } - std::string service = getObjectType.begin()->first; - BMCWEB_LOG_DEBUG << "GetObjectType: " << service; - - crow::connections::systemBus->async_method_call( - [resName, service, asyncResp{asyncResp}]( - const boost::system::error_code ec, - dbus::utility::ManagedObjectType& subtree) { - if (ec) - { - BMCWEB_LOG_DEBUG << "DBUS response error"; - - return; - } - - for (const auto& object : subtree) - { - const std::string& path = - static_cast<const std::string&>( - object.first); - - std::size_t lastIndex = path.rfind('/'); - if (lastIndex == std::string::npos) - { - continue; - } - - lastIndex += 1; - - if (path.substr(lastIndex) == resName) - { - lastIndex = path.rfind("Proxy"); - if (lastIndex != std::string::npos) - { - // Proxy mode - doVmAction(asyncResp, service, - resName, false); - } - - lastIndex = path.rfind("Legacy"); - if (lastIndex != std::string::npos) - { - // Legacy mode - doVmAction(asyncResp, service, - resName, true); - } - - return; - } - } - BMCWEB_LOG_DEBUG << "Parent item not found"; - messages::resourceNotFound( - asyncResp->res, "VirtualMedia", resName); - }, - service, "/xyz/openbmc_project/VirtualMedia", - "org.freedesktop.DBus.ObjectManager", - "GetManagedObjects"); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", - "/xyz/openbmc_project/VirtualMedia", - std::array<const char*, 0>()); - }); + + return; + } + } + BMCWEB_LOG_DEBUG << "Parent item not found"; + messages::resourceNotFound(asyncResp->res, "VirtualMedia", + resName); + }, + service, "/xyz/openbmc_project/VirtualMedia", + "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", + "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/") .privileges(redfish::privileges::getVirtualMediaCollection) .methods(boost::beast::http::verb::get)( [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& name) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (name != "bmc") - { - messages::resourceNotFound(asyncResp->res, "VirtualMedia", - name); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (name != "bmc") + { + messages::resourceNotFound(asyncResp->res, "VirtualMedia", name); - return; - } + return; + } - asyncResp->res.jsonValue["@odata.type"] = - "#VirtualMediaCollection.VirtualMediaCollection"; - asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; - asyncResp->res.jsonValue["@odata.id"] = - "/redfish/v1/Managers/" + name + "/VirtualMedia"; - - crow::connections::systemBus->async_method_call( - [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); + asyncResp->res.jsonValue["@odata.type"] = + "#VirtualMediaCollection.VirtualMediaCollection"; + asyncResp->res.jsonValue["Name"] = "Virtual Media Services"; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/Managers/" + name + "/VirtualMedia"; - return; - } - std::string service = getObjectType.begin()->first; - BMCWEB_LOG_DEBUG << "GetObjectType: " << service; - - getVmResourceList(asyncResp, service, name); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", - "/xyz/openbmc_project/VirtualMedia", - std::array<const char*, 0>()); - }); + crow::connections::systemBus->async_method_call( + [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); + + return; + } + std::string service = getObjectType.begin()->first; + BMCWEB_LOG_DEBUG << "GetObjectType: " << service; + + getVmResourceList(asyncResp, service, name); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", + "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); + }); BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/VirtualMedia/<str>/") .privileges(redfish::privileges::getVirtualMedia) @@ -1064,42 +1044,39 @@ inline void requestNBDVirtualMediaRoutes(App& app) [&app](const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& name, const std::string& resName) { - if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) - { - return; - } - if (name != "bmc") - { - messages::resourceNotFound(asyncResp->res, "VirtualMedia", - resName); + if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) + { + return; + } + if (name != "bmc") + { + messages::resourceNotFound(asyncResp->res, "VirtualMedia", resName); - return; - } + return; + } - crow::connections::systemBus->async_method_call( - [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); + crow::connections::systemBus->async_method_call( + [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); - return; - } - std::string service = getObjectType.begin()->first; - BMCWEB_LOG_DEBUG << "GetObjectType: " << service; - - getVmData(asyncResp, service, name, resName); - }, - "xyz.openbmc_project.ObjectMapper", - "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", - "/xyz/openbmc_project/VirtualMedia", - std::array<const char*, 0>()); - }); + return; + } + std::string service = getObjectType.begin()->first; + BMCWEB_LOG_DEBUG << "GetObjectType: " << service; + + getVmData(asyncResp, service, name, resName); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", + "/xyz/openbmc_project/VirtualMedia", std::array<const char*, 0>()); + }); } } // namespace redfish |