Move to clang-format-6.0
This commit moves the codebase to the lastest clang-format file from
upstream, as well as clang-format-6.0.
Change-Id: Ice8313468097c0c42317fbb9e10ddf036e8cff4c
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
index 4865516..085b76f 100644
--- a/redfish-core/include/error_messages.hpp
+++ b/redfish-core/include/error_messages.hpp
@@ -24,9 +24,11 @@
#pragma once
#include <nlohmann/json.hpp>
-namespace redfish {
+namespace redfish
+{
-namespace messages {
+namespace messages
+{
constexpr const char* messageVersionPrefix = "Base.1.2.0.";
constexpr const char* messageAnnotation = "@Message.ExtendedInfo";
@@ -636,6 +638,6 @@
* AUTOGENERATED FUNCTIONS END *
*********************************/
-} // namespace messages
+} // namespace messages
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/include/node.hpp b/redfish-core/include/node.hpp
index 20d2951..8dbb0c2 100644
--- a/redfish-core/include/node.hpp
+++ b/redfish-core/include/node.hpp
@@ -18,161 +18,190 @@
#include "privileges.hpp"
#include "token_authorization_middleware.hpp"
#include "webserver_common.hpp"
+
#include "crow.h"
-namespace redfish {
+namespace redfish
+{
/**
* AsyncResp
* Gathers data needed for response processing after async calls are done
*/
-class AsyncResp {
- public:
- AsyncResp(crow::Response& response) : res(response) {}
+class AsyncResp
+{
+ public:
+ AsyncResp(crow::Response& response) : res(response)
+ {
+ }
- ~AsyncResp() { res.end(); }
+ ~AsyncResp()
+ {
+ res.end();
+ }
- crow::Response& res;
+ crow::Response& res;
};
/**
* @brief Abstract class used for implementing Redfish nodes.
*
*/
-class Node {
- public:
- template <typename... Params>
- Node(CrowApp& app, std::string&& entityUrl, Params... params) {
- app.routeDynamic(entityUrl.c_str())
- .methods("GET"_method, "PATCH"_method, "POST"_method,
- "DELETE"_method)([&](const crow::Request& req,
- crow::Response& res, Params... params) {
- std::vector<std::string> paramVec = {params...};
- dispatchRequest(app, req, res, paramVec);
- });
- }
-
- virtual ~Node() = default;
-
- const std::string* getUrl() const {
- auto odataId = json.find("@odata.id");
- if (odataId == json.end()) {
- return nullptr;
+class Node
+{
+ public:
+ template <typename... Params>
+ Node(CrowApp& app, std::string&& entityUrl, Params... params)
+ {
+ app.routeDynamic(entityUrl.c_str())
+ .methods("GET"_method, "PATCH"_method, "POST"_method,
+ "DELETE"_method)([&](const crow::Request& req,
+ crow::Response& res,
+ Params... params) {
+ std::vector<std::string> paramVec = {params...};
+ dispatchRequest(app, req, res, paramVec);
+ });
}
- return odataId->get_ptr<const std::string*>();
- }
+ virtual ~Node() = default;
- /**
- * @brief Inserts subroute fields into for the node's json in the form:
- * "subroute_name" : { "odata.id": "node_url/subroute_name/" }
- * Excludes metadata urls starting with "$" and child urls having
- * more than one level.
- *
- * @return None
- */
- void getSubRoutes(const std::vector<std::unique_ptr<Node>>& allNodes) {
- const std::string* url = getUrl();
- if (url == nullptr) {
- // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
- return;
+ const std::string* getUrl() const
+ {
+ auto odataId = json.find("@odata.id");
+ if (odataId == json.end())
+ {
+ return nullptr;
+ }
+
+ return odataId->get_ptr<const std::string*>();
}
- for (const auto& node : allNodes) {
- const std::string* route = node->getUrl();
- if (route == nullptr) {
- // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
- continue;
- }
- if (boost::starts_with(*route, *url)) {
- std::string subRoute = route->substr(url->size());
- if (subRoute.empty()) {
- continue;
+ /**
+ * @brief Inserts subroute fields into for the node's json in the form:
+ * "subroute_name" : { "odata.id": "node_url/subroute_name/" }
+ * Excludes metadata urls starting with "$" and child urls having
+ * more than one level.
+ *
+ * @return None
+ */
+ void getSubRoutes(const std::vector<std::unique_ptr<Node>>& allNodes)
+ {
+ const std::string* url = getUrl();
+ if (url == nullptr)
+ {
+ // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
+ return;
}
- if (boost::starts_with(subRoute, "/")) {
- subRoute.erase(0, 1);
+ for (const auto& node : allNodes)
+ {
+ const std::string* route = node->getUrl();
+ if (route == nullptr)
+ {
+ // BMCWEB_LOG_CRITICAL << "Unable to get url for route";
+ continue;
+ }
+ if (boost::starts_with(*route, *url))
+ {
+ std::string subRoute = route->substr(url->size());
+ if (subRoute.empty())
+ {
+ continue;
+ }
+
+ if (boost::starts_with(subRoute, "/"))
+ {
+ subRoute.erase(0, 1);
+ }
+
+ if (boost::ends_with(subRoute, "/"))
+ {
+ subRoute.pop_back();
+ }
+
+ if (!boost::starts_with(subRoute, "$") &&
+ subRoute.find('/') == std::string::npos)
+ {
+ json[subRoute] = nlohmann::json{{"@odata.id", *route}};
+ }
+ }
}
-
- if (boost::ends_with(subRoute, "/")) {
- subRoute.pop_back();
- }
-
- if (!boost::starts_with(subRoute, "$") &&
- subRoute.find('/') == std::string::npos) {
- json[subRoute] = nlohmann::json{{"@odata.id", *route}};
- }
- }
- }
- }
-
- OperationMap entityPrivileges;
-
- protected:
- // Node is designed to be an abstract class, so doGet is pure virtual
- virtual void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) {
- res.result(boost::beast::http::status::method_not_allowed);
- res.end();
- }
-
- virtual void doPatch(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) {
- res.result(boost::beast::http::status::method_not_allowed);
- res.end();
- }
-
- virtual void doPost(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) {
- res.result(boost::beast::http::status::method_not_allowed);
- res.end();
- }
-
- virtual void doDelete(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) {
- res.result(boost::beast::http::status::method_not_allowed);
- res.end();
- }
-
- nlohmann::json json;
-
- private:
- void dispatchRequest(CrowApp& app, const crow::Request& req,
- crow::Response& res,
- const std::vector<std::string>& params) {
- auto ctx =
- app.template getContext<crow::token_authorization::Middleware>(req);
-
- if (!isMethodAllowedForUser(req.method(), entityPrivileges,
- ctx.session->username)) {
- res.result(boost::beast::http::status::method_not_allowed);
- res.end();
- return;
}
- switch (req.method()) {
- case "GET"_method:
- doGet(res, req, params);
- break;
+ OperationMap entityPrivileges;
- case "PATCH"_method:
- doPatch(res, req, params);
- break;
-
- case "POST"_method:
- doPost(res, req, params);
- break;
-
- case "DELETE"_method:
- doDelete(res, req, params);
- break;
-
- default:
- res.result(boost::beast::http::status::not_found);
+ protected:
+ // Node is designed to be an abstract class, so doGet is pure virtual
+ virtual void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params)
+ {
+ res.result(boost::beast::http::status::method_not_allowed);
res.end();
}
- return;
- }
+
+ virtual void doPatch(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params)
+ {
+ res.result(boost::beast::http::status::method_not_allowed);
+ res.end();
+ }
+
+ virtual void doPost(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params)
+ {
+ res.result(boost::beast::http::status::method_not_allowed);
+ res.end();
+ }
+
+ virtual void doDelete(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params)
+ {
+ res.result(boost::beast::http::status::method_not_allowed);
+ res.end();
+ }
+
+ nlohmann::json json;
+
+ private:
+ void dispatchRequest(CrowApp& app, const crow::Request& req,
+ crow::Response& res,
+ const std::vector<std::string>& params)
+ {
+ auto ctx =
+ app.template getContext<crow::token_authorization::Middleware>(req);
+
+ if (!isMethodAllowedForUser(req.method(), entityPrivileges,
+ ctx.session->username))
+ {
+ res.result(boost::beast::http::status::method_not_allowed);
+ res.end();
+ return;
+ }
+
+ switch (req.method())
+ {
+ case "GET"_method:
+ doGet(res, req, params);
+ break;
+
+ case "PATCH"_method:
+ doPatch(res, req, params);
+ break;
+
+ case "POST"_method:
+ doPost(res, req, params);
+ break;
+
+ case "DELETE"_method:
+ doDelete(res, req, params);
+ break;
+
+ default:
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+ }
+ return;
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/include/privileges.hpp b/redfish-core/include/privileges.hpp
index 437bb15..0f6b903 100644
--- a/redfish-core/include/privileges.hpp
+++ b/redfish-core/include/privileges.hpp
@@ -16,15 +16,21 @@
#pragma once
#include <bitset>
-#include <cstdint>
-#include <vector>
-#include "crow.h"
#include <boost/container/flat_map.hpp>
#include <boost/optional.hpp>
+#include <cstdint>
+#include <vector>
-namespace redfish {
+#include "crow.h"
-enum class PrivilegeType { BASE, OEM };
+namespace redfish
+{
+
+enum class PrivilegeType
+{
+ BASE,
+ OEM
+};
/** @brief A fixed array of compile time privileges */
constexpr std::array<const char*, 5> basePrivileges{
@@ -56,105 +62,118 @@
* (user domain) and false otherwise.
*
*/
-class Privileges {
- public:
- /**
- * @brief Constructs object without any privileges active
- *
- */
- Privileges() = default;
+class Privileges
+{
+ public:
+ /**
+ * @brief Constructs object without any privileges active
+ *
+ */
+ Privileges() = default;
- /**
- * @brief Constructs object with given privileges active
- *
- * @param[in] privilegeList List of privileges to be activated
- *
- */
- Privileges(std::initializer_list<const char*> privilegeList) {
- for (const char* privilege : privilegeList) {
- if (!setSinglePrivilege(privilege)) {
- BMCWEB_LOG_CRITICAL << "Unable to set privilege " << privilege
- << "in constructor";
- }
- }
- }
-
- /**
- * @brief Sets given privilege in the bitset
- *
- * @param[in] privilege Privilege to be set
- *
- * @return None
- *
- */
- bool setSinglePrivilege(const char* privilege) {
- for (int searchIndex = 0; searchIndex < privilegeNames.size();
- searchIndex++) {
- if (privilege == privilegeNames[searchIndex]) {
- privilegeBitset.set(searchIndex);
- return true;
- }
+ /**
+ * @brief Constructs object with given privileges active
+ *
+ * @param[in] privilegeList List of privileges to be activated
+ *
+ */
+ Privileges(std::initializer_list<const char*> privilegeList)
+ {
+ for (const char* privilege : privilegeList)
+ {
+ if (!setSinglePrivilege(privilege))
+ {
+ BMCWEB_LOG_CRITICAL << "Unable to set privilege " << privilege
+ << "in constructor";
+ }
+ }
}
- return false;
- }
+ /**
+ * @brief Sets given privilege in the bitset
+ *
+ * @param[in] privilege Privilege to be set
+ *
+ * @return None
+ *
+ */
+ bool setSinglePrivilege(const char* privilege)
+ {
+ for (int searchIndex = 0; searchIndex < privilegeNames.size();
+ searchIndex++)
+ {
+ if (privilege == privilegeNames[searchIndex])
+ {
+ privilegeBitset.set(searchIndex);
+ return true;
+ }
+ }
- /**
- * @brief Sets given privilege in the bitset
- *
- * @param[in] privilege Privilege to be set
- *
- * @return None
- *
- */
- bool setSinglePrivilege(const std::string& privilege) {
- return setSinglePrivilege(privilege.c_str());
- }
-
- /**
- * @brief Retrieves names of all active privileges for a given type
- *
- * @param[in] type Base or OEM
- *
- * @return Vector of active privileges. Pointers are valid until
- * the setSinglePrivilege is called, or the Privilege structure is destroyed
- *
- */
- std::vector<const std::string*> getActivePrivilegeNames(
- const PrivilegeType type) const {
- std::vector<const std::string*> activePrivileges;
-
- int searchIndex = 0;
- int endIndex = basePrivilegeCount;
- if (type == PrivilegeType::OEM) {
- searchIndex = basePrivilegeCount - 1;
- endIndex = privilegeNames.size();
+ return false;
}
- for (; searchIndex < endIndex; searchIndex++) {
- if (privilegeBitset.test(searchIndex)) {
- activePrivileges.emplace_back(&privilegeNames[searchIndex]);
- }
+ /**
+ * @brief Sets given privilege in the bitset
+ *
+ * @param[in] privilege Privilege to be set
+ *
+ * @return None
+ *
+ */
+ bool setSinglePrivilege(const std::string& privilege)
+ {
+ return setSinglePrivilege(privilege.c_str());
}
- return activePrivileges;
- }
+ /**
+ * @brief Retrieves names of all active privileges for a given type
+ *
+ * @param[in] type Base or OEM
+ *
+ * @return Vector of active privileges. Pointers are valid until
+ * the setSinglePrivilege is called, or the Privilege structure is destroyed
+ *
+ */
+ std::vector<const std::string*>
+ getActivePrivilegeNames(const PrivilegeType type) const
+ {
+ std::vector<const std::string*> activePrivileges;
- /**
- * @brief Determines if this Privilege set is a superset of the given
- * privilege set
- *
- * @param[in] privilege Privilege to be checked
- *
- * @return None
- *
- */
- bool isSupersetOf(const Privileges& p) const {
- return (privilegeBitset & p.privilegeBitset) == p.privilegeBitset;
- }
+ int searchIndex = 0;
+ int endIndex = basePrivilegeCount;
+ if (type == PrivilegeType::OEM)
+ {
+ searchIndex = basePrivilegeCount - 1;
+ endIndex = privilegeNames.size();
+ }
- private:
- std::bitset<maxPrivilegeCount> privilegeBitset = 0;
+ for (; searchIndex < endIndex; searchIndex++)
+ {
+ if (privilegeBitset.test(searchIndex))
+ {
+ activePrivileges.emplace_back(&privilegeNames[searchIndex]);
+ }
+ }
+
+ return activePrivileges;
+ }
+
+ /**
+ * @brief Determines if this Privilege set is a superset of the given
+ * privilege set
+ *
+ * @param[in] privilege Privilege to be checked
+ *
+ * @return None
+ *
+ */
+ bool isSupersetOf(const Privileges& p) const
+ {
+ return (privilegeBitset & p.privilegeBitset) == p.privilegeBitset;
+ }
+
+ private:
+ std::bitset<maxPrivilegeCount> privilegeBitset = 0;
};
using OperationMap = boost::container::flat_map<boost::beast::http::verb,
@@ -171,23 +190,28 @@
*/
inline bool isMethodAllowedWithPrivileges(const boost::beast::http::verb method,
const OperationMap& operationMap,
- const Privileges& userPrivileges) {
- const auto& it = operationMap.find(method);
- if (it == operationMap.end()) {
- return false;
- }
-
- // If there are no privileges assigned, assume no privileges required
- if (it->second.empty()) {
- return true;
- }
-
- for (auto& requiredPrivileges : it->second) {
- if (userPrivileges.isSupersetOf(requiredPrivileges)) {
- return true;
+ const Privileges& userPrivileges)
+{
+ const auto& it = operationMap.find(method);
+ if (it == operationMap.end())
+ {
+ return false;
}
- }
- return false;
+
+ // If there are no privileges assigned, assume no privileges required
+ if (it->second.empty())
+ {
+ return true;
+ }
+
+ for (auto& requiredPrivileges : it->second)
+ {
+ if (userPrivileges.isSupersetOf(requiredPrivileges))
+ {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -201,13 +225,14 @@
*/
inline bool isMethodAllowedForUser(const boost::beast::http::verb method,
const OperationMap& operationMap,
- const std::string& user) {
- // TODO: load user privileges from configuration as soon as its available
- // now we are granting all privileges to everyone.
- Privileges userPrivileges{"Login", "ConfigureManager", "ConfigureSelf",
- "ConfigureUsers", "ConfigureComponents"};
+ const std::string& user)
+{
+ // TODO: load user privileges from configuration as soon as its available
+ // now we are granting all privileges to everyone.
+ Privileges userPrivileges{"Login", "ConfigureManager", "ConfigureSelf",
+ "ConfigureUsers", "ConfigureComponents"};
- return isMethodAllowedWithPrivileges(method, operationMap, userPrivileges);
+ return isMethodAllowedWithPrivileges(method, operationMap, userPrivileges);
}
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index ab60abb..7f41b63 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -28,48 +28,53 @@
#include "../lib/update_service.hpp"
#include "webserver_common.hpp"
-namespace redfish {
+namespace redfish
+{
/*
* @brief Top level class installing and providing Redfish services
*/
-class RedfishService {
- public:
- /*
- * @brief Redfish service constructor
- *
- * Loads Redfish configuration and installs schema resources
- *
- * @param[in] app Crow app on which Redfish will initialize
- */
- RedfishService(CrowApp& app) {
- nodes.emplace_back(std::make_unique<AccountService>(app));
- nodes.emplace_back(std::make_unique<SessionCollection>(app));
- nodes.emplace_back(std::make_unique<Roles>(app));
- nodes.emplace_back(std::make_unique<RoleCollection>(app));
- nodes.emplace_back(std::make_unique<ServiceRoot>(app));
- nodes.emplace_back(std::make_unique<NetworkProtocol>(app));
- nodes.emplace_back(std::make_unique<SessionService>(app));
- nodes.emplace_back(std::make_unique<EthernetCollection>(app));
- nodes.emplace_back(std::make_unique<EthernetInterface>(app));
- nodes.emplace_back(std::make_unique<Thermal>(app));
- nodes.emplace_back(std::make_unique<ManagerCollection>(app));
- nodes.emplace_back(std::make_unique<Manager>(app));
- nodes.emplace_back(std::make_unique<ChassisCollection>(app));
- nodes.emplace_back(std::make_unique<Chassis>(app));
- nodes.emplace_back(std::make_unique<UpdateService>(app));
- nodes.emplace_back(std::make_unique<SoftwareInventoryCollection>(app));
- nodes.emplace_back(std::make_unique<SoftwareInventory>(app));
- nodes.emplace_back(std::make_unique<VlanNetworkInterfaceCollection>(app));
- nodes.emplace_back(std::make_unique<SystemsCollection>(app));
- nodes.emplace_back(std::make_unique<Systems>(app));
+class RedfishService
+{
+ public:
+ /*
+ * @brief Redfish service constructor
+ *
+ * Loads Redfish configuration and installs schema resources
+ *
+ * @param[in] app Crow app on which Redfish will initialize
+ */
+ RedfishService(CrowApp& app)
+ {
+ nodes.emplace_back(std::make_unique<AccountService>(app));
+ nodes.emplace_back(std::make_unique<SessionCollection>(app));
+ nodes.emplace_back(std::make_unique<Roles>(app));
+ nodes.emplace_back(std::make_unique<RoleCollection>(app));
+ nodes.emplace_back(std::make_unique<ServiceRoot>(app));
+ nodes.emplace_back(std::make_unique<NetworkProtocol>(app));
+ nodes.emplace_back(std::make_unique<SessionService>(app));
+ nodes.emplace_back(std::make_unique<EthernetCollection>(app));
+ nodes.emplace_back(std::make_unique<EthernetInterface>(app));
+ nodes.emplace_back(std::make_unique<Thermal>(app));
+ nodes.emplace_back(std::make_unique<ManagerCollection>(app));
+ nodes.emplace_back(std::make_unique<Manager>(app));
+ nodes.emplace_back(std::make_unique<ChassisCollection>(app));
+ nodes.emplace_back(std::make_unique<Chassis>(app));
+ nodes.emplace_back(std::make_unique<UpdateService>(app));
+ nodes.emplace_back(std::make_unique<SoftwareInventoryCollection>(app));
+ nodes.emplace_back(std::make_unique<SoftwareInventory>(app));
+ nodes.emplace_back(
+ std::make_unique<VlanNetworkInterfaceCollection>(app));
+ nodes.emplace_back(std::make_unique<SystemsCollection>(app));
+ nodes.emplace_back(std::make_unique<Systems>(app));
- for (auto& node : nodes) {
- node->getSubRoutes(nodes);
+ for (auto& node : nodes)
+ {
+ node->getSubRoutes(nodes);
+ }
}
- }
- private:
- std::vector<std::unique_ptr<Node>> nodes;
+ private:
+ std::vector<std::unique_ptr<Node>> nodes;
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp
index 25ac954..bde81ce 100644
--- a/redfish-core/include/utils/json_utils.hpp
+++ b/redfish-core/include/utils/json_utils.hpp
@@ -14,26 +14,36 @@
// limitations under the License.
*/
#pragma once
-#include <nlohmann/json.hpp>
#include <crow/http_request.h>
#include <crow/http_response.h>
-namespace redfish {
+#include <nlohmann/json.hpp>
-namespace json_util {
+namespace redfish
+{
+
+namespace json_util
+{
/**
* @brief Defines JSON utils operation status
*/
-enum class Result { SUCCESS, NOT_EXIST, WRONG_TYPE, NULL_POINTER };
+enum class Result
+{
+ SUCCESS,
+ NOT_EXIST,
+ WRONG_TYPE,
+ NULL_POINTER
+};
/**
* @brief Describes JSON utils messages requirement
*/
-enum class MessageSetting {
- NONE = 0x0, ///< No messages will be added
- MISSING = 0x1, ///< PropertyMissing message will be added
- TYPE_ERROR = 0x2 ///< PropertyValueTypeError message will be added
+enum class MessageSetting
+{
+ NONE = 0x0, ///< No messages will be added
+ MISSING = 0x1, ///< PropertyMissing message will be added
+ TYPE_ERROR = 0x2 ///< PropertyValueTypeError message will be added
};
/**
@@ -287,6 +297,6 @@
bool processJsonFromRequest(crow::Response& res, const crow::Request& req,
nlohmann::json& reqJson);
-} // namespace json_util
+} // namespace json_util
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 47b4c4c..c58cafd 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -17,40 +17,45 @@
#include "node.hpp"
-namespace redfish {
+namespace redfish
+{
-class AccountService : public Node {
- public:
- AccountService(CrowApp& app) : Node(app, "/redfish/v1/AccountService/") {
- Node::json["@odata.id"] = "/redfish/v1/AccountService";
- Node::json["@odata.type"] = "#AccountService.v1_1_0.AccountService";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#AccountService.AccountService";
- Node::json["Id"] = "AccountService";
- Node::json["Description"] = "BMC User Accounts";
- Node::json["Name"] = "Account Service";
- Node::json["ServiceEnabled"] = true;
- Node::json["MinPasswordLength"] = 1;
- Node::json["MaxPasswordLength"] = 20;
- Node::json["Accounts"]["@odata.id"] = "/redfish/v1/AccountService/Accounts";
- Node::json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles";
+class AccountService : public Node
+{
+ public:
+ AccountService(CrowApp& app) : Node(app, "/redfish/v1/AccountService/")
+ {
+ Node::json["@odata.id"] = "/redfish/v1/AccountService";
+ Node::json["@odata.type"] = "#AccountService.v1_1_0.AccountService";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#AccountService.AccountService";
+ Node::json["Id"] = "AccountService";
+ Node::json["Description"] = "BMC User Accounts";
+ Node::json["Name"] = "Account Service";
+ Node::json["ServiceEnabled"] = true;
+ Node::json["MinPasswordLength"] = 1;
+ Node::json["MaxPasswordLength"] = 20;
+ Node::json["Accounts"]["@odata.id"] =
+ "/redfish/v1/AccountService/Accounts";
+ Node::json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles";
- entityPrivileges = {
- {boost::beast::http::verb::get,
- {{"ConfigureUsers"}, {"ConfigureManager"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureUsers"}}},
- {boost::beast::http::verb::put, {{"ConfigureUsers"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}},
- {boost::beast::http::verb::post, {{"ConfigureUsers"}}}};
- }
+ entityPrivileges = {
+ {boost::beast::http::verb::get,
+ {{"ConfigureUsers"}, {"ConfigureManager"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureUsers"}}},
+ {boost::beast::http::verb::put, {{"ConfigureUsers"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureUsers"}}},
+ {boost::beast::http::verb::post, {{"ConfigureUsers"}}}};
+ }
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- res.jsonValue = Node::json;
- res.end();
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ res.jsonValue = Node::json;
+ res.end();
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index b1c20a5..7b68a27 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -16,9 +16,11 @@
#pragma once
#include "node.hpp"
+
#include <boost/container/flat_map.hpp>
-namespace redfish {
+namespace redfish
+{
/**
* DBus types primitives for several generic DBus interfaces
@@ -47,220 +49,251 @@
* This perhaps shall be different file, which has to be chosen on compile time
* depending on OEM needs
*/
-class OnDemandChassisProvider {
- public:
- /**
- * Function that retrieves all Chassis available through EntityManager.
- * @param callback a function that shall be called to convert Dbus output into
- * JSON.
- */
- template <typename CallbackFunc>
- void getChassisList(CallbackFunc &&callback) {
- const std::array<const char *, 4> interfaces = {
- "xyz.openbmc_project.Inventory.Item.Board",
- "xyz.openbmc_project.Inventory.Item.Chassis",
- "xyz.openbmc_project.Inventory.Item.PowerSupply",
- "xyz.openbmc_project.Inventory.Item.System",
+class OnDemandChassisProvider
+{
+ public:
+ /**
+ * Function that retrieves all Chassis available through EntityManager.
+ * @param callback a function that shall be called to convert Dbus output
+ * into JSON.
+ */
+ template <typename CallbackFunc>
+ void getChassisList(CallbackFunc &&callback)
+ {
+ const std::array<const char *, 4> interfaces = {
+ "xyz.openbmc_project.Inventory.Item.Board",
+ "xyz.openbmc_project.Inventory.Item.Chassis",
+ "xyz.openbmc_project.Inventory.Item.PowerSupply",
+ "xyz.openbmc_project.Inventory.Item.System",
+ };
+ crow::connections::systemBus->async_method_call(
+ [callback{std::move(callback)}](
+ const boost::system::error_code error_code,
+ const std::vector<std::string> &resp) {
+ // Callback requires vector<string> to retrieve all available
+ // chassis list.
+ std::vector<std::string> chassisList;
+ if (error_code)
+ {
+ // Something wrong on DBus, the error_code is not important
+ // at this moment, just return success=false, and empty
+ // output. Since size of vector may vary depending on
+ // information from Entity Manager, and empty output could
+ // not be treated same way as error.
+ callback(false, chassisList);
+ return;
+ }
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::string &objpath : resp)
+ {
+ std::size_t lastPos = objpath.rfind("/");
+ if (lastPos != std::string::npos)
+ {
+ // and put it into output vector.
+ chassisList.emplace_back(objpath.substr(lastPos + 1));
+ }
+ }
+ // Finally make a callback with useful data
+ callback(true, chassisList);
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/inventory", int32_t(3), interfaces);
};
- crow::connections::systemBus->async_method_call(
- [callback{std::move(callback)}](
- const boost::system::error_code error_code,
- const std::vector<std::string> &resp) {
- // Callback requires vector<string> to retrieve all available chassis
- // list.
- std::vector<std::string> chassisList;
- if (error_code) {
- // Something wrong on DBus, the error_code is not important at this
- // moment, just return success=false, and empty output. Since size
- // of vector may vary depending on information from Entity Manager,
- // and empty output could not be treated same way as error.
- callback(false, chassisList);
- return;
- }
- // Iterate over all retrieved ObjectPaths.
- for (const std::string &objpath : resp) {
- std::size_t lastPos = objpath.rfind("/");
- if (lastPos != std::string::npos) {
- // and put it into output vector.
- chassisList.emplace_back(objpath.substr(lastPos + 1));
- }
- }
- // Finally make a callback with useful data
- callback(true, chassisList);
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
- "/xyz/openbmc_project/inventory", int32_t(3), interfaces);
- };
};
/**
* ChassisCollection derived class for delivering Chassis Collection Schema
*/
-class ChassisCollection : public Node {
- public:
- ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/") {
- Node::json["@odata.type"] = "#ChassisCollection.ChassisCollection";
- Node::json["@odata.id"] = "/redfish/v1/Chassis";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#ChassisCollection.ChassisCollection";
- Node::json["Name"] = "Chassis Collection";
+class ChassisCollection : public Node
+{
+ public:
+ ChassisCollection(CrowApp &app) : Node(app, "/redfish/v1/Chassis/")
+ {
+ Node::json["@odata.type"] = "#ChassisCollection.ChassisCollection";
+ Node::json["@odata.id"] = "/redfish/v1/Chassis";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#ChassisCollection.ChassisCollection";
+ Node::json["Name"] = "Chassis Collection";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
+ }
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // get chassis list, and call the below callback for JSON preparation
- chassisProvider.getChassisList(
- [&](const bool &success, const std::vector<std::string> &output) {
- if (success) {
- // ... prepare json array with appropriate @odata.id links
- nlohmann::json chassisArray = nlohmann::json::array();
- for (const std::string &chassisItem : output) {
- chassisArray.push_back(
- {{"@odata.id", "/redfish/v1/Chassis/" + chassisItem}});
- }
- // Then attach members, count size and return,
- Node::json["Members"] = chassisArray;
- Node::json["Members@odata.count"] = chassisArray.size();
- res.jsonValue = Node::json;
- } else {
- // ... otherwise, return INTERNALL ERROR
- res.result(boost::beast::http::status::internal_server_error);
- }
- res.end();
- });
- }
+ private:
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // get chassis list, and call the below callback for JSON preparation
+ chassisProvider.getChassisList(
+ [&](const bool &success, const std::vector<std::string> &output) {
+ if (success)
+ {
+ // ... prepare json array with appropriate @odata.id links
+ nlohmann::json chassisArray = nlohmann::json::array();
+ for (const std::string &chassisItem : output)
+ {
+ chassisArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Chassis/" + chassisItem}});
+ }
+ // Then attach members, count size and return,
+ Node::json["Members"] = chassisArray;
+ Node::json["Members@odata.count"] = chassisArray.size();
+ res.jsonValue = Node::json;
+ }
+ else
+ {
+ // ... otherwise, return INTERNALL ERROR
+ res.result(
+ boost::beast::http::status::internal_server_error);
+ }
+ res.end();
+ });
+ }
- // Chassis Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandChassisProvider chassisProvider;
+ // Chassis Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandChassisProvider chassisProvider;
};
/**
* Chassis override class for delivering Chassis Schema
*/
-class Chassis : public Node {
- public:
- Chassis(CrowApp &app)
- : Node(app, "/redfish/v1/Chassis/<str>/", std::string()) {
- Node::json["@odata.type"] = "#Chassis.v1_4_0.Chassis";
- Node::json["@odata.id"] = "/redfish/v1/Chassis";
- Node::json["@odata.context"] = "/redfish/v1/$metadata#Chassis.Chassis";
- Node::json["Name"] = "Chassis Collection";
- Node::json["ChassisType"] = "RackMount";
+class Chassis : public Node
+{
+ public:
+ Chassis(CrowApp &app) :
+ Node(app, "/redfish/v1/Chassis/<str>/", std::string())
+ {
+ Node::json["@odata.type"] = "#Chassis.v1_4_0.Chassis";
+ Node::json["@odata.id"] = "/redfish/v1/Chassis";
+ Node::json["@odata.context"] = "/redfish/v1/$metadata#Chassis.Chassis";
+ Node::json["Name"] = "Chassis Collection";
+ Node::json["ChassisType"] = "RackMount";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // Check if there is required param, truly entering this shall be
- // impossible.
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- res.jsonValue = Node::json;
- const std::string &chassisId = params[0];
- crow::connections::systemBus->async_method_call(
- [&res, chassisId(std::string(chassisId)) ](
- const boost::system::error_code error_code,
- const std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>>
- &subtree) {
- if (error_code) {
- res.jsonValue = {};
+ private:
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // Check if there is required param, truly entering this shall be
+ // impossible.
+ if (params.size() != 1)
+ {
res.result(boost::beast::http::status::internal_server_error);
res.end();
return;
- }
- // Iterate over all retrieved ObjectPaths.
- for (const std::pair<std::string,
- std::vector<std::pair<std::string,
- std::vector<std::string>>>>
- &object : subtree) {
- const std::string &path = object.first;
- const std::vector<std::pair<std::string, std::vector<std::string>>>
- &connectionNames = object.second;
+ }
- if (!boost::ends_with(path, chassisId)) {
- continue;
- }
- if (connectionNames.size() < 1) {
- BMCWEB_LOG_ERROR << "Only got " << connectionNames.size()
- << " Connection names";
- continue;
- }
+ res.jsonValue = Node::json;
+ const std::string &chassisId = params[0];
+ crow::connections::systemBus->async_method_call(
+ [&res, chassisId(std::string(chassisId))](
+ const boost::system::error_code error_code,
+ const std::vector<std::pair<
+ std::string, std::vector<std::pair<
+ std::string, std::vector<std::string>>>>>
+ &subtree) {
+ if (error_code)
+ {
+ res.jsonValue = {};
+ res.result(
+ boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::pair<
+ std::string,
+ std::vector<
+ std::pair<std::string, std::vector<std::string>>>>
+ &object : subtree)
+ {
+ const std::string &path = object.first;
+ const std::vector<
+ std::pair<std::string, std::vector<std::string>>>
+ &connectionNames = object.second;
- const std::string connectionName = connectionNames[0].first;
- crow::connections::systemBus->async_method_call(
- [&res, chassisId(std::string(chassisId)) ](
- const boost::system::error_code error_code,
- const std::vector<std::pair<std::string, VariantType>>
- &propertiesList) {
- for (const std::pair<std::string, VariantType> &property :
- propertiesList) {
- const std::string *value =
- mapbox::getPtr<const std::string>(property.second);
- if (value != nullptr) {
- res.jsonValue[property.first] = *value;
+ if (!boost::ends_with(path, chassisId))
+ {
+ continue;
}
- }
- res.jsonValue["Name"] = chassisId;
- res.jsonValue["Id"] = chassisId;
- res.jsonValue["Thermal"] = {
- {"@odata.id",
- "/redfish/v1/Chassis/" + chassisId + "/Thermal"}};
- res.end();
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
- // Found the Connection we were looking for, return
- return;
- }
+ if (connectionNames.size() < 1)
+ {
+ BMCWEB_LOG_ERROR << "Only got "
+ << connectionNames.size()
+ << " Connection names";
+ continue;
+ }
- // Couldn't find an object with that name. return an error
- res.result(boost::beast::http::status::not_found);
+ const std::string connectionName = connectionNames[0].first;
+ crow::connections::systemBus->async_method_call(
+ [&res, chassisId(std::string(chassisId))](
+ const boost::system::error_code error_code,
+ const std::vector<std::pair<
+ std::string, VariantType>> &propertiesList) {
+ for (const std::pair<std::string, VariantType>
+ &property : propertiesList)
+ {
+ const std::string *value =
+ mapbox::getPtr<const std::string>(
+ property.second);
+ if (value != nullptr)
+ {
+ res.jsonValue[property.first] = *value;
+ }
+ }
+ res.jsonValue["Name"] = chassisId;
+ res.jsonValue["Id"] = chassisId;
+ res.jsonValue["Thermal"] = {
+ {"@odata.id", "/redfish/v1/Chassis/" +
+ chassisId + "/Thermal"}};
+ res.end();
+ },
+ connectionName, path, "org.freedesktop.DBus.Properties",
+ "GetAll",
+ "xyz.openbmc_project.Inventory.Decorator.Asset");
+ // Found the Connection we were looking for, return
+ return;
+ }
- res.end();
- },
- "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.Decorator.Asset"});
- }
+ // Couldn't find an object with that name. return an error
+ res.result(boost::beast::http::status::not_found);
- // Chassis Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandChassisProvider chassisProvider;
-}; // namespace redfish
+ res.end();
+ },
+ "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.Decorator.Asset"});
+ }
-} // namespace redfish
+ // Chassis Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandChassisProvider chassisProvider;
+}; // namespace redfish
+
+} // namespace redfish
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 01111a4..0c64279 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -15,13 +15,14 @@
*/
#pragma once
+#include <boost/container/flat_map.hpp>
#include <dbus_singleton.hpp>
#include <error_messages.hpp>
#include <node.hpp>
#include <utils/json_utils.hpp>
-#include <boost/container/flat_map.hpp>
-namespace redfish {
+namespace redfish
+{
/**
* DBus types primitives for several generic DBus interfaces
@@ -45,35 +46,40 @@
* Structure for keeping IPv4 data required by Redfish
* TODO(Pawel) consider change everything to ptr, or to non-ptr values.
*/
-struct IPv4AddressData {
- std::string id;
- const std::string *address;
- const std::string *domain;
- const std::string *gateway;
- std::string netmask;
- std::string origin;
- bool global;
- /**
- * @brief Operator< to enable sorting
- *
- * @param[in] obj Object to compare with
- *
- * @return This object id < supplied object id
- */
- bool operator<(const IPv4AddressData &obj) const { return (id < obj.id); }
+struct IPv4AddressData
+{
+ std::string id;
+ const std::string *address;
+ const std::string *domain;
+ const std::string *gateway;
+ std::string netmask;
+ std::string origin;
+ bool global;
+ /**
+ * @brief Operator< to enable sorting
+ *
+ * @param[in] obj Object to compare with
+ *
+ * @return This object id < supplied object id
+ */
+ bool operator<(const IPv4AddressData &obj) const
+ {
+ return (id < obj.id);
+ }
};
/**
* Structure for keeping basic single Ethernet Interface information
* available from DBus
*/
-struct EthernetInterfaceData {
- const unsigned int *speed;
- const bool *autoNeg;
- const std::string *hostname;
- const std::string *defaultGateway;
- const std::string *macAddress;
- const unsigned int *vlanId;
+struct EthernetInterfaceData
+{
+ const unsigned int *speed;
+ const bool *autoNeg;
+ const std::string *hostname;
+ const std::string *defaultGateway;
+ const std::string *macAddress;
+ const unsigned int *vlanId;
};
/**
@@ -85,1264 +91,1493 @@
* This perhaps shall be different file, which has to be chosen on compile time
* depending on OEM needs
*/
-class OnDemandEthernetProvider {
- private:
- // Consts that may have influence on EthernetProvider performance/memory usage
- const size_t maxIpV4AddressesPerInterface = 10;
+class OnDemandEthernetProvider
+{
+ private:
+ // Consts that may have influence on EthernetProvider performance/memory
+ // usage
+ const size_t maxIpV4AddressesPerInterface = 10;
- // Helper function that allows to extract GetAllPropertiesType from
- // GetManagedObjectsType, based on object path, and interface name
- const PropertiesMapType *extractInterfaceProperties(
- const sdbusplus::message::object_path &objpath,
- const std::string &interface, const GetManagedObjectsType &dbus_data) {
- const auto &dbusObj = dbus_data.find(objpath);
- if (dbusObj != dbus_data.end()) {
- const auto &iface = dbusObj->second.find(interface);
- if (iface != dbusObj->second.end()) {
- return &iface->second;
- }
- }
- return nullptr;
- }
-
- // Helper Wrapper that does inline object_path conversion from string
- // into sdbusplus::message::object_path type
- inline const PropertiesMapType *extractInterfaceProperties(
- const std::string &objpath, const std::string &interface,
- const GetManagedObjectsType &dbus_data) {
- const auto &dbusObj = sdbusplus::message::object_path{objpath};
- return extractInterfaceProperties(dbusObj, interface, dbus_data);
- }
-
- // Helper function that allows to get pointer to the property from
- // GetAllPropertiesType native, or extracted by GetAllPropertiesType
- template <typename T>
- inline T const *const extractProperty(const PropertiesMapType &properties,
- const std::string &name) {
- const auto &property = properties.find(name);
- if (property != properties.end()) {
- return mapbox::getPtr<const T>(property->second);
- }
- return nullptr;
- }
- // TODO(Pawel) Consider to move the above functions to dbus
- // generic_interfaces.hpp
-
- // Helper function that extracts data from several dbus objects and several
- // interfaces required by single ethernet interface instance
- void extractEthernetInterfaceData(const std::string ðifaceId,
- const GetManagedObjectsType &dbus_data,
- EthernetInterfaceData ð_data) {
- // Extract data that contains MAC Address
- const PropertiesMapType *macProperties = extractInterfaceProperties(
- "/xyz/openbmc_project/network/" + ethifaceId,
- "xyz.openbmc_project.Network.MACAddress", dbus_data);
-
- if (macProperties != nullptr) {
- eth_data.macAddress =
- extractProperty<std::string>(*macProperties, "MACAddress");
- }
-
- const PropertiesMapType *vlanProperties = extractInterfaceProperties(
- "/xyz/openbmc_project/network/" + ethifaceId,
- "xyz.openbmc_project.Network.VLAN", dbus_data);
-
- if (vlanProperties != nullptr) {
- eth_data.vlanId = extractProperty<unsigned int>(*vlanProperties, "Id");
- }
-
- // Extract data that contains link information (auto negotiation and speed)
- const PropertiesMapType *ethProperties = extractInterfaceProperties(
- "/xyz/openbmc_project/network/" + ethifaceId,
- "xyz.openbmc_project.Network.EthernetInterface", dbus_data);
-
- if (ethProperties != nullptr) {
- eth_data.autoNeg = extractProperty<bool>(*ethProperties, "AutoNeg");
- eth_data.speed = extractProperty<unsigned int>(*ethProperties, "Speed");
- }
-
- // Extract data that contains network config (HostName and DefaultGW)
- const PropertiesMapType *configProperties = extractInterfaceProperties(
- "/xyz/openbmc_project/network/config",
- "xyz.openbmc_project.Network.SystemConfiguration", dbus_data);
-
- if (configProperties != nullptr) {
- eth_data.hostname =
- extractProperty<std::string>(*configProperties, "HostName");
- eth_data.defaultGateway =
- extractProperty<std::string>(*configProperties, "DefaultGateway");
- }
- }
-
- // Helper function that changes bits netmask notation (i.e. /24)
- // into full dot notation
- inline std::string getNetmask(unsigned int bits) {
- uint32_t value = 0xffffffff << (32 - bits);
- std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
- std::to_string((value >> 16) & 0xff) + "." +
- std::to_string((value >> 8) & 0xff) + "." +
- std::to_string(value & 0xff);
- return netmask;
- }
-
- // Helper function that extracts data for single ethernet ipv4 address
- void extractIPv4Data(const std::string ðifaceId,
- const GetManagedObjectsType &dbus_data,
- std::vector<IPv4AddressData> &ipv4_config) {
- const std::string pathStart =
- "/xyz/openbmc_project/network/" + ethifaceId + "/ipv4/";
-
- // Since there might be several IPv4 configurations aligned with
- // single ethernet interface, loop over all of them
- for (auto &objpath : dbus_data) {
- // Check if proper patter for object path appears
- if (boost::starts_with(static_cast<const std::string &>(objpath.first),
- pathStart)) {
- // and get approrpiate interface
- const auto &interface =
- objpath.second.find("xyz.openbmc_project.Network.IP");
- if (interface != objpath.second.end()) {
- // Make a properties 'shortcut', to make everything more readable
- const PropertiesMapType &properties = interface->second;
- // Instance IPv4AddressData structure, and set as appropriate
- IPv4AddressData ipv4Address;
-
- ipv4Address.id = static_cast<const std::string &>(objpath.first)
- .substr(pathStart.size());
-
- // IPv4 address
- ipv4Address.address =
- extractProperty<std::string>(properties, "Address");
- // IPv4 gateway
- ipv4Address.gateway =
- extractProperty<std::string>(properties, "Gateway");
-
- // Origin is kind of DBus object so fetch pointer...
- const std::string *origin =
- extractProperty<std::string>(properties, "Origin");
- if (origin != nullptr) {
- ipv4Address.origin =
- translateAddressOriginBetweenDBusAndRedfish(origin, true, true);
- }
-
- // Netmask is presented as PrefixLength
- const auto *mask =
- extractProperty<uint8_t>(properties, "PrefixLength");
- if (mask != nullptr) {
- // convert it to the string
- ipv4Address.netmask = getNetmask(*mask);
- }
-
- // Attach IPv4 only if address is present
- if (ipv4Address.address != nullptr) {
- // Check if given address is local, or global
- if (boost::starts_with(*ipv4Address.address, "169.254")) {
- ipv4Address.global = false;
- } else {
- ipv4Address.global = true;
+ // Helper function that allows to extract GetAllPropertiesType from
+ // GetManagedObjectsType, based on object path, and interface name
+ const PropertiesMapType *extractInterfaceProperties(
+ const sdbusplus::message::object_path &objpath,
+ const std::string &interface, const GetManagedObjectsType &dbus_data)
+ {
+ const auto &dbusObj = dbus_data.find(objpath);
+ if (dbusObj != dbus_data.end())
+ {
+ const auto &iface = dbusObj->second.find(interface);
+ if (iface != dbusObj->second.end())
+ {
+ return &iface->second;
}
- ipv4_config.emplace_back(std::move(ipv4Address));
- }
}
- }
+ return nullptr;
+ }
+
+ // Helper Wrapper that does inline object_path conversion from string
+ // into sdbusplus::message::object_path type
+ inline const PropertiesMapType *
+ extractInterfaceProperties(const std::string &objpath,
+ const std::string &interface,
+ const GetManagedObjectsType &dbus_data)
+ {
+ const auto &dbusObj = sdbusplus::message::object_path{objpath};
+ return extractInterfaceProperties(dbusObj, interface, dbus_data);
+ }
+
+ // Helper function that allows to get pointer to the property from
+ // GetAllPropertiesType native, or extracted by GetAllPropertiesType
+ template <typename T>
+ inline T const *const extractProperty(const PropertiesMapType &properties,
+ const std::string &name)
+ {
+ const auto &property = properties.find(name);
+ if (property != properties.end())
+ {
+ return mapbox::getPtr<const T>(property->second);
+ }
+ return nullptr;
+ }
+ // TODO(Pawel) Consider to move the above functions to dbus
+ // generic_interfaces.hpp
+
+ // Helper function that extracts data from several dbus objects and several
+ // interfaces required by single ethernet interface instance
+ void extractEthernetInterfaceData(const std::string ðifaceId,
+ const GetManagedObjectsType &dbus_data,
+ EthernetInterfaceData ð_data)
+ {
+ // Extract data that contains MAC Address
+ const PropertiesMapType *macProperties = extractInterfaceProperties(
+ "/xyz/openbmc_project/network/" + ethifaceId,
+ "xyz.openbmc_project.Network.MACAddress", dbus_data);
+
+ if (macProperties != nullptr)
+ {
+ eth_data.macAddress =
+ extractProperty<std::string>(*macProperties, "MACAddress");
+ }
+
+ const PropertiesMapType *vlanProperties = extractInterfaceProperties(
+ "/xyz/openbmc_project/network/" + ethifaceId,
+ "xyz.openbmc_project.Network.VLAN", dbus_data);
+
+ if (vlanProperties != nullptr)
+ {
+ eth_data.vlanId =
+ extractProperty<unsigned int>(*vlanProperties, "Id");
+ }
+
+ // Extract data that contains link information (auto negotiation and
+ // speed)
+ const PropertiesMapType *ethProperties = extractInterfaceProperties(
+ "/xyz/openbmc_project/network/" + ethifaceId,
+ "xyz.openbmc_project.Network.EthernetInterface", dbus_data);
+
+ if (ethProperties != nullptr)
+ {
+ eth_data.autoNeg = extractProperty<bool>(*ethProperties, "AutoNeg");
+ eth_data.speed =
+ extractProperty<unsigned int>(*ethProperties, "Speed");
+ }
+
+ // Extract data that contains network config (HostName and DefaultGW)
+ const PropertiesMapType *configProperties = extractInterfaceProperties(
+ "/xyz/openbmc_project/network/config",
+ "xyz.openbmc_project.Network.SystemConfiguration", dbus_data);
+
+ if (configProperties != nullptr)
+ {
+ eth_data.hostname =
+ extractProperty<std::string>(*configProperties, "HostName");
+ eth_data.defaultGateway = extractProperty<std::string>(
+ *configProperties, "DefaultGateway");
+ }
+ }
+
+ // Helper function that changes bits netmask notation (i.e. /24)
+ // into full dot notation
+ inline std::string getNetmask(unsigned int bits)
+ {
+ uint32_t value = 0xffffffff << (32 - bits);
+ std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
+ std::to_string((value >> 16) & 0xff) + "." +
+ std::to_string((value >> 8) & 0xff) + "." +
+ std::to_string(value & 0xff);
+ return netmask;
+ }
+
+ // Helper function that extracts data for single ethernet ipv4 address
+ void extractIPv4Data(const std::string ðifaceId,
+ const GetManagedObjectsType &dbus_data,
+ std::vector<IPv4AddressData> &ipv4_config)
+ {
+ const std::string pathStart =
+ "/xyz/openbmc_project/network/" + ethifaceId + "/ipv4/";
+
+ // Since there might be several IPv4 configurations aligned with
+ // single ethernet interface, loop over all of them
+ for (auto &objpath : dbus_data)
+ {
+ // Check if proper patter for object path appears
+ if (boost::starts_with(
+ static_cast<const std::string &>(objpath.first), pathStart))
+ {
+ // and get approrpiate interface
+ const auto &interface =
+ objpath.second.find("xyz.openbmc_project.Network.IP");
+ if (interface != objpath.second.end())
+ {
+ // Make a properties 'shortcut', to make everything more
+ // readable
+ const PropertiesMapType &properties = interface->second;
+ // Instance IPv4AddressData structure, and set as
+ // appropriate
+ IPv4AddressData ipv4Address;
+
+ ipv4Address.id =
+ static_cast<const std::string &>(objpath.first)
+ .substr(pathStart.size());
+
+ // IPv4 address
+ ipv4Address.address =
+ extractProperty<std::string>(properties, "Address");
+ // IPv4 gateway
+ ipv4Address.gateway =
+ extractProperty<std::string>(properties, "Gateway");
+
+ // Origin is kind of DBus object so fetch pointer...
+ const std::string *origin =
+ extractProperty<std::string>(properties, "Origin");
+ if (origin != nullptr)
+ {
+ ipv4Address.origin =
+ translateAddressOriginBetweenDBusAndRedfish(
+ origin, true, true);
+ }
+
+ // Netmask is presented as PrefixLength
+ const auto *mask =
+ extractProperty<uint8_t>(properties, "PrefixLength");
+ if (mask != nullptr)
+ {
+ // convert it to the string
+ ipv4Address.netmask = getNetmask(*mask);
+ }
+
+ // Attach IPv4 only if address is present
+ if (ipv4Address.address != nullptr)
+ {
+ // Check if given address is local, or global
+ if (boost::starts_with(*ipv4Address.address, "169.254"))
+ {
+ ipv4Address.global = false;
+ }
+ else
+ {
+ ipv4Address.global = true;
+ }
+ ipv4_config.emplace_back(std::move(ipv4Address));
+ }
+ }
+ }
+ }
+
+ /**
+ * We have to sort this vector and ensure that order of IPv4 addresses
+ * is consistent between GETs to allow modification and deletion in
+ * PATCHes
+ */
+ std::sort(ipv4_config.begin(), ipv4_config.end());
+ }
+
+ static const constexpr int ipV4AddressSectionsCount = 4;
+
+ public:
+ /**
+ * @brief Creates VLAN for given interface with given Id through D-Bus
+ *
+ * @param[in] ifaceId Id of interface for which VLAN will be created
+ * @param[in] inputVlanId ID of the new VLAN
+ * @param[in] callback Function that will be called after the operation
+ *
+ * @return None.
+ */
+ template <typename CallbackFunc>
+ void createVlan(const std::string &ifaceId, const uint64_t &inputVlanId,
+ CallbackFunc &&callback)
+ {
+ crow::connections::systemBus->async_method_call(
+ callback, "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network",
+ "xyz.openbmc_project.Network.VLAN.Create", "VLAN", ifaceId,
+ static_cast<uint32_t>(inputVlanId));
+ };
+
+ /**
+ * @brief Sets given Id on the given VLAN interface through D-Bus
+ *
+ * @param[in] ifaceId Id of VLAN interface that should be modified
+ * @param[in] inputVlanId New ID of the VLAN
+ * @param[in] callback Function that will be called after the operation
+ *
+ * @return None.
+ */
+ template <typename CallbackFunc>
+ static void changeVlanId(const std::string &ifaceId,
+ const uint32_t &inputVlanId,
+ CallbackFunc &&callback)
+ {
+ crow::connections::systemBus->async_method_call(
+ callback, "xyz.openbmc_project.Network",
+ std::string("/xyz/openbmc_project/network/") + ifaceId,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.VLAN", "Id",
+ sdbusplus::message::variant<uint32_t>(inputVlanId));
+ };
+
+ /**
+ * @brief Helper function that verifies IP address to check if it is in
+ * proper format. If bits pointer is provided, also calculates active
+ * bit count for Subnet Mask.
+ *
+ * @param[in] ip IP that will be verified
+ * @param[out] bits Calculated mask in bits notation
+ *
+ * @return true in case of success, false otherwise
+ */
+ bool ipv4VerifyIpAndGetBitcount(const std::string &ip,
+ uint8_t *bits = nullptr)
+ {
+ std::vector<std::string> bytesInMask;
+
+ boost::split(bytesInMask, ip, boost::is_any_of("."));
+
+ if (bytesInMask.size() != ipV4AddressSectionsCount)
+ {
+ return false;
+ }
+
+ if (bits != nullptr)
+ {
+ *bits = 0;
+ }
+
+ char *endPtr;
+ long previousValue = 255;
+ bool firstZeroInByteHit;
+ for (const std::string &byte : bytesInMask)
+ {
+ if (byte.empty())
+ {
+ return false;
+ }
+
+ // Use strtol instead of stroi to avoid exceptions
+ long value = std::strtol(byte.c_str(), &endPtr, 10);
+
+ // endPtr should point to the end of the string, otherwise given
+ // string is not 100% number
+ if (*endPtr != '\0')
+ {
+ return false;
+ }
+
+ // Value should be contained in byte
+ if (value < 0 || value > 255)
+ {
+ return false;
+ }
+
+ if (bits != nullptr)
+ {
+ // Mask has to be continuous between bytes
+ if (previousValue != 255 && value != 0)
+ {
+ return false;
+ }
+
+ // Mask has to be continuous inside bytes
+ firstZeroInByteHit = false;
+
+ // Count bits
+ for (int bitIdx = 7; bitIdx >= 0; bitIdx--)
+ {
+ if (value & (1 << bitIdx))
+ {
+ if (firstZeroInByteHit)
+ {
+ // Continuity not preserved
+ return false;
+ }
+ else
+ {
+ (*bits)++;
+ }
+ }
+ else
+ {
+ firstZeroInByteHit = true;
+ }
+ }
+ }
+
+ previousValue = value;
+ }
+
+ return true;
}
/**
- * We have to sort this vector and ensure that order of IPv4 addresses
- * is consistent between GETs to allow modification and deletion in PATCHes
+ * @brief Changes IPv4 address type property (Address, Gateway)
+ *
+ * @param[in] ifaceId Id of interface whose IP should be modified
+ * @param[in] ipIdx index of IP in input array that should be modified
+ * @param[in] ipHash DBus Hash id of modified IP
+ * @param[in] name Name of field in JSON representation
+ * @param[in] newValue New value that should be written
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return true if give IP is valid and has been sent do D-Bus, false
+ * otherwise
*/
- std::sort(ipv4_config.begin(), ipv4_config.end());
- }
-
- static const constexpr int ipV4AddressSectionsCount = 4;
-
- public:
- /**
- * @brief Creates VLAN for given interface with given Id through D-Bus
- *
- * @param[in] ifaceId Id of interface for which VLAN will be created
- * @param[in] inputVlanId ID of the new VLAN
- * @param[in] callback Function that will be called after the operation
- *
- * @return None.
- */
- template <typename CallbackFunc>
- void createVlan(const std::string &ifaceId, const uint64_t &inputVlanId,
- CallbackFunc &&callback) {
- crow::connections::systemBus->async_method_call(
- callback, "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
- "xyz.openbmc_project.Network.VLAN.Create", "VLAN", ifaceId,
- static_cast<uint32_t>(inputVlanId));
- };
-
- /**
- * @brief Sets given Id on the given VLAN interface through D-Bus
- *
- * @param[in] ifaceId Id of VLAN interface that should be modified
- * @param[in] inputVlanId New ID of the VLAN
- * @param[in] callback Function that will be called after the operation
- *
- * @return None.
- */
- template <typename CallbackFunc>
- static void changeVlanId(const std::string &ifaceId,
- const uint32_t &inputVlanId,
- CallbackFunc &&callback) {
- crow::connections::systemBus->async_method_call(
- callback, "xyz.openbmc_project.Network",
- std::string("/xyz/openbmc_project/network/") + ifaceId,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.VLAN", "Id",
- sdbusplus::message::variant<uint32_t>(inputVlanId));
- };
-
- /**
- * @brief Helper function that verifies IP address to check if it is in
- * proper format. If bits pointer is provided, also calculates active
- * bit count for Subnet Mask.
- *
- * @param[in] ip IP that will be verified
- * @param[out] bits Calculated mask in bits notation
- *
- * @return true in case of success, false otherwise
- */
- bool ipv4VerifyIpAndGetBitcount(const std::string &ip,
- uint8_t *bits = nullptr) {
- std::vector<std::string> bytesInMask;
-
- boost::split(bytesInMask, ip, boost::is_any_of("."));
-
- if (bytesInMask.size() != ipV4AddressSectionsCount) {
- return false;
- }
-
- if (bits != nullptr) {
- *bits = 0;
- }
-
- char *endPtr;
- long previousValue = 255;
- bool firstZeroInByteHit;
- for (const std::string &byte : bytesInMask) {
- if (byte.empty()) {
- return false;
- }
-
- // Use strtol instead of stroi to avoid exceptions
- long value = std::strtol(byte.c_str(), &endPtr, 10);
-
- // endPtr should point to the end of the string, otherwise given string
- // is not 100% number
- if (*endPtr != '\0') {
- return false;
- }
-
- // Value should be contained in byte
- if (value < 0 || value > 255) {
- return false;
- }
-
- if (bits != nullptr) {
- // Mask has to be continuous between bytes
- if (previousValue != 255 && value != 0) {
- return false;
- }
-
- // Mask has to be continuous inside bytes
- firstZeroInByteHit = false;
-
- // Count bits
- for (int bitIdx = 7; bitIdx >= 0; bitIdx--) {
- if (value & (1 << bitIdx)) {
- if (firstZeroInByteHit) {
- // Continuity not preserved
- return false;
- } else {
- (*bits)++;
+ void changeIPv4AddressProperty(const std::string &ifaceId, int ipIdx,
+ const std::string &ipHash,
+ const std::string &name,
+ const std::string &newValue,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ auto callback = [asyncResp, ipIdx{std::move(ipIdx)},
+ name{std::move(name)}, newValue{std::move(newValue)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue, messages::internalError(),
+ "/IPv4Addresses/" + std::to_string(ipIdx) + "/" + name);
}
- } else {
- firstZeroInByteHit = true;
- }
- }
- }
-
- previousValue = value;
- }
-
- return true;
- }
-
- /**
- * @brief Changes IPv4 address type property (Address, Gateway)
- *
- * @param[in] ifaceId Id of interface whose IP should be modified
- * @param[in] ipIdx index of IP in input array that should be modified
- * @param[in] ipHash DBus Hash id of modified IP
- * @param[in] name Name of field in JSON representation
- * @param[in] newValue New value that should be written
- * @param[io] asyncResp Response object that will be returned to client
- *
- * @return true if give IP is valid and has been sent do D-Bus, false
- * otherwise
- */
- void changeIPv4AddressProperty(const std::string &ifaceId, int ipIdx,
- const std::string &ipHash,
- const std::string &name,
- const std::string &newValue,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- auto callback = [
- asyncResp, ipIdx{std::move(ipIdx)}, name{std::move(name)},
- newValue{std::move(newValue)}
- ](const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::internalError(),
- "/IPv4Addresses/" + std::to_string(ipIdx) + "/" + name);
- } else {
- asyncResp->res.jsonValue["IPv4Addresses"][ipIdx][name] = newValue;
- }
- };
-
- crow::connections::systemBus->async_method_call(
- std::move(callback), "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.IP", name,
- sdbusplus::message::variant<std::string>(newValue));
- };
-
- /**
- * @brief Changes IPv4 address origin property
- *
- * @param[in] ifaceId Id of interface whose IP should be modified
- * @param[in] ipIdx index of IP in input array that should be modified
- * @param[in] ipHash DBus Hash id of modified IP
- * @param[in] newValue New value in Redfish format
- * @param[in] newValueDbus New value in D-Bus format
- * @param[io] asyncResp Response object that will be returned to client
- *
- * @return true if give IP is valid and has been sent do D-Bus, false
- * otherwise
- */
- void changeIPv4Origin(const std::string &ifaceId, int ipIdx,
- const std::string &ipHash, const std::string &newValue,
- const std::string &newValueDbus,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- auto callback =
- [ asyncResp, ipIdx{std::move(ipIdx)},
- newValue{std::move(newValue)} ](const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::internalError(),
- "/IPv4Addresses/" + std::to_string(ipIdx) + "/AddressOrigin");
- } else {
- asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["AddressOrigin"] =
- newValue;
- }
- };
-
- crow::connections::systemBus->async_method_call(
- std::move(callback), "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.IP", "Origin",
- sdbusplus::message::variant<std::string>(newValueDbus));
- };
-
- /**
- * @brief Modifies SubnetMask for given IP
- *
- * @param[in] ifaceId Id of interface whose IP should be modified
- * @param[in] ipIdx index of IP in input array that should be modified
- * @param[in] ipHash DBus Hash id of modified IP
- * @param[in] newValueStr Mask in dot notation as string
- * @param[in] newValue Mask as PrefixLength in bitcount
- * @param[io] asyncResp Response object that will be returned to client
- *
- * @return None
- */
- void changeIPv4SubnetMaskProperty(
- const std::string &ifaceId, int ipIdx, const std::string &ipHash,
- const std::string &newValueStr, uint8_t &newValue,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- auto callback = [
- asyncResp, ipIdx{std::move(ipIdx)}, newValueStr{std::move(newValueStr)}
- ](const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::internalError(),
- "/IPv4Addresses/" + std::to_string(ipIdx) + "/SubnetMask");
- } else {
- asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["SubnetMask"] =
- newValueStr;
- }
- };
-
- crow::connections::systemBus->async_method_call(
- std::move(callback), "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.IP", "PrefixLength",
- sdbusplus::message::variant<uint8_t>(newValue));
- };
-
- /**
- * @brief Disables VLAN with given ifaceId
- *
- * @param[in] ifaceId Id of VLAN interface that should be disabled
- * @param[in] callback Function that will be called after the operation
- *
- * @return None.
- */
- template <typename CallbackFunc>
- static void disableVlan(const std::string &ifaceId, CallbackFunc &&callback) {
- crow::connections::systemBus->async_method_call(
- callback, "xyz.openbmc_project.Network",
- std::string("/xyz/openbmc_project/network/") + ifaceId,
- "xyz.openbmc_project.Object.Delete", "Delete");
- };
-
- /**
- * @brief Sets given HostName of the machine through D-Bus
- *
- * @param[in] newHostname New name that HostName will be changed to
- * @param[in] callback Function that will be called after the operation
- *
- * @return None.
- */
- template <typename CallbackFunc>
- void setHostName(const std::string &newHostname, CallbackFunc &&callback) {
- crow::connections::systemBus->async_method_call(
- callback, "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/config",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
- sdbusplus::message::variant<std::string>(newHostname));
- };
-
- /**
- * @brief Deletes given IPv4
- *
- * @param[in] ifaceId Id of interface whose IP should be deleted
- * @param[in] ipIdx index of IP in input array that should be deleted
- * @param[in] ipHash DBus Hash id of IP that should be deleted
- * @param[io] asyncResp Response object that will be returned to client
- *
- * @return None
- */
- void deleteIPv4(const std::string &ifaceId, const std::string &ipHash,
- unsigned int ipIdx,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- crow::connections::systemBus->async_method_call(
- [ ipIdx{std::move(ipIdx)}, asyncResp{std::move(asyncResp)} ](
- const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::internalError(),
- "/IPv4Addresses/" + std::to_string(ipIdx) + "/");
- } else {
- asyncResp->res.jsonValue["IPv4Addresses"][ipIdx] = nullptr;
- }
- },
- "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
- "xyz.openbmc_project.Object.Delete", "Delete");
- }
-
- /**
- * @brief Creates IPv4 with given data
- *
- * @param[in] ifaceId Id of interface whose IP should be deleted
- * @param[in] ipIdx index of IP in input array that should be deleted
- * @param[in] ipHash DBus Hash id of IP that should be deleted
- * @param[io] asyncResp Response object that will be returned to client
- *
- * @return None
- */
- void createIPv4(const std::string &ifaceId, unsigned int ipIdx,
- uint8_t subnetMask, const std::string &gateway,
- const std::string &address,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- auto createIpHandler = [
- ipIdx{std::move(ipIdx)}, asyncResp{std::move(asyncResp)}
- ](const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::internalError(),
- "/IPv4Addresses/" + std::to_string(ipIdx) + "/");
- }
- };
-
- crow::connections::systemBus->async_method_call(
- std::move(createIpHandler), "xyz.openbmc_project.Network",
- "/xyz/openbmc_project/network/" + ifaceId,
- "xyz.openbmc_project.Network.IP.Create", "IP",
- "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask,
- gateway);
- }
-
- /**
- * @brief Translates Address Origin value from D-Bus to Redfish format and
- * vice-versa
- *
- * @param[in] inputOrigin Input value that should be translated
- * @param[in] isIPv4 True for IPv4 origins, False for IPv6
- * @param[in] isFromDBus True for DBus->Redfish conversion, false for reverse
- *
- * @return Empty string in case of failure, translated value otherwise
- */
- std::string translateAddressOriginBetweenDBusAndRedfish(
- const std::string *inputOrigin, bool isIPv4, bool isFromDBus) {
- // Invalid pointer
- if (inputOrigin == nullptr) {
- return "";
- }
-
- static const constexpr unsigned int firstIPv4OnlyIdx = 1;
- static const constexpr unsigned int firstIPv6OnlyIdx = 3;
-
- std::array<std::pair<const char *, const char *>, 6> translationTable{
- {{"xyz.openbmc_project.Network.IP.AddressOrigin.Static", "Static"},
- {"xyz.openbmc_project.Network.IP.AddressOrigin.DHCP", "DHCP"},
- {"xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal",
- "IPv4LinkLocal"},
- {"xyz.openbmc_project.Network.IP.AddressOrigin.DHCP", "DHCPv6"},
- {"xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal",
- "LinkLocal"},
- {"xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC", "SLAAC"}}};
-
- for (unsigned int i = 0; i < translationTable.size(); i++) {
- // Skip unrelated
- if (isIPv4 && i >= firstIPv6OnlyIdx) break;
- if (!isIPv4 && i >= firstIPv4OnlyIdx && i < firstIPv6OnlyIdx) continue;
-
- // When translating D-Bus to Redfish compare input to first element
- if (isFromDBus && translationTable[i].first == *inputOrigin)
- return translationTable[i].second;
-
- // When translating Redfish to D-Bus compare input to second element
- if (!isFromDBus && translationTable[i].second == *inputOrigin)
- return translationTable[i].first;
- }
-
- // If we are still here, that means that value has not been found
- return "";
- }
-
- /**
- * Function that retrieves all properties for given Ethernet Interface
- * Object
- * from EntityManager Network Manager
- * @param ethifaceId a eth interface id to query on DBus
- * @param callback a function that shall be called to convert Dbus output
- * into JSON
- */
- template <typename CallbackFunc>
- void getEthernetIfaceData(const std::string ðifaceId,
- CallbackFunc &&callback) {
- crow::connections::systemBus->async_method_call(
- [
- this, ethifaceId{std::move(ethifaceId)}, callback{std::move(callback)}
- ](const boost::system::error_code error_code,
- const GetManagedObjectsType &resp) {
- EthernetInterfaceData ethData{};
- std::vector<IPv4AddressData> ipv4Data;
- ipv4Data.reserve(maxIpV4AddressesPerInterface);
-
- if (error_code) {
- // Something wrong on DBus, the error_code is not important at
- // this moment, just return success=false, and empty output. Since
- // size of vector may vary depending on information from Network
- // Manager, and empty output could not be treated same way as
- // error.
- callback(false, ethData, ipv4Data);
- return;
- }
-
- // Find interface
- if (resp.find("/xyz/openbmc_project/network/" + ethifaceId) ==
- resp.end()) {
- // Interface has not been found
- callback(false, ethData, ipv4Data);
- return;
- }
-
- extractEthernetInterfaceData(ethifaceId, resp, ethData);
- extractIPv4Data(ethifaceId, resp, ipv4Data);
-
- // Fix global GW
- for (IPv4AddressData &ipv4 : ipv4Data) {
- if ((ipv4.global) &&
- ((ipv4.gateway == nullptr) || (*ipv4.gateway == "0.0.0.0"))) {
- ipv4.gateway = ethData.defaultGateway;
+ else
+ {
+ asyncResp->res.jsonValue["IPv4Addresses"][ipIdx][name] =
+ newValue;
}
- }
+ };
- // Finally make a callback with useful data
- callback(true, ethData, ipv4Data);
- },
- "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- };
+ crow::connections::systemBus->async_method_call(
+ std::move(callback), "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.IP", name,
+ sdbusplus::message::variant<std::string>(newValue));
+ };
- /**
- * Function that retrieves all Ethernet Interfaces available through Network
- * Manager
- * @param callback a function that shall be called to convert Dbus output into
- * JSON.
- */
- template <typename CallbackFunc>
- void getEthernetIfaceList(CallbackFunc &&callback) {
- crow::connections::systemBus->async_method_call(
- [ this, callback{std::move(callback)} ](
- const boost::system::error_code error_code,
- GetManagedObjectsType &resp) {
- // Callback requires vector<string> to retrieve all available ethernet
- // interfaces
- std::vector<std::string> ifaceList;
- ifaceList.reserve(resp.size());
- if (error_code) {
- // Something wrong on DBus, the error_code is not important at this
- // moment, just return success=false, and empty output. Since size
- // of vector may vary depending on information from Network Manager,
- // and empty output could not be treated same way as error.
- callback(false, ifaceList);
- return;
- }
+ /**
+ * @brief Changes IPv4 address origin property
+ *
+ * @param[in] ifaceId Id of interface whose IP should be modified
+ * @param[in] ipIdx index of IP in input array that should be
+ * modified
+ * @param[in] ipHash DBus Hash id of modified IP
+ * @param[in] newValue New value in Redfish format
+ * @param[in] newValueDbus New value in D-Bus format
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return true if give IP is valid and has been sent do D-Bus, false
+ * otherwise
+ */
+ void changeIPv4Origin(const std::string &ifaceId, int ipIdx,
+ const std::string &ipHash,
+ const std::string &newValue,
+ const std::string &newValueDbus,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ auto callback = [asyncResp, ipIdx{std::move(ipIdx)},
+ newValue{std::move(newValue)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue, messages::internalError(),
+ "/IPv4Addresses/" + std::to_string(ipIdx) +
+ "/AddressOrigin");
+ }
+ else
+ {
+ asyncResp->res
+ .jsonValue["IPv4Addresses"][ipIdx]["AddressOrigin"] =
+ newValue;
+ }
+ };
- // Iterate over all retrieved ObjectPaths.
- for (auto &objpath : resp) {
- // And all interfaces available for certain ObjectPath.
- for (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") {
- // Cut out everything until last "/", ...
- const std::string &ifaceId =
- static_cast<const std::string &>(objpath.first);
- std::size_t lastPos = ifaceId.rfind("/");
- if (lastPos != std::string::npos) {
- // and put it into output vector.
- ifaceList.emplace_back(ifaceId.substr(lastPos + 1));
+ crow::connections::systemBus->async_method_call(
+ std::move(callback), "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.IP", "Origin",
+ sdbusplus::message::variant<std::string>(newValueDbus));
+ };
+
+ /**
+ * @brief Modifies SubnetMask for given IP
+ *
+ * @param[in] ifaceId Id of interface whose IP should be modified
+ * @param[in] ipIdx index of IP in input array that should be
+ * modified
+ * @param[in] ipHash DBus Hash id of modified IP
+ * @param[in] newValueStr Mask in dot notation as string
+ * @param[in] newValue Mask as PrefixLength in bitcount
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return None
+ */
+ void changeIPv4SubnetMaskProperty(
+ const std::string &ifaceId, int ipIdx, const std::string &ipHash,
+ const std::string &newValueStr, uint8_t &newValue,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ auto callback = [asyncResp, ipIdx{std::move(ipIdx)},
+ newValueStr{std::move(newValueStr)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue, messages::internalError(),
+ "/IPv4Addresses/" + std::to_string(ipIdx) + "/SubnetMask");
+ }
+ else
+ {
+ asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["SubnetMask"] =
+ newValueStr;
+ }
+ };
+
+ crow::connections::systemBus->async_method_call(
+ std::move(callback), "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.IP", "PrefixLength",
+ sdbusplus::message::variant<uint8_t>(newValue));
+ };
+
+ /**
+ * @brief Disables VLAN with given ifaceId
+ *
+ * @param[in] ifaceId Id of VLAN interface that should be disabled
+ * @param[in] callback Function that will be called after the operation
+ *
+ * @return None.
+ */
+ template <typename CallbackFunc>
+ static void disableVlan(const std::string &ifaceId, CallbackFunc &&callback)
+ {
+ crow::connections::systemBus->async_method_call(
+ callback, "xyz.openbmc_project.Network",
+ std::string("/xyz/openbmc_project/network/") + ifaceId,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ };
+
+ /**
+ * @brief Sets given HostName of the machine through D-Bus
+ *
+ * @param[in] newHostname New name that HostName will be changed to
+ * @param[in] callback Function that will be called after the operation
+ *
+ * @return None.
+ */
+ template <typename CallbackFunc>
+ void setHostName(const std::string &newHostname, CallbackFunc &&callback)
+ {
+ crow::connections::systemBus->async_method_call(
+ callback, "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/config",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
+ sdbusplus::message::variant<std::string>(newHostname));
+ };
+
+ /**
+ * @brief Deletes given IPv4
+ *
+ * @param[in] ifaceId Id of interface whose IP should be deleted
+ * @param[in] ipIdx index of IP in input array that should be deleted
+ * @param[in] ipHash DBus Hash id of IP that should be deleted
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return None
+ */
+ void deleteIPv4(const std::string &ifaceId, const std::string &ipHash,
+ unsigned int ipIdx,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ crow::connections::systemBus->async_method_call(
+ [ipIdx{std::move(ipIdx)}, asyncResp{std::move(asyncResp)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue, messages::internalError(),
+ "/IPv4Addresses/" + std::to_string(ipIdx) + "/");
}
- }
+ else
+ {
+ asyncResp->res.jsonValue["IPv4Addresses"][ipIdx] = nullptr;
+ }
+ },
+ "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
+ "xyz.openbmc_project.Object.Delete", "Delete");
+ }
+
+ /**
+ * @brief Creates IPv4 with given data
+ *
+ * @param[in] ifaceId Id of interface whose IP should be deleted
+ * @param[in] ipIdx index of IP in input array that should be deleted
+ * @param[in] ipHash DBus Hash id of IP that should be deleted
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return None
+ */
+ void createIPv4(const std::string &ifaceId, unsigned int ipIdx,
+ uint8_t subnetMask, const std::string &gateway,
+ const std::string &address,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ auto createIpHandler = [ipIdx{std::move(ipIdx)},
+ asyncResp{std::move(asyncResp)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue, messages::internalError(),
+ "/IPv4Addresses/" + std::to_string(ipIdx) + "/");
}
- }
- // Finally make a callback with useful data
- callback(true, ifaceList);
- },
- "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- };
+ };
+
+ crow::connections::systemBus->async_method_call(
+ std::move(createIpHandler), "xyz.openbmc_project.Network",
+ "/xyz/openbmc_project/network/" + ifaceId,
+ "xyz.openbmc_project.Network.IP.Create", "IP",
+ "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask,
+ gateway);
+ }
+
+ /**
+ * @brief Translates Address Origin value from D-Bus to Redfish format and
+ * vice-versa
+ *
+ * @param[in] inputOrigin Input value that should be translated
+ * @param[in] isIPv4 True for IPv4 origins, False for IPv6
+ * @param[in] isFromDBus True for DBus->Redfish conversion, false for
+ * reverse
+ *
+ * @return Empty string in case of failure, translated value otherwise
+ */
+ std::string translateAddressOriginBetweenDBusAndRedfish(
+ const std::string *inputOrigin, bool isIPv4, bool isFromDBus)
+ {
+ // Invalid pointer
+ if (inputOrigin == nullptr)
+ {
+ return "";
+ }
+
+ static const constexpr unsigned int firstIPv4OnlyIdx = 1;
+ static const constexpr unsigned int firstIPv6OnlyIdx = 3;
+
+ std::array<std::pair<const char *, const char *>, 6> translationTable{
+ {{"xyz.openbmc_project.Network.IP.AddressOrigin.Static", "Static"},
+ {"xyz.openbmc_project.Network.IP.AddressOrigin.DHCP", "DHCP"},
+ {"xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal",
+ "IPv4LinkLocal"},
+ {"xyz.openbmc_project.Network.IP.AddressOrigin.DHCP", "DHCPv6"},
+ {"xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal",
+ "LinkLocal"},
+ {"xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC", "SLAAC"}}};
+
+ for (unsigned int i = 0; i < translationTable.size(); i++)
+ {
+ // Skip unrelated
+ if (isIPv4 && i >= firstIPv6OnlyIdx)
+ break;
+ if (!isIPv4 && i >= firstIPv4OnlyIdx && i < firstIPv6OnlyIdx)
+ continue;
+
+ // When translating D-Bus to Redfish compare input to first element
+ if (isFromDBus && translationTable[i].first == *inputOrigin)
+ return translationTable[i].second;
+
+ // When translating Redfish to D-Bus compare input to second element
+ if (!isFromDBus && translationTable[i].second == *inputOrigin)
+ return translationTable[i].first;
+ }
+
+ // If we are still here, that means that value has not been found
+ return "";
+ }
+
+ /**
+ * Function that retrieves all properties for given Ethernet Interface
+ * Object
+ * from EntityManager Network Manager
+ * @param ethifaceId a eth interface id to query on DBus
+ * @param callback a function that shall be called to convert Dbus output
+ * into JSON
+ */
+ template <typename CallbackFunc>
+ void getEthernetIfaceData(const std::string ðifaceId,
+ CallbackFunc &&callback)
+ {
+ crow::connections::systemBus->async_method_call(
+ [this, ethifaceId{std::move(ethifaceId)},
+ callback{std::move(callback)}](
+ const boost::system::error_code error_code,
+ const GetManagedObjectsType &resp) {
+ EthernetInterfaceData ethData{};
+ std::vector<IPv4AddressData> ipv4Data;
+ ipv4Data.reserve(maxIpV4AddressesPerInterface);
+
+ if (error_code)
+ {
+ // Something wrong on DBus, the error_code is not important
+ // at this moment, just return success=false, and empty
+ // output. Since size of vector may vary depending on
+ // information from Network Manager, and empty output could
+ // not be treated same way as error.
+ callback(false, ethData, ipv4Data);
+ return;
+ }
+
+ // Find interface
+ if (resp.find("/xyz/openbmc_project/network/" + ethifaceId) ==
+ resp.end())
+ {
+ // Interface has not been found
+ callback(false, ethData, ipv4Data);
+ return;
+ }
+
+ extractEthernetInterfaceData(ethifaceId, resp, ethData);
+ extractIPv4Data(ethifaceId, resp, ipv4Data);
+
+ // Fix global GW
+ for (IPv4AddressData &ipv4 : ipv4Data)
+ {
+ if ((ipv4.global) && ((ipv4.gateway == nullptr) ||
+ (*ipv4.gateway == "0.0.0.0")))
+ {
+ ipv4.gateway = ethData.defaultGateway;
+ }
+ }
+
+ // Finally make a callback with useful data
+ callback(true, ethData, ipv4Data);
+ },
+ "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ };
+
+ /**
+ * Function that retrieves all Ethernet Interfaces available through Network
+ * Manager
+ * @param callback a function that shall be called to convert Dbus output
+ * into JSON.
+ */
+ template <typename CallbackFunc>
+ void getEthernetIfaceList(CallbackFunc &&callback)
+ {
+ crow::connections::systemBus->async_method_call(
+ [this, callback{std::move(callback)}](
+ const boost::system::error_code error_code,
+ GetManagedObjectsType &resp) {
+ // Callback requires vector<string> to retrieve all available
+ // ethernet interfaces
+ std::vector<std::string> ifaceList;
+ ifaceList.reserve(resp.size());
+ if (error_code)
+ {
+ // Something wrong on DBus, the error_code is not important
+ // at this moment, just return success=false, and empty
+ // output. Since size of vector may vary depending on
+ // information from Network Manager, and empty output could
+ // not be treated same way as error.
+ callback(false, ifaceList);
+ return;
+ }
+
+ // Iterate over all retrieved ObjectPaths.
+ for (auto &objpath : resp)
+ {
+ // And all interfaces available for certain ObjectPath.
+ for (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")
+ {
+ // Cut out everything until last "/", ...
+ const std::string &ifaceId =
+ static_cast<const std::string &>(objpath.first);
+ std::size_t lastPos = ifaceId.rfind("/");
+ if (lastPos != std::string::npos)
+ {
+ // and put it into output vector.
+ ifaceList.emplace_back(
+ ifaceId.substr(lastPos + 1));
+ }
+ }
+ }
+ }
+ // Finally make a callback with useful data
+ callback(true, ifaceList);
+ },
+ "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ };
};
/**
* EthernetCollection derived class for delivering Ethernet Collection Schema
*/
-class EthernetCollection : public Node {
- public:
- // TODO(Pawel) Remove line from below, where we assume that there is only one
- // manager called openbmc This shall be generic, but requires to update
- // GetSubroutes method
- EthernetCollection(CrowApp &app)
- : Node(app, "/redfish/v1/Managers/openbmc/EthernetInterfaces/") {
- Node::json["@odata.type"] =
- "#EthernetInterfaceCollection.EthernetInterfaceCollection";
- Node::json["@odata.context"] =
- "/redfish/v1/"
- "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection";
- Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc/EthernetInterfaces";
- Node::json["Name"] = "Ethernet Network Interface Collection";
- Node::json["Description"] =
- "Collection of EthernetInterfaces for this Manager";
-
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces for
- // any Manager, not only hardcoded 'openbmc'.
- std::string managerId = "openbmc";
-
- // get eth interface list, and call the below callback for JSON preparation
- ethernetProvider.getEthernetIfaceList([&, managerId{std::move(managerId)} ](
- const bool &success, const std::vector<std::string> &iface_list) {
- if (success) {
- nlohmann::json ifaceArray = nlohmann::json::array();
- for (const std::string &ifaceItem : iface_list) {
- ifaceArray.push_back(
- {{"@odata.id", "/redfish/v1/Managers/" + managerId +
- "/EthernetInterfaces/" + ifaceItem}});
- }
- Node::json["Members"] = ifaceArray;
- Node::json["Members@odata.count"] = ifaceArray.size();
+class EthernetCollection : public Node
+{
+ public:
+ // TODO(Pawel) Remove line from below, where we assume that there is only
+ // one manager called openbmc This shall be generic, but requires to update
+ // GetSubroutes method
+ EthernetCollection(CrowApp &app) :
+ Node(app, "/redfish/v1/Managers/openbmc/EthernetInterfaces/")
+ {
+ Node::json["@odata.type"] =
+ "#EthernetInterfaceCollection.EthernetInterfaceCollection";
+ Node::json["@odata.context"] =
+ "/redfish/v1/"
+ "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection";
Node::json["@odata.id"] =
- "/redfish/v1/Managers/" + managerId + "/EthernetInterfaces";
- res.jsonValue = Node::json;
- } else {
- // No success, best what we can do is return INTERNALL ERROR
- res.result(boost::beast::http::status::internal_server_error);
- }
- res.end();
- });
- }
+ "/redfish/v1/Managers/openbmc/EthernetInterfaces";
+ Node::json["Name"] = "Ethernet Network Interface Collection";
+ Node::json["Description"] =
+ "Collection of EthernetInterfaces for this Manager";
- // Ethernet Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandEthernetProvider ethernetProvider;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
+ }
+
+ private:
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces
+ // for any Manager, not only hardcoded 'openbmc'.
+ std::string managerId = "openbmc";
+
+ // get eth interface list, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceList(
+ [&, managerId{std::move(managerId)}](
+ const bool &success,
+ const std::vector<std::string> &iface_list) {
+ if (success)
+ {
+ nlohmann::json ifaceArray = nlohmann::json::array();
+ for (const std::string &ifaceItem : iface_list)
+ {
+ ifaceArray.push_back(
+ {{"@odata.id", "/redfish/v1/Managers/" + managerId +
+ "/EthernetInterfaces/" +
+ ifaceItem}});
+ }
+ Node::json["Members"] = ifaceArray;
+ Node::json["Members@odata.count"] = ifaceArray.size();
+ Node::json["@odata.id"] = "/redfish/v1/Managers/" +
+ managerId + "/EthernetInterfaces";
+ res.jsonValue = Node::json;
+ }
+ else
+ {
+ // No success, best what we can do is return INTERNALL ERROR
+ res.result(
+ boost::beast::http::status::internal_server_error);
+ }
+ res.end();
+ });
+ }
+
+ // Ethernet Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandEthernetProvider ethernetProvider;
};
/**
* EthernetInterface derived class for delivering Ethernet Schema
*/
-class EthernetInterface : public Node {
- public:
- /*
- * Default Constructor
- */
- // TODO(Pawel) Remove line from below, where we assume that there is only one
- // manager called openbmc This shall be generic, but requires to update
- // GetSubroutes method
- EthernetInterface(CrowApp &app)
- : Node(app, "/redfish/v1/Managers/openbmc/EthernetInterfaces/<str>/",
- std::string()) {
- Node::json["@odata.type"] = "#EthernetInterface.v1_2_0.EthernetInterface";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#EthernetInterface.EthernetInterface";
- Node::json["Name"] = "Manager Ethernet Interface";
- Node::json["Description"] = "Management Network Interface";
+class EthernetInterface : public Node
+{
+ public:
+ /*
+ * Default Constructor
+ */
+ // TODO(Pawel) Remove line from below, where we assume that there is only
+ // one manager called openbmc This shall be generic, but requires to update
+ // GetSubroutes method
+ EthernetInterface(CrowApp &app) :
+ Node(app, "/redfish/v1/Managers/openbmc/EthernetInterfaces/<str>/",
+ std::string())
+ {
+ Node::json["@odata.type"] =
+ "#EthernetInterface.v1_2_0.EthernetInterface";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#EthernetInterface.EthernetInterface";
+ Node::json["Name"] = "Manager Ethernet Interface";
+ Node::json["Description"] = "Management Network Interface";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- // TODO(kkowalsk) Find a suitable class/namespace for this
- static void handleVlanPatch(const std::string &ifaceId,
- const nlohmann::json &input,
- const EthernetInterfaceData ð_data,
- const std::string &pathPrefix,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- if (!input.is_object()) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueTypeError(input.dump(), "VLAN"), pathPrefix);
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- const std::string pathStart = (pathPrefix == "/") ? "" : pathPrefix;
- nlohmann::json ¶msJson =
- (pathPrefix == "/")
- ? asyncResp->res.jsonValue
- : asyncResp->res.jsonValue[nlohmann::json_pointer<nlohmann::json>(
- pathPrefix)];
- bool inputVlanEnabled;
- uint64_t inputVlanId;
-
- json_util::Result inputVlanEnabledState = json_util::getBool(
- "VLANEnable", input, inputVlanEnabled,
- static_cast<int>(json_util::MessageSetting::TYPE_ERROR),
- asyncResp->res.jsonValue, std::string(pathStart + "/VLANEnable"));
- json_util::Result inputVlanIdState = json_util::getUnsigned(
- "VLANId", input, inputVlanId,
- static_cast<int>(json_util::MessageSetting::TYPE_ERROR),
- asyncResp->res.jsonValue, std::string(pathStart + "/VLANId"));
- bool inputInvalid = false;
-
- // Do not proceed if fields in VLAN object were of wrong type
- if (inputVlanEnabledState == json_util::Result::WRONG_TYPE ||
- inputVlanIdState == json_util::Result::WRONG_TYPE) {
- return;
- }
-
- // Verify input
- if (eth_data.vlanId == nullptr) {
- // This interface is not a VLAN. Cannot do anything with it
- // TODO(kkowalsk) Change this message
- messages::addMessageToJson(asyncResp->res.jsonValue,
- messages::propertyMissing("VLANEnable"),
- pathPrefix);
-
- inputInvalid = true;
- } else {
- // Load actual data into field values if they were not provided
- if (inputVlanEnabledState == json_util::Result::NOT_EXIST) {
- inputVlanEnabled = true;
- }
-
- if (inputVlanIdState == json_util::Result::NOT_EXIST) {
- inputVlanId = *eth_data.vlanId;
- }
- }
-
- // Do not proceed if input has not been valid
- if (inputInvalid) {
- return;
- }
-
- // VLAN is configured on the interface
- if (inputVlanEnabled == true && inputVlanId != *eth_data.vlanId) {
- // Change VLAN Id
- paramsJson["VLANId"] = inputVlanId;
- OnDemandEthernetProvider::changeVlanId(
- ifaceId, static_cast<uint32_t>(inputVlanId),
- [&, asyncResp, pathPrefx{std::move(pathPrefix)} ](
- const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(asyncResp->res.jsonValue,
- messages::internalError(), pathPrefix);
- } else {
- paramsJson["VLANEnable"] = true;
- }
- });
- } else if (inputVlanEnabled == false) {
- // Disable VLAN
- OnDemandEthernetProvider::disableVlan(
- ifaceId, [&, asyncResp, pathPrefx{std::move(pathPrefix)} ](
- const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(asyncResp->res.jsonValue,
- messages::internalError(), pathPrefix);
- } else {
- paramsJson["VLANEnable"] = false;
- }
- });
- }
- }
-
- private:
- void handleHostnamePatch(const nlohmann::json &input,
- const EthernetInterfaceData ð_data,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- if (input.is_string()) {
- std::string newHostname = input.get<std::string>();
-
- if (eth_data.hostname == nullptr || newHostname != *eth_data.hostname) {
- // Change hostname
- ethernetProvider.setHostName(
- newHostname,
- [asyncResp, newHostname](const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToJson(asyncResp->res.jsonValue,
- messages::internalError(),
- "/HostName");
- } else {
- asyncResp->res.jsonValue["HostName"] = newHostname;
- }
- });
- }
- } else {
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueTypeError(input.dump(), "HostName"),
- "/HostName");
- }
- }
-
- void handleIPv4Patch(const std::string &ifaceId, const nlohmann::json &input,
- const std::vector<IPv4AddressData> &ipv4_data,
- const std::shared_ptr<AsyncResp> &asyncResp) {
- if (!input.is_array()) {
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueTypeError(input.dump(), "IPv4Addresses"),
- "/IPv4Addresses");
- return;
- }
-
- // According to Redfish PATCH definition, size must be at least equal
- if (input.size() < ipv4_data.size()) {
- // TODO(kkowalsk) This should be a message indicating that not enough
- // data has been provided
- messages::addMessageToJson(asyncResp->res.jsonValue,
- messages::internalError(), "/IPv4Addresses");
- return;
- }
-
- json_util::Result addressFieldState;
- json_util::Result subnetMaskFieldState;
- json_util::Result addressOriginFieldState;
- json_util::Result gatewayFieldState;
- const std::string *addressFieldValue;
- const std::string *subnetMaskFieldValue;
- const std::string *addressOriginFieldValue = nullptr;
- const std::string *gatewayFieldValue;
- uint8_t subnetMaskAsPrefixLength;
- std::string addressOriginInDBusFormat;
-
- bool errorDetected = false;
- for (unsigned int entryIdx = 0; entryIdx < input.size(); entryIdx++) {
- // Check that entry is not of some unexpected type
- if (!input[entryIdx].is_object() && !input[entryIdx].is_null()) {
- // Invalid object type
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueTypeError(input[entryIdx].dump(),
- "IPv4Address"),
- "/IPv4Addresses/" + std::to_string(entryIdx));
-
- continue;
- }
-
- // Try to load fields
- addressFieldState = json_util::getString(
- "Address", input[entryIdx], addressFieldValue,
- static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
- asyncResp->res.jsonValue,
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Address");
- subnetMaskFieldState = json_util::getString(
- "SubnetMask", input[entryIdx], subnetMaskFieldValue,
- static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
- asyncResp->res.jsonValue,
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/SubnetMask");
- addressOriginFieldState = json_util::getString(
- "AddressOrigin", input[entryIdx], addressOriginFieldValue,
- static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
- asyncResp->res.jsonValue,
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/AddressOrigin");
- gatewayFieldState = json_util::getString(
- "Gateway", input[entryIdx], gatewayFieldValue,
- static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
- asyncResp->res.jsonValue,
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Gateway");
-
- if (addressFieldState == json_util::Result::WRONG_TYPE ||
- subnetMaskFieldState == json_util::Result::WRONG_TYPE ||
- addressOriginFieldState == json_util::Result::WRONG_TYPE ||
- gatewayFieldState == json_util::Result::WRONG_TYPE) {
- return;
- }
-
- if (addressFieldState == json_util::Result::SUCCESS &&
- !ethernetProvider.ipv4VerifyIpAndGetBitcount(*addressFieldValue)) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueFormatError(*addressFieldValue, "Address"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Address");
- }
-
- if (subnetMaskFieldState == json_util::Result::SUCCESS &&
- !ethernetProvider.ipv4VerifyIpAndGetBitcount(
- *subnetMaskFieldValue, &subnetMaskAsPrefixLength)) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueFormatError(*subnetMaskFieldValue,
- "SubnetMask"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/SubnetMask");
- }
-
- // get Address origin in proper format
- addressOriginInDBusFormat =
- ethernetProvider.translateAddressOriginBetweenDBusAndRedfish(
- addressOriginFieldValue, true, false);
-
- if (addressOriginFieldState == json_util::Result::SUCCESS &&
- addressOriginInDBusFormat.empty()) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueNotInList(*addressOriginFieldValue,
- "AddressOrigin"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/AddressOrigin");
- }
-
- if (gatewayFieldState == json_util::Result::SUCCESS &&
- !ethernetProvider.ipv4VerifyIpAndGetBitcount(*gatewayFieldValue)) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyValueFormatError(*gatewayFieldValue, "Gateway"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Gateway");
- }
-
- // If any error occured do not proceed with current entry, but do not
- // end loop
- if (errorDetected) {
- errorDetected = false;
- continue;
- }
-
- if (entryIdx >= ipv4_data.size()) {
- asyncResp->res.jsonValue["IPv4Addresses"][entryIdx] = input[entryIdx];
-
- // Verify that all field were provided
- if (addressFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::propertyMissing("Address"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Address");
- }
-
- if (subnetMaskFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::propertyMissing("SubnetMask"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/SubnetMask");
- }
-
- if (addressOriginFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyMissing("AddressOrigin"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/AddressOrigin");
- }
-
- if (gatewayFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::propertyMissing("Gateway"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Gateway");
- }
-
- // If any error occured do not proceed with current entry, but do not
- // end loop
- if (errorDetected) {
- errorDetected = false;
- continue;
- }
-
- // Create IPv4 with provided data
- ethernetProvider.createIPv4(ifaceId, entryIdx, subnetMaskAsPrefixLength,
- *gatewayFieldValue, *addressFieldValue,
- asyncResp);
- } else {
- // Existing object that should be modified/deleted/remain unchanged
- if (input[entryIdx].is_null()) {
- // Object should be deleted
- ethernetProvider.deleteIPv4(ifaceId, ipv4_data[entryIdx].id, entryIdx,
- asyncResp);
- } else if (input[entryIdx].is_object()) {
- if (input[entryIdx].size() == 0) {
- // Object shall remain unchanged
- continue;
- }
-
- // Apply changes
- if (addressFieldState == json_util::Result::SUCCESS &&
- ipv4_data[entryIdx].address != nullptr &&
- *ipv4_data[entryIdx].address != *addressFieldValue) {
- ethernetProvider.changeIPv4AddressProperty(
- ifaceId, entryIdx, ipv4_data[entryIdx].id, "Address",
- *addressFieldValue, asyncResp);
- }
-
- if (subnetMaskFieldState == json_util::Result::SUCCESS &&
- ipv4_data[entryIdx].netmask != *subnetMaskFieldValue) {
- ethernetProvider.changeIPv4SubnetMaskProperty(
- ifaceId, entryIdx, ipv4_data[entryIdx].id,
- *subnetMaskFieldValue, subnetMaskAsPrefixLength, asyncResp);
- }
-
- if (addressOriginFieldState == json_util::Result::SUCCESS &&
- ipv4_data[entryIdx].origin != *addressFieldValue) {
- ethernetProvider.changeIPv4Origin(
- ifaceId, entryIdx, ipv4_data[entryIdx].id,
- *addressOriginFieldValue, addressOriginInDBusFormat, asyncResp);
- }
-
- if (gatewayFieldState == json_util::Result::SUCCESS &&
- ipv4_data[entryIdx].gateway != nullptr &&
- *ipv4_data[entryIdx].gateway != *gatewayFieldValue) {
- ethernetProvider.changeIPv4AddressProperty(
- ifaceId, entryIdx, ipv4_data[entryIdx].id, "Gateway",
- *gatewayFieldValue, asyncResp);
- }
- }
- }
- }
- }
-
- nlohmann::json parseInterfaceData(
- const std::string &ifaceId, const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- // Copy JSON object to avoid race condition
- nlohmann::json jsonResponse(Node::json);
-
- // Fill out obvious data...
- jsonResponse["Id"] = ifaceId;
- jsonResponse["@odata.id"] =
- "/redfish/v1/Managers/openbmc/EthernetInterfaces/" + ifaceId;
-
- // ... then the one from DBus, regarding eth iface...
- if (eth_data.speed != nullptr) jsonResponse["SpeedMbps"] = *eth_data.speed;
-
- if (eth_data.macAddress != nullptr)
- jsonResponse["MACAddress"] = *eth_data.macAddress;
-
- if (eth_data.hostname != nullptr)
- jsonResponse["HostName"] = *eth_data.hostname;
-
- if (eth_data.vlanId != nullptr) {
- nlohmann::json &vlanObj = jsonResponse["VLAN"];
- vlanObj["VLANEnable"] = true;
- vlanObj["VLANId"] = *eth_data.vlanId;
- } else {
- nlohmann::json &vlanObj = jsonResponse["VLANs"];
- vlanObj["@odata.id"] =
- "/redfish/v1/Managers/openbmc/EthernetInterfaces/" + ifaceId +
- "/VLANs";
- }
-
- // ... at last, check if there are IPv4 data and prepare appropriate
- // collection
- if (ipv4_data.size() > 0) {
- nlohmann::json ipv4Array = nlohmann::json::array();
- for (auto &ipv4Config : ipv4_data) {
- nlohmann::json jsonIpv4;
- if (ipv4Config.address != nullptr) {
- jsonIpv4["Address"] = *ipv4Config.address;
- if (ipv4Config.gateway != nullptr)
- jsonIpv4["Gateway"] = *ipv4Config.gateway;
-
- jsonIpv4["AddressOrigin"] = ipv4Config.origin;
- jsonIpv4["SubnetMask"] = ipv4Config.netmask;
-
- ipv4Array.push_back(std::move(jsonIpv4));
- }
- }
- jsonResponse["IPv4Addresses"] = std::move(ipv4Array);
- }
-
- return jsonResponse;
- }
-
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // TODO(Pawel) this shall be parametrized call (two params) to get
- // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
- // Check if there is required param, truly entering this shall be
- // impossible.
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
- }
-
- const std::string &ifaceId = params[0];
-
- // get single eth interface data, and call the below callback for JSON
- // preparation
- ethernetProvider.getEthernetIfaceData(
- ifaceId,
- [&, ifaceId](const bool &success, const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- if (success) {
- res.jsonValue = parseInterfaceData(ifaceId, eth_data, ipv4_data);
- } else {
- // ... otherwise return error
- // TODO(Pawel)consider distinguish between non existing object, and
- // other errors
- messages::addMessageToErrorJson(
- res.jsonValue,
- messages::resourceNotFound("EthernetInterface", ifaceId));
- res.result(boost::beast::http::status::not_found);
- }
- res.end();
- });
- }
-
- void doPatch(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // TODO(Pawel) this shall be parametrized call (two params) to get
- // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
- // Check if there is required param, truly entering this shall be
- // impossible.
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
- }
-
- const std::string &ifaceId = params[0];
-
- nlohmann::json patchReq;
-
- if (!json_util::processJsonFromRequest(res, req, patchReq)) {
- return;
- }
-
- // get single eth interface data, and call the below callback for JSON
- // preparation
- ethernetProvider.getEthernetIfaceData(
- ifaceId, [&, ifaceId, patchReq = std::move(patchReq) ](
- const bool &success, const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- if (!success) {
- // ... otherwise return error
- // TODO(Pawel)consider distinguish between non existing object, and
- // other errors
- messages::addMessageToErrorJson(
- res.jsonValue,
- messages::resourceNotFound("VLAN Network Interface", ifaceId));
- res.result(boost::beast::http::status::not_found);
- res.end();
-
+ // TODO(kkowalsk) Find a suitable class/namespace for this
+ static void handleVlanPatch(const std::string &ifaceId,
+ const nlohmann::json &input,
+ const EthernetInterfaceData ð_data,
+ const std::string &pathPrefix,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ if (!input.is_object())
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueTypeError(input.dump(), "VLAN"),
+ pathPrefix);
return;
- }
+ }
- res.jsonValue = parseInterfaceData(ifaceId, eth_data, ipv4_data);
+ const std::string pathStart = (pathPrefix == "/") ? "" : pathPrefix;
+ nlohmann::json ¶msJson =
+ (pathPrefix == "/")
+ ? asyncResp->res.jsonValue
+ : asyncResp->res
+ .jsonValue[nlohmann::json_pointer<nlohmann::json>(
+ pathPrefix)];
+ bool inputVlanEnabled;
+ uint64_t inputVlanId;
- std::shared_ptr<AsyncResp> asyncResp =
- std::make_shared<AsyncResp>(res);
+ json_util::Result inputVlanEnabledState = json_util::getBool(
+ "VLANEnable", input, inputVlanEnabled,
+ static_cast<int>(json_util::MessageSetting::TYPE_ERROR),
+ asyncResp->res.jsonValue, std::string(pathStart + "/VLANEnable"));
+ json_util::Result inputVlanIdState = json_util::getUnsigned(
+ "VLANId", input, inputVlanId,
+ static_cast<int>(json_util::MessageSetting::TYPE_ERROR),
+ asyncResp->res.jsonValue, std::string(pathStart + "/VLANId"));
+ bool inputInvalid = false;
- for (auto propertyIt = patchReq.begin(); propertyIt != patchReq.end();
- ++propertyIt) {
- if (propertyIt.key() == "VLAN") {
- handleVlanPatch(ifaceId, propertyIt.value(), eth_data, "/VLAN",
- asyncResp);
- } else if (propertyIt.key() == "HostName") {
- handleHostnamePatch(propertyIt.value(), eth_data, asyncResp);
- } else if (propertyIt.key() == "IPv4Addresses") {
- handleIPv4Patch(ifaceId, propertyIt.value(), ipv4_data,
- asyncResp);
- } else if (propertyIt.key() == "IPv6Addresses") {
- // TODO(kkowalsk) IPv6 Not supported on D-Bus yet
- messages::addMessageToJsonRoot(
- res.jsonValue,
- messages::propertyNotWritable(propertyIt.key()));
- } else {
- auto fieldInJsonIt = res.jsonValue.find(propertyIt.key());
+ // Do not proceed if fields in VLAN object were of wrong type
+ if (inputVlanEnabledState == json_util::Result::WRONG_TYPE ||
+ inputVlanIdState == json_util::Result::WRONG_TYPE)
+ {
+ return;
+ }
- if (fieldInJsonIt == res.jsonValue.end()) {
- // Field not in scope of defined fields
- messages::addMessageToJsonRoot(
- res.jsonValue, messages::propertyUnknown(propertyIt.key()));
- } else if (*fieldInJsonIt != *propertyIt) {
- // User attempted to modify non-writable field
- messages::addMessageToJsonRoot(
- res.jsonValue,
- messages::propertyNotWritable(propertyIt.key()));
- }
+ // Verify input
+ if (eth_data.vlanId == nullptr)
+ {
+ // This interface is not a VLAN. Cannot do anything with it
+ // TODO(kkowalsk) Change this message
+ messages::addMessageToJson(asyncResp->res.jsonValue,
+ messages::propertyMissing("VLANEnable"),
+ pathPrefix);
+
+ inputInvalid = true;
+ }
+ else
+ {
+ // Load actual data into field values if they were not provided
+ if (inputVlanEnabledState == json_util::Result::NOT_EXIST)
+ {
+ inputVlanEnabled = true;
}
- }
- });
- }
- // Ethernet Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandEthernetProvider ethernetProvider;
+ if (inputVlanIdState == json_util::Result::NOT_EXIST)
+ {
+ inputVlanId = *eth_data.vlanId;
+ }
+ }
+
+ // Do not proceed if input has not been valid
+ if (inputInvalid)
+ {
+ return;
+ }
+
+ // VLAN is configured on the interface
+ if (inputVlanEnabled == true && inputVlanId != *eth_data.vlanId)
+ {
+ // Change VLAN Id
+ paramsJson["VLANId"] = inputVlanId;
+ OnDemandEthernetProvider::changeVlanId(
+ ifaceId, static_cast<uint32_t>(inputVlanId),
+ [&, asyncResp, pathPrefx{std::move(pathPrefix)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(asyncResp->res.jsonValue,
+ messages::internalError(),
+ pathPrefix);
+ }
+ else
+ {
+ paramsJson["VLANEnable"] = true;
+ }
+ });
+ }
+ else if (inputVlanEnabled == false)
+ {
+ // Disable VLAN
+ OnDemandEthernetProvider::disableVlan(
+ ifaceId, [&, asyncResp, pathPrefx{std::move(pathPrefix)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(asyncResp->res.jsonValue,
+ messages::internalError(),
+ pathPrefix);
+ }
+ else
+ {
+ paramsJson["VLANEnable"] = false;
+ }
+ });
+ }
+ }
+
+ private:
+ void handleHostnamePatch(const nlohmann::json &input,
+ const EthernetInterfaceData ð_data,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ if (input.is_string())
+ {
+ std::string newHostname = input.get<std::string>();
+
+ if (eth_data.hostname == nullptr ||
+ newHostname != *eth_data.hostname)
+ {
+ // Change hostname
+ ethernetProvider.setHostName(
+ newHostname, [asyncResp, newHostname](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::internalError(), "/HostName");
+ }
+ else
+ {
+ asyncResp->res.jsonValue["HostName"] = newHostname;
+ }
+ });
+ }
+ }
+ else
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueTypeError(input.dump(), "HostName"),
+ "/HostName");
+ }
+ }
+
+ void handleIPv4Patch(const std::string &ifaceId,
+ const nlohmann::json &input,
+ const std::vector<IPv4AddressData> &ipv4_data,
+ const std::shared_ptr<AsyncResp> &asyncResp)
+ {
+ if (!input.is_array())
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueTypeError(input.dump(), "IPv4Addresses"),
+ "/IPv4Addresses");
+ return;
+ }
+
+ // According to Redfish PATCH definition, size must be at least equal
+ if (input.size() < ipv4_data.size())
+ {
+ // TODO(kkowalsk) This should be a message indicating that not
+ // enough data has been provided
+ messages::addMessageToJson(asyncResp->res.jsonValue,
+ messages::internalError(),
+ "/IPv4Addresses");
+ return;
+ }
+
+ json_util::Result addressFieldState;
+ json_util::Result subnetMaskFieldState;
+ json_util::Result addressOriginFieldState;
+ json_util::Result gatewayFieldState;
+ const std::string *addressFieldValue;
+ const std::string *subnetMaskFieldValue;
+ const std::string *addressOriginFieldValue = nullptr;
+ const std::string *gatewayFieldValue;
+ uint8_t subnetMaskAsPrefixLength;
+ std::string addressOriginInDBusFormat;
+
+ bool errorDetected = false;
+ for (unsigned int entryIdx = 0; entryIdx < input.size(); entryIdx++)
+ {
+ // Check that entry is not of some unexpected type
+ if (!input[entryIdx].is_object() && !input[entryIdx].is_null())
+ {
+ // Invalid object type
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueTypeError(input[entryIdx].dump(),
+ "IPv4Address"),
+ "/IPv4Addresses/" + std::to_string(entryIdx));
+
+ continue;
+ }
+
+ // Try to load fields
+ addressFieldState = json_util::getString(
+ "Address", input[entryIdx], addressFieldValue,
+ static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
+ asyncResp->res.jsonValue,
+ "/IPv4Addresses/" + std::to_string(entryIdx) + "/Address");
+ subnetMaskFieldState = json_util::getString(
+ "SubnetMask", input[entryIdx], subnetMaskFieldValue,
+ static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
+ asyncResp->res.jsonValue,
+ "/IPv4Addresses/" + std::to_string(entryIdx) + "/SubnetMask");
+ addressOriginFieldState = json_util::getString(
+ "AddressOrigin", input[entryIdx], addressOriginFieldValue,
+ static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
+ asyncResp->res.jsonValue,
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/AddressOrigin");
+ gatewayFieldState = json_util::getString(
+ "Gateway", input[entryIdx], gatewayFieldValue,
+ static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
+ asyncResp->res.jsonValue,
+ "/IPv4Addresses/" + std::to_string(entryIdx) + "/Gateway");
+
+ if (addressFieldState == json_util::Result::WRONG_TYPE ||
+ subnetMaskFieldState == json_util::Result::WRONG_TYPE ||
+ addressOriginFieldState == json_util::Result::WRONG_TYPE ||
+ gatewayFieldState == json_util::Result::WRONG_TYPE)
+ {
+ return;
+ }
+
+ if (addressFieldState == json_util::Result::SUCCESS &&
+ !ethernetProvider.ipv4VerifyIpAndGetBitcount(
+ *addressFieldValue))
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueFormatError(*addressFieldValue,
+ "Address"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) + "/Address");
+ }
+
+ if (subnetMaskFieldState == json_util::Result::SUCCESS &&
+ !ethernetProvider.ipv4VerifyIpAndGetBitcount(
+ *subnetMaskFieldValue, &subnetMaskAsPrefixLength))
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueFormatError(*subnetMaskFieldValue,
+ "SubnetMask"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/SubnetMask");
+ }
+
+ // get Address origin in proper format
+ addressOriginInDBusFormat =
+ ethernetProvider.translateAddressOriginBetweenDBusAndRedfish(
+ addressOriginFieldValue, true, false);
+
+ if (addressOriginFieldState == json_util::Result::SUCCESS &&
+ addressOriginInDBusFormat.empty())
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueNotInList(*addressOriginFieldValue,
+ "AddressOrigin"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/AddressOrigin");
+ }
+
+ if (gatewayFieldState == json_util::Result::SUCCESS &&
+ !ethernetProvider.ipv4VerifyIpAndGetBitcount(
+ *gatewayFieldValue))
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueFormatError(*gatewayFieldValue,
+ "Gateway"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) + "/Gateway");
+ }
+
+ // If any error occured do not proceed with current entry, but do
+ // not end loop
+ if (errorDetected)
+ {
+ errorDetected = false;
+ continue;
+ }
+
+ if (entryIdx >= ipv4_data.size())
+ {
+ asyncResp->res.jsonValue["IPv4Addresses"][entryIdx] =
+ input[entryIdx];
+
+ // Verify that all field were provided
+ if (addressFieldState == json_util::Result::NOT_EXIST)
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyMissing("Address"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/Address");
+ }
+
+ if (subnetMaskFieldState == json_util::Result::NOT_EXIST)
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyMissing("SubnetMask"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/SubnetMask");
+ }
+
+ if (addressOriginFieldState == json_util::Result::NOT_EXIST)
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyMissing("AddressOrigin"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/AddressOrigin");
+ }
+
+ if (gatewayFieldState == json_util::Result::NOT_EXIST)
+ {
+ errorDetected = true;
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyMissing("Gateway"),
+ "/IPv4Addresses/" + std::to_string(entryIdx) +
+ "/Gateway");
+ }
+
+ // If any error occured do not proceed with current entry, but
+ // do not end loop
+ if (errorDetected)
+ {
+ errorDetected = false;
+ continue;
+ }
+
+ // Create IPv4 with provided data
+ ethernetProvider.createIPv4(
+ ifaceId, entryIdx, subnetMaskAsPrefixLength,
+ *gatewayFieldValue, *addressFieldValue, asyncResp);
+ }
+ else
+ {
+ // Existing object that should be modified/deleted/remain
+ // unchanged
+ if (input[entryIdx].is_null())
+ {
+ // Object should be deleted
+ ethernetProvider.deleteIPv4(ifaceId, ipv4_data[entryIdx].id,
+ entryIdx, asyncResp);
+ }
+ else if (input[entryIdx].is_object())
+ {
+ if (input[entryIdx].size() == 0)
+ {
+ // Object shall remain unchanged
+ continue;
+ }
+
+ // Apply changes
+ if (addressFieldState == json_util::Result::SUCCESS &&
+ ipv4_data[entryIdx].address != nullptr &&
+ *ipv4_data[entryIdx].address != *addressFieldValue)
+ {
+ ethernetProvider.changeIPv4AddressProperty(
+ ifaceId, entryIdx, ipv4_data[entryIdx].id,
+ "Address", *addressFieldValue, asyncResp);
+ }
+
+ if (subnetMaskFieldState == json_util::Result::SUCCESS &&
+ ipv4_data[entryIdx].netmask != *subnetMaskFieldValue)
+ {
+ ethernetProvider.changeIPv4SubnetMaskProperty(
+ ifaceId, entryIdx, ipv4_data[entryIdx].id,
+ *subnetMaskFieldValue, subnetMaskAsPrefixLength,
+ asyncResp);
+ }
+
+ if (addressOriginFieldState == json_util::Result::SUCCESS &&
+ ipv4_data[entryIdx].origin != *addressFieldValue)
+ {
+ ethernetProvider.changeIPv4Origin(
+ ifaceId, entryIdx, ipv4_data[entryIdx].id,
+ *addressOriginFieldValue, addressOriginInDBusFormat,
+ asyncResp);
+ }
+
+ if (gatewayFieldState == json_util::Result::SUCCESS &&
+ ipv4_data[entryIdx].gateway != nullptr &&
+ *ipv4_data[entryIdx].gateway != *gatewayFieldValue)
+ {
+ ethernetProvider.changeIPv4AddressProperty(
+ ifaceId, entryIdx, ipv4_data[entryIdx].id,
+ "Gateway", *gatewayFieldValue, asyncResp);
+ }
+ }
+ }
+ }
+ }
+
+ nlohmann::json
+ parseInterfaceData(const std::string &ifaceId,
+ const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data)
+ {
+ // Copy JSON object to avoid race condition
+ nlohmann::json jsonResponse(Node::json);
+
+ // Fill out obvious data...
+ jsonResponse["Id"] = ifaceId;
+ jsonResponse["@odata.id"] =
+ "/redfish/v1/Managers/openbmc/EthernetInterfaces/" + ifaceId;
+
+ // ... then the one from DBus, regarding eth iface...
+ if (eth_data.speed != nullptr)
+ jsonResponse["SpeedMbps"] = *eth_data.speed;
+
+ if (eth_data.macAddress != nullptr)
+ jsonResponse["MACAddress"] = *eth_data.macAddress;
+
+ if (eth_data.hostname != nullptr)
+ jsonResponse["HostName"] = *eth_data.hostname;
+
+ if (eth_data.vlanId != nullptr)
+ {
+ nlohmann::json &vlanObj = jsonResponse["VLAN"];
+ vlanObj["VLANEnable"] = true;
+ vlanObj["VLANId"] = *eth_data.vlanId;
+ }
+ else
+ {
+ nlohmann::json &vlanObj = jsonResponse["VLANs"];
+ vlanObj["@odata.id"] =
+ "/redfish/v1/Managers/openbmc/EthernetInterfaces/" + ifaceId +
+ "/VLANs";
+ }
+
+ // ... at last, check if there are IPv4 data and prepare appropriate
+ // collection
+ if (ipv4_data.size() > 0)
+ {
+ nlohmann::json ipv4Array = nlohmann::json::array();
+ for (auto &ipv4Config : ipv4_data)
+ {
+ nlohmann::json jsonIpv4;
+ if (ipv4Config.address != nullptr)
+ {
+ jsonIpv4["Address"] = *ipv4Config.address;
+ if (ipv4Config.gateway != nullptr)
+ jsonIpv4["Gateway"] = *ipv4Config.gateway;
+
+ jsonIpv4["AddressOrigin"] = ipv4Config.origin;
+ jsonIpv4["SubnetMask"] = ipv4Config.netmask;
+
+ ipv4Array.push_back(std::move(jsonIpv4));
+ }
+ }
+ jsonResponse["IPv4Addresses"] = std::move(ipv4Array);
+ }
+
+ return jsonResponse;
+ }
+
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // TODO(Pawel) this shall be parametrized call (two params) to get
+ // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
+ // Check if there is required param, truly entering this shall be
+ // impossible.
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+
+ const std::string &ifaceId = params[0];
+
+ // get single eth interface data, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceData(
+ ifaceId,
+ [&, ifaceId](const bool &success,
+ const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data) {
+ if (success)
+ {
+ res.jsonValue =
+ parseInterfaceData(ifaceId, eth_data, ipv4_data);
+ }
+ else
+ {
+ // ... otherwise return error
+ // TODO(Pawel)consider distinguish between non existing
+ // object, and other errors
+ messages::addMessageToErrorJson(
+ res.jsonValue, messages::resourceNotFound(
+ "EthernetInterface", ifaceId));
+ res.result(boost::beast::http::status::not_found);
+ }
+ res.end();
+ });
+ }
+
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // TODO(Pawel) this shall be parametrized call (two params) to get
+ // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
+ // Check if there is required param, truly entering this shall be
+ // impossible.
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+
+ const std::string &ifaceId = params[0];
+
+ nlohmann::json patchReq;
+
+ if (!json_util::processJsonFromRequest(res, req, patchReq))
+ {
+ return;
+ }
+
+ // get single eth interface data, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceData(
+ ifaceId,
+ [&, ifaceId, patchReq = std::move(patchReq)](
+ const bool &success, const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data) {
+ if (!success)
+ {
+ // ... otherwise return error
+ // TODO(Pawel)consider distinguish between non existing
+ // object, and other errors
+ messages::addMessageToErrorJson(
+ res.jsonValue, messages::resourceNotFound(
+ "VLAN Network Interface", ifaceId));
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+
+ return;
+ }
+
+ res.jsonValue =
+ parseInterfaceData(ifaceId, eth_data, ipv4_data);
+
+ std::shared_ptr<AsyncResp> asyncResp =
+ std::make_shared<AsyncResp>(res);
+
+ for (auto propertyIt = patchReq.begin();
+ propertyIt != patchReq.end(); ++propertyIt)
+ {
+ if (propertyIt.key() == "VLAN")
+ {
+ handleVlanPatch(ifaceId, propertyIt.value(), eth_data,
+ "/VLAN", asyncResp);
+ }
+ else if (propertyIt.key() == "HostName")
+ {
+ handleHostnamePatch(propertyIt.value(), eth_data,
+ asyncResp);
+ }
+ else if (propertyIt.key() == "IPv4Addresses")
+ {
+ handleIPv4Patch(ifaceId, propertyIt.value(), ipv4_data,
+ asyncResp);
+ }
+ else if (propertyIt.key() == "IPv6Addresses")
+ {
+ // TODO(kkowalsk) IPv6 Not supported on D-Bus yet
+ messages::addMessageToJsonRoot(
+ res.jsonValue,
+ messages::propertyNotWritable(propertyIt.key()));
+ }
+ else
+ {
+ auto fieldInJsonIt =
+ res.jsonValue.find(propertyIt.key());
+
+ if (fieldInJsonIt == res.jsonValue.end())
+ {
+ // Field not in scope of defined fields
+ messages::addMessageToJsonRoot(
+ res.jsonValue,
+ messages::propertyUnknown(propertyIt.key()));
+ }
+ else if (*fieldInJsonIt != *propertyIt)
+ {
+ // User attempted to modify non-writable field
+ messages::addMessageToJsonRoot(
+ res.jsonValue, messages::propertyNotWritable(
+ propertyIt.key()));
+ }
+ }
+ }
+ });
+ }
+
+ // Ethernet Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandEthernetProvider ethernetProvider;
};
class VlanNetworkInterfaceCollection;
@@ -1350,422 +1585,499 @@
/**
* VlanNetworkInterface derived class for delivering VLANNetworkInterface Schema
*/
-class VlanNetworkInterface : public Node {
- public:
- /*
- * Default Constructor
- */
- template <typename CrowApp>
- // TODO(Pawel) Remove line from below, where we assume that there is only one
- // manager called openbmc This shall be generic, but requires to update
- // GetSubroutes method
- VlanNetworkInterface(CrowApp &app)
- : Node(
+class VlanNetworkInterface : public Node
+{
+ public:
+ /*
+ * Default Constructor
+ */
+ template <typename CrowApp>
+ // TODO(Pawel) Remove line from below, where we assume that there is only
+ // one manager called openbmc This shall be generic, but requires to update
+ // GetSubroutes method
+ VlanNetworkInterface(CrowApp &app) :
+ Node(
app,
"/redfish/v1/Managers/openbmc/EthernetInterfaces/<str>/VLANs/<str>",
- std::string(), std::string()) {
- Node::json["@odata.type"] =
- "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface";
- Node::json["Name"] = "VLAN Network Interface";
+ std::string(), std::string())
+ {
+ Node::json["@odata.type"] =
+ "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface";
+ Node::json["Name"] = "VLAN Network Interface";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- nlohmann::json parseInterfaceData(
- const std::string &parent_ifaceId, const std::string &ifaceId,
- const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- // Copy JSON object to avoid race condition
- nlohmann::json jsonResponse(Node::json);
-
- // Fill out obvious data...
- jsonResponse["Id"] = ifaceId;
- jsonResponse["@odata.id"] =
- "/redfish/v1/Managers/openbmc/EthernetInterfaces/" + parent_ifaceId +
- "/VLANs/" + ifaceId;
-
- jsonResponse["VLANEnable"] = true;
- jsonResponse["VLANId"] = *eth_data.vlanId;
-
- return jsonResponse;
- }
-
- bool verifyNames(crow::Response &res, const std::string &parent,
- const std::string &iface) {
- if (!boost::starts_with(iface, parent + "_")) {
- messages::addMessageToErrorJson(
- res.jsonValue,
- messages::resourceNotFound("VLAN Network Interface", iface));
- res.result(boost::beast::http::status::not_found);
- res.end();
-
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // TODO(Pawel) this shall be parametrized call (two params) to get
- // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
- // Check if there is required param, truly entering this shall be
- // impossible.
- if (params.size() != 2) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- const std::string &parentIfaceId = params[0];
- const std::string &ifaceId = params[1];
+ private:
+ nlohmann::json
+ parseInterfaceData(const std::string &parent_ifaceId,
+ const std::string &ifaceId,
+ const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data)
+ {
+ // Copy JSON object to avoid race condition
+ nlohmann::json jsonResponse(Node::json);
- if (!verifyNames(res, parentIfaceId, ifaceId)) {
- return;
+ // Fill out obvious data...
+ jsonResponse["Id"] = ifaceId;
+ jsonResponse["@odata.id"] =
+ "/redfish/v1/Managers/openbmc/EthernetInterfaces/" +
+ parent_ifaceId + "/VLANs/" + ifaceId;
+
+ jsonResponse["VLANEnable"] = true;
+ jsonResponse["VLANId"] = *eth_data.vlanId;
+
+ return jsonResponse;
}
- // Get single eth interface data, and call the below callback for JSON
- // preparation
- ethernetProvider.getEthernetIfaceData(
- ifaceId, [&, parentIfaceId, ifaceId](
- const bool &success, const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- if (success && eth_data.vlanId != nullptr) {
- res.jsonValue =
- parseInterfaceData(parentIfaceId, ifaceId, eth_data, ipv4_data);
- } else {
- // ... otherwise return error
- // TODO(Pawel)consider distinguish between non existing object, and
- // other errors
+ bool verifyNames(crow::Response &res, const std::string &parent,
+ const std::string &iface)
+ {
+ if (!boost::starts_with(iface, parent + "_"))
+ {
messages::addMessageToErrorJson(
res.jsonValue,
- messages::resourceNotFound("VLAN Network Interface", ifaceId));
- res.result(boost::beast::http::status::not_found);
- }
- res.end();
- });
- }
-
- void doPatch(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- if (params.size() != 2) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
- }
-
- const std::string &parentIfaceId = params[0];
- const std::string &ifaceId = params[1];
-
- if (!verifyNames(res, parentIfaceId, ifaceId)) {
- return;
- }
-
- nlohmann::json patchReq;
-
- if (!json_util::processJsonFromRequest(res, req, patchReq)) {
- return;
- }
-
- // Get single eth interface data, and call the below callback for JSON
- // preparation
- ethernetProvider.getEthernetIfaceData(
- ifaceId, [&, parentIfaceId, ifaceId, patchReq = std::move(patchReq) ](
- const bool &success, const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- if (!success) {
- // ... otherwise return error
- // TODO(Pawel)consider distinguish between non existing object,
- // and
- // other errors
- messages::addMessageToErrorJson(
- res.jsonValue,
- messages::resourceNotFound("VLAN Network Interface", ifaceId));
+ messages::resourceNotFound("VLAN Network Interface", iface));
res.result(boost::beast::http::status::not_found);
res.end();
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // TODO(Pawel) this shall be parametrized call (two params) to get
+ // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
+ // Check if there is required param, truly entering this shall be
+ // impossible.
+ if (params.size() != 2)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
return;
- }
+ }
- res.jsonValue =
- parseInterfaceData(parentIfaceId, ifaceId, eth_data, ipv4_data);
+ const std::string &parentIfaceId = params[0];
+ const std::string &ifaceId = params[1];
- std::shared_ptr<AsyncResp> asyncResp =
- std::make_shared<AsyncResp>(res);
+ if (!verifyNames(res, parentIfaceId, ifaceId))
+ {
+ return;
+ }
- for (auto propertyIt = patchReq.begin(); propertyIt != patchReq.end();
- ++propertyIt) {
- if (propertyIt.key() != "VLANEnable" &&
- propertyIt.key() != "VLANId") {
- auto fieldInJsonIt = res.jsonValue.find(propertyIt.key());
-
- if (fieldInJsonIt == res.jsonValue.end()) {
- // Field not in scope of defined fields
- messages::addMessageToJsonRoot(
- res.jsonValue, messages::propertyUnknown(propertyIt.key()));
- } else if (*fieldInJsonIt != *propertyIt) {
- // User attempted to modify non-writable field
- messages::addMessageToJsonRoot(
- res.jsonValue,
- messages::propertyNotWritable(propertyIt.key()));
- }
- }
- }
-
- EthernetInterface::handleVlanPatch(ifaceId, patchReq, eth_data, "/",
- asyncResp);
- });
- }
-
- void doDelete(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- if (params.size() != 2) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
+ // Get single eth interface data, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceData(
+ ifaceId, [&, parentIfaceId,
+ ifaceId](const bool &success,
+ const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data) {
+ if (success && eth_data.vlanId != nullptr)
+ {
+ res.jsonValue = parseInterfaceData(parentIfaceId, ifaceId,
+ eth_data, ipv4_data);
+ }
+ else
+ {
+ // ... otherwise return error
+ // TODO(Pawel)consider distinguish between non existing
+ // object, and other errors
+ messages::addMessageToErrorJson(
+ res.jsonValue, messages::resourceNotFound(
+ "VLAN Network Interface", ifaceId));
+ res.result(boost::beast::http::status::not_found);
+ }
+ res.end();
+ });
}
- const std::string &parentIfaceId = params[0];
- const std::string &ifaceId = params[1];
-
- if (!verifyNames(res, parentIfaceId, ifaceId)) {
- return;
- }
-
- // Get single eth interface data, and call the below callback for JSON
- // preparation
- ethernetProvider.getEthernetIfaceData(
- ifaceId, [&, parentIfaceId, ifaceId](
- const bool &success, const EthernetInterfaceData ð_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- if (success && eth_data.vlanId != nullptr) {
- res.jsonValue =
- parseInterfaceData(parentIfaceId, ifaceId, eth_data, ipv4_data);
-
- // Disable VLAN
- OnDemandEthernetProvider::disableVlan(
- ifaceId, [&](const boost::system::error_code ec) {
- if (ec) {
- res.jsonValue = nlohmann::json::object();
- messages::addMessageToErrorJson(res.jsonValue,
- messages::internalError());
- res.result(
- boost::beast::http::status::internal_server_error);
- }
- res.end();
- });
- } else {
- // ... otherwise return error
- // TODO(Pawel)consider distinguish between non existing object,
- // and
- // other errors
- messages::addMessageToErrorJson(
- res.jsonValue,
- messages::resourceNotFound("VLAN Network Interface", ifaceId));
- res.result(boost::beast::http::status::not_found);
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ if (params.size() != 2)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
res.end();
- }
- });
- }
+ return;
+ }
- /**
- * This allows VlanNetworkInterfaceCollection to reuse this class' doGet
- * method, to maintain consistency of returned data, as Collection's doPost
- * should return data for created member which should match member's doGet
- * result in 100%.
- */
- friend VlanNetworkInterfaceCollection;
+ const std::string &parentIfaceId = params[0];
+ const std::string &ifaceId = params[1];
- // Ethernet Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandEthernetProvider ethernetProvider;
+ if (!verifyNames(res, parentIfaceId, ifaceId))
+ {
+ return;
+ }
+
+ nlohmann::json patchReq;
+
+ if (!json_util::processJsonFromRequest(res, req, patchReq))
+ {
+ return;
+ }
+
+ // Get single eth interface data, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceData(
+ ifaceId,
+ [&, parentIfaceId, ifaceId, patchReq = std::move(patchReq)](
+ const bool &success, const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data) {
+ if (!success)
+ {
+ // ... otherwise return error
+ // TODO(Pawel)consider distinguish between non existing
+ // object, and other errors
+ messages::addMessageToErrorJson(
+ res.jsonValue, messages::resourceNotFound(
+ "VLAN Network Interface", ifaceId));
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+
+ return;
+ }
+
+ res.jsonValue = parseInterfaceData(parentIfaceId, ifaceId,
+ eth_data, ipv4_data);
+
+ std::shared_ptr<AsyncResp> asyncResp =
+ std::make_shared<AsyncResp>(res);
+
+ for (auto propertyIt = patchReq.begin();
+ propertyIt != patchReq.end(); ++propertyIt)
+ {
+ if (propertyIt.key() != "VLANEnable" &&
+ propertyIt.key() != "VLANId")
+ {
+ auto fieldInJsonIt =
+ res.jsonValue.find(propertyIt.key());
+
+ if (fieldInJsonIt == res.jsonValue.end())
+ {
+ // Field not in scope of defined fields
+ messages::addMessageToJsonRoot(
+ res.jsonValue,
+ messages::propertyUnknown(propertyIt.key()));
+ }
+ else if (*fieldInJsonIt != *propertyIt)
+ {
+ // User attempted to modify non-writable field
+ messages::addMessageToJsonRoot(
+ res.jsonValue, messages::propertyNotWritable(
+ propertyIt.key()));
+ }
+ }
+ }
+
+ EthernetInterface::handleVlanPatch(ifaceId, patchReq, eth_data,
+ "/", asyncResp);
+ });
+ }
+
+ void doDelete(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ if (params.size() != 2)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+
+ const std::string &parentIfaceId = params[0];
+ const std::string &ifaceId = params[1];
+
+ if (!verifyNames(res, parentIfaceId, ifaceId))
+ {
+ return;
+ }
+
+ // Get single eth interface data, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceData(
+ ifaceId, [&, parentIfaceId,
+ ifaceId](const bool &success,
+ const EthernetInterfaceData ð_data,
+ const std::vector<IPv4AddressData> &ipv4_data) {
+ if (success && eth_data.vlanId != nullptr)
+ {
+ res.jsonValue = parseInterfaceData(parentIfaceId, ifaceId,
+ eth_data, ipv4_data);
+
+ // Disable VLAN
+ OnDemandEthernetProvider::disableVlan(
+ ifaceId, [&](const boost::system::error_code ec) {
+ if (ec)
+ {
+ res.jsonValue = nlohmann::json::object();
+ messages::addMessageToErrorJson(
+ res.jsonValue, messages::internalError());
+ res.result(boost::beast::http::status::
+ internal_server_error);
+ }
+ res.end();
+ });
+ }
+ else
+ {
+ // ... otherwise return error
+ // TODO(Pawel)consider distinguish between non existing
+ // object, and other errors
+ messages::addMessageToErrorJson(
+ res.jsonValue, messages::resourceNotFound(
+ "VLAN Network Interface", ifaceId));
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+ }
+ });
+ }
+
+ /**
+ * This allows VlanNetworkInterfaceCollection to reuse this class' doGet
+ * method, to maintain consistency of returned data, as Collection's doPost
+ * should return data for created member which should match member's doGet
+ * result in 100%.
+ */
+ friend VlanNetworkInterfaceCollection;
+
+ // Ethernet Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandEthernetProvider ethernetProvider;
};
/**
* VlanNetworkInterfaceCollection derived class for delivering
* VLANNetworkInterface Collection Schema
*/
-class VlanNetworkInterfaceCollection : public Node {
- public:
- template <typename CrowApp>
- // TODO(Pawel) Remove line from below, where we assume that there is only one
- // manager called openbmc This shall be generic, but requires to update
- // GetSubroutes method
- VlanNetworkInterfaceCollection(CrowApp &app)
- : Node(app,
+class VlanNetworkInterfaceCollection : public Node
+{
+ public:
+ template <typename CrowApp>
+ // TODO(Pawel) Remove line from below, where we assume that there is only
+ // one manager called openbmc This shall be generic, but requires to update
+ // GetSubroutes method
+ VlanNetworkInterfaceCollection(CrowApp &app) :
+ Node(app,
"/redfish/v1/Managers/openbmc/EthernetInterfaces/<str>/VLANs/",
std::string()),
- memberVlan(app) {
- Node::json["@odata.type"] =
- "#VLanNetworkInterfaceCollection.VLanNetworkInterfaceCollection";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata"
- "#VLanNetworkInterfaceCollection.VLanNetworkInterfaceCollection";
- Node::json["Name"] = "VLAN Network Interface Collection";
+ memberVlan(app)
+ {
+ Node::json["@odata.type"] =
+ "#VLanNetworkInterfaceCollection.VLanNetworkInterfaceCollection";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata"
+ "#VLanNetworkInterfaceCollection.VLanNetworkInterfaceCollection";
+ Node::json["Name"] = "VLAN Network Interface Collection";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- if (params.size() != 1) {
- // This means there is a problem with the router
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
-
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces for
- // any Manager, not only hardcoded 'openbmc'.
- std::string managerId = "openbmc";
- std::string rootInterfaceName = params[0];
+ private:
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ if (params.size() != 1)
+ {
+ // This means there is a problem with the router
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
- // get eth interface list, and call the below callback for JSON preparation
- ethernetProvider.getEthernetIfaceList([
- &, managerId{std::move(managerId)},
- rootInterfaceName{std::move(rootInterfaceName)}
- ](const bool &success, const std::vector<std::string> &iface_list) {
- if (success) {
- bool rootInterfaceFound = false;
- nlohmann::json ifaceArray = nlohmann::json::array();
-
- for (const std::string &ifaceItem : iface_list) {
- if (ifaceItem == rootInterfaceName) {
- rootInterfaceFound = true;
- } else if (boost::starts_with(ifaceItem, rootInterfaceName + "_")) {
- ifaceArray.push_back(
- {{"@odata.id", "/redfish/v1/Managers/" + managerId +
- "/EthernetInterfaces/" + rootInterfaceName +
- "/VLANs/" + ifaceItem}});
- }
+ return;
}
- if (rootInterfaceFound) {
- Node::json["Members"] = ifaceArray;
- Node::json["Members@odata.count"] = ifaceArray.size();
- Node::json["@odata.id"] = "/redfish/v1/Managers/" + managerId +
- "/EthernetInterfaces/" + rootInterfaceName +
- "/VLANs";
- res.jsonValue = Node::json;
- } else {
- messages::addMessageToErrorJson(
- res.jsonValue, messages::resourceNotFound("EthernetInterface",
- rootInterfaceName));
- res.result(boost::beast::http::status::not_found);
- res.end();
- }
- } else {
- // No success, best what we can do is return INTERNALL ERROR
- res.result(boost::beast::http::status::internal_server_error);
- }
- res.end();
- });
- }
+ // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces
+ // for any Manager, not only hardcoded 'openbmc'.
+ std::string managerId = "openbmc";
+ std::string rootInterfaceName = params[0];
- void doPost(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- if (params.size() != 1) {
- // This means there is a problem with the router
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
- }
+ // get eth interface list, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceList(
+ [&, managerId{std::move(managerId)},
+ rootInterfaceName{std::move(rootInterfaceName)}](
+ const bool &success,
+ const std::vector<std::string> &iface_list) {
+ if (success)
+ {
+ bool rootInterfaceFound = false;
+ nlohmann::json ifaceArray = nlohmann::json::array();
- nlohmann::json postReq;
+ for (const std::string &ifaceItem : iface_list)
+ {
+ if (ifaceItem == rootInterfaceName)
+ {
+ rootInterfaceFound = true;
+ }
+ else if (boost::starts_with(ifaceItem,
+ rootInterfaceName + "_"))
+ {
+ ifaceArray.push_back(
+ {{"@odata.id", "/redfish/v1/Managers/" +
+ managerId +
+ "/EthernetInterfaces/" +
+ rootInterfaceName +
+ "/VLANs/" + ifaceItem}});
+ }
+ }
- if (!json_util::processJsonFromRequest(res, req, postReq)) {
- return;
- }
-
- // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces for
- // any Manager, not only hardcoded 'openbmc'.
- std::string managerId = "openbmc";
- std::string rootInterfaceName = params[0];
- uint64_t vlanId;
- bool errorDetected;
-
- if (json_util::getUnsigned(
- "VLANId", postReq, vlanId,
- static_cast<uint8_t>(json_util::MessageSetting::MISSING) |
- static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
- res.jsonValue, "/VLANId") != json_util::Result::SUCCESS) {
- res.end();
- return;
- }
-
- // get eth interface list, and call the below callback for JSON preparation
- ethernetProvider.getEthernetIfaceList([
- &, managerId{std::move(managerId)},
- rootInterfaceName{std::move(rootInterfaceName)}
- ](const bool &success, const std::vector<std::string> &iface_list) {
- if (success) {
- bool rootInterfaceFound = false;
-
- for (const std::string &ifaceItem : iface_list) {
- if (ifaceItem == rootInterfaceName) {
- rootInterfaceFound = true;
- break;
- }
- }
-
- if (rootInterfaceFound) {
- ethernetProvider.createVlan(
- rootInterfaceName, vlanId,
- [&, vlanId, rootInterfaceName,
- req{std::move(req)} ](const boost::system::error_code ec) {
- if (ec) {
- messages::addMessageToErrorJson(res.jsonValue,
- messages::internalError());
- res.end();
- } else {
- memberVlan.doGet(
- res, req,
- {rootInterfaceName,
- rootInterfaceName + "_" + std::to_string(vlanId)});
+ if (rootInterfaceFound)
+ {
+ Node::json["Members"] = ifaceArray;
+ Node::json["Members@odata.count"] = ifaceArray.size();
+ Node::json["@odata.id"] = "/redfish/v1/Managers/" +
+ managerId +
+ "/EthernetInterfaces/" +
+ rootInterfaceName + "/VLANs";
+ res.jsonValue = Node::json;
+ }
+ else
+ {
+ messages::addMessageToErrorJson(
+ res.jsonValue,
+ messages::resourceNotFound("EthernetInterface",
+ rootInterfaceName));
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+ }
}
- });
- } else {
- messages::addMessageToErrorJson(
- res.jsonValue, messages::resourceNotFound("EthernetInterface",
- rootInterfaceName));
- res.result(boost::beast::http::status::not_found);
- res.end();
- }
- } else {
- // No success, best what we can do is return INTERNALL ERROR
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- }
- });
- }
+ else
+ {
+ // No success, best what we can do is return INTERNALL ERROR
+ res.result(
+ boost::beast::http::status::internal_server_error);
+ }
+ res.end();
+ });
+ }
- // Ethernet Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandEthernetProvider ethernetProvider;
- VlanNetworkInterface memberVlan;
+ void doPost(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ if (params.size() != 1)
+ {
+ // This means there is a problem with the router
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+
+ nlohmann::json postReq;
+
+ if (!json_util::processJsonFromRequest(res, req, postReq))
+ {
+ return;
+ }
+
+ // TODO(Pawel) this shall be parametrized call to get EthernetInterfaces
+ // for any Manager, not only hardcoded 'openbmc'.
+ std::string managerId = "openbmc";
+ std::string rootInterfaceName = params[0];
+ uint64_t vlanId;
+ bool errorDetected;
+
+ if (json_util::getUnsigned(
+ "VLANId", postReq, vlanId,
+ static_cast<uint8_t>(json_util::MessageSetting::MISSING) |
+ static_cast<uint8_t>(json_util::MessageSetting::TYPE_ERROR),
+ res.jsonValue, "/VLANId") != json_util::Result::SUCCESS)
+ {
+ res.end();
+ return;
+ }
+
+ // get eth interface list, and call the below callback for JSON
+ // preparation
+ ethernetProvider.getEthernetIfaceList(
+ [&, managerId{std::move(managerId)},
+ rootInterfaceName{std::move(rootInterfaceName)}](
+ const bool &success,
+ const std::vector<std::string> &iface_list) {
+ if (success)
+ {
+ bool rootInterfaceFound = false;
+
+ for (const std::string &ifaceItem : iface_list)
+ {
+ if (ifaceItem == rootInterfaceName)
+ {
+ rootInterfaceFound = true;
+ break;
+ }
+ }
+
+ if (rootInterfaceFound)
+ {
+ ethernetProvider.createVlan(
+ rootInterfaceName, vlanId,
+ [&, vlanId, rootInterfaceName, req{std::move(req)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ messages::addMessageToErrorJson(
+ res.jsonValue,
+ messages::internalError());
+ res.end();
+ }
+ else
+ {
+ memberVlan.doGet(
+ res, req,
+ {rootInterfaceName,
+ rootInterfaceName + "_" +
+ std::to_string(vlanId)});
+ }
+ });
+ }
+ else
+ {
+ messages::addMessageToErrorJson(
+ res.jsonValue,
+ messages::resourceNotFound("EthernetInterface",
+ rootInterfaceName));
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+ }
+ }
+ else
+ {
+ // No success, best what we can do is return INTERNALL ERROR
+ res.result(
+ boost::beast::http::status::internal_server_error);
+ res.end();
+ }
+ });
+ }
+
+ // Ethernet Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandEthernetProvider ethernetProvider;
+ VlanNetworkInterface memberVlan;
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 7a861b4..86fe567 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -17,101 +17,111 @@
#include "node.hpp"
-namespace redfish {
+namespace redfish
+{
-class Manager : public Node {
- public:
- Manager(CrowApp& app) : Node(app, "/redfish/v1/Managers/openbmc/") {
- Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc";
- Node::json["@odata.type"] = "#Manager.v1_3_0.Manager";
- Node::json["@odata.context"] = "/redfish/v1/$metadata#Manager.Manager";
- Node::json["Id"] = "openbmc";
- Node::json["Name"] = "OpenBmc Manager";
- Node::json["Description"] = "Baseboard Management Controller";
- Node::json["PowerState"] = "On";
- Node::json["UUID"] =
- app.template getMiddleware<crow::persistent_data::Middleware>()
- .systemUuid;
- Node::json["Model"] = "OpenBmc"; // TODO(ed), get model
- Node::json["FirmwareVersion"] = "1234456789"; // TODO(ed), get fwversion
- Node::json["EthernetInterfaces"] = nlohmann::json(
- {{"@odata.id",
- "/redfish/v1/Managers/openbmc/EthernetInterfaces"}}); // TODO(Pawel),
- // remove this
- // when
- // subroutes
- // will work
- // correctly
+class Manager : public Node
+{
+ public:
+ Manager(CrowApp& app) : Node(app, "/redfish/v1/Managers/openbmc/")
+ {
+ Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc";
+ Node::json["@odata.type"] = "#Manager.v1_3_0.Manager";
+ Node::json["@odata.context"] = "/redfish/v1/$metadata#Manager.Manager";
+ Node::json["Id"] = "openbmc";
+ Node::json["Name"] = "OpenBmc Manager";
+ Node::json["Description"] = "Baseboard Management Controller";
+ Node::json["PowerState"] = "On";
+ Node::json["UUID"] =
+ app.template getMiddleware<crow::persistent_data::Middleware>()
+ .systemUuid;
+ Node::json["Model"] = "OpenBmc"; // TODO(ed), get model
+ Node::json["FirmwareVersion"] = "1234456789"; // TODO(ed), get fwversion
+ Node::json["EthernetInterfaces"] = nlohmann::json(
+ {{"@odata.id", "/redfish/v1/Managers/openbmc/"
+ "EthernetInterfaces"}}); // TODO(Pawel),
+ // remove this
+ // when
+ // subroutes
+ // will work
+ // correctly
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- Node::json["DateTime"] = getDateTime();
- // Copy over the static data to include the entries added by SubRoute
- res.jsonValue = Node::json;
- res.end();
- }
-
- std::string getDateTime() const {
- std::array<char, 128> dateTime;
- std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
- std::time_t time = std::time(nullptr);
-
- if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
- std::localtime(&time))) {
- // insert the colon required by the ISO 8601 standard
- redfishDateTime = std::string(dateTime.data());
- redfishDateTime.insert(redfishDateTime.end() - 2, ':');
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
}
- return redfishDateTime;
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ Node::json["DateTime"] = getDateTime();
+ // Copy over the static data to include the entries added by SubRoute
+ res.jsonValue = Node::json;
+ res.end();
+ }
+
+ std::string getDateTime() const
+ {
+ std::array<char, 128> dateTime;
+ std::string redfishDateTime("0000-00-00T00:00:00Z00:00");
+ std::time_t time = std::time(nullptr);
+
+ if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z",
+ std::localtime(&time)))
+ {
+ // insert the colon required by the ISO 8601 standard
+ redfishDateTime = std::string(dateTime.data());
+ redfishDateTime.insert(redfishDateTime.end() - 2, ':');
+ }
+
+ return redfishDateTime;
+ }
};
-class ManagerCollection : public Node {
- public:
- ManagerCollection(CrowApp& app) : Node(app, "/redfish/v1/Managers/") {
- Node::json["@odata.id"] = "/redfish/v1/Managers";
- Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
- Node::json["Name"] = "Manager Collection";
- Node::json["Members@odata.count"] = 1;
- Node::json["Members"] = {{{"@odata.id", "/redfish/v1/Managers/openbmc"}}};
+class ManagerCollection : public Node
+{
+ public:
+ ManagerCollection(CrowApp& app) : Node(app, "/redfish/v1/Managers/")
+ {
+ Node::json["@odata.id"] = "/redfish/v1/Managers";
+ Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
+ Node::json["Name"] = "Manager Collection";
+ Node::json["Members@odata.count"] = 1;
+ Node::json["Members"] = {
+ {{"@odata.id", "/redfish/v1/Managers/openbmc"}}};
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ }
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- // Collections don't include the static data added by SubRoute because it
- // has a duplicate entry for members
- res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
- res.jsonValue["@odata.type"] = "#ManagerCollection.ManagerCollection";
- res.jsonValue["@odata.context"] =
- "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
- res.jsonValue["Name"] = "Manager Collection";
- res.jsonValue["Members@odata.count"] = 1;
- res.jsonValue["Members"] = {
- {{"@odata.id", "/redfish/v1/Managers/openbmc"}}};
- res.end();
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ // Collections don't include the static data added by SubRoute because
+ // it has a duplicate entry for members
+ res.jsonValue["@odata.id"] = "/redfish/v1/Managers";
+ res.jsonValue["@odata.type"] = "#ManagerCollection.ManagerCollection";
+ res.jsonValue["@odata.context"] =
+ "/redfish/v1/$metadata#ManagerCollection.ManagerCollection";
+ res.jsonValue["Name"] = "Manager Collection";
+ res.jsonValue["Members@odata.count"] = 1;
+ res.jsonValue["Members"] = {
+ {{"@odata.id", "/redfish/v1/Managers/openbmc"}}};
+ res.end();
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp
index ae29df0..bb021f5 100644
--- a/redfish-core/lib/network_protocol.hpp
+++ b/redfish-core/lib/network_protocol.hpp
@@ -18,24 +18,27 @@
#include "error_messages.hpp"
#include "node.hpp"
-namespace redfish {
+namespace redfish
+{
-enum NetworkProtocolUnitStructFields {
- NET_PROTO_UNIT_NAME,
- NET_PROTO_UNIT_DESC,
- NET_PROTO_UNIT_LOAD_STATE,
- NET_PROTO_UNIT_ACTIVE_STATE,
- NET_PROTO_UNIT_SUB_STATE,
- NET_PROTO_UNIT_DEVICE,
- NET_PROTO_UNIT_OBJ_PATH,
- NET_PROTO_UNIT_ALWAYS_0,
- NET_PROTO_UNIT_ALWAYS_EMPTY,
- NET_PROTO_UNIT_ALWAYS_ROOT_PATH
+enum NetworkProtocolUnitStructFields
+{
+ NET_PROTO_UNIT_NAME,
+ NET_PROTO_UNIT_DESC,
+ NET_PROTO_UNIT_LOAD_STATE,
+ NET_PROTO_UNIT_ACTIVE_STATE,
+ NET_PROTO_UNIT_SUB_STATE,
+ NET_PROTO_UNIT_DEVICE,
+ NET_PROTO_UNIT_OBJ_PATH,
+ NET_PROTO_UNIT_ALWAYS_0,
+ NET_PROTO_UNIT_ALWAYS_EMPTY,
+ NET_PROTO_UNIT_ALWAYS_ROOT_PATH
};
-enum NetworkProtocolListenResponseElements {
- NET_PROTO_LISTEN_TYPE,
- NET_PROTO_LISTEN_STREAM
+enum NetworkProtocolListenResponseElements
+{
+ NET_PROTO_LISTEN_TYPE,
+ NET_PROTO_LISTEN_STREAM
};
/**
@@ -46,9 +49,10 @@
std::string, sdbusplus::message::object_path, uint32_t,
std::string, sdbusplus::message::object_path>;
-struct ServiceConfiguration {
- const char* serviceName;
- const char* socketPath;
+struct ServiceConfiguration
+{
+ const char* serviceName;
+ const char* socketPath;
};
const static boost::container::flat_map<const char*, ServiceConfiguration>
@@ -63,128 +67,161 @@
{"phosphor-ipmi-net.service",
"/org/freedesktop/systemd1/unit/phosphor_2dipmi_2dnet_2esocket"}}};
-class NetworkProtocol : public Node {
- public:
- NetworkProtocol(CrowApp& app)
- : Node(app, "/redfish/v1/Managers/openbmc/NetworkProtocol") {
- Node::json["@odata.type"] =
- "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol";
- Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc/NetworkProtocol";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol";
- Node::json["Id"] = "NetworkProtocol";
- Node::json["Name"] = "Manager Network Protocol";
- Node::json["Description"] = "Manager Network Service";
- Node::json["Status"]["Health"] = "OK";
- Node::json["Status"]["HealthRollup"] = "OK";
- Node::json["Status"]["State"] = "Enabled";
+class NetworkProtocol : public Node
+{
+ public:
+ NetworkProtocol(CrowApp& app) :
+ Node(app, "/redfish/v1/Managers/openbmc/NetworkProtocol")
+ {
+ Node::json["@odata.type"] =
+ "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol";
+ Node::json["@odata.id"] =
+ "/redfish/v1/Managers/openbmc/NetworkProtocol";
+ Node::json["@odata.context"] =
+ "/redfish/v1/"
+ "$metadata#ManagerNetworkProtocol.ManagerNetworkProtocol";
+ Node::json["Id"] = "NetworkProtocol";
+ Node::json["Name"] = "Manager Network Protocol";
+ Node::json["Description"] = "Manager Network Service";
+ Node::json["Status"]["Health"] = "OK";
+ Node::json["Status"]["HealthRollup"] = "OK";
+ Node::json["Status"]["State"] = "Enabled";
- for (auto& protocol : protocolToDBus) {
- Node::json[protocol.first]["ProtocolEnabled"] = false;
+ for (auto& protocol : protocolToDBus)
+ {
+ Node::json[protocol.first]["ProtocolEnabled"] = false;
+ }
+
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
}
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
-
- getData(asyncResp);
- }
-
- std::string getHostName() const {
- std::string hostName;
-
- std::array<char, HOST_NAME_MAX> hostNameCStr;
- if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0) {
- hostName = hostNameCStr.data();
+ getData(asyncResp);
}
- return hostName;
- }
- void getData(const std::shared_ptr<AsyncResp>& asyncResp) {
- Node::json["HostName"] = getHostName();
- asyncResp->res.jsonValue = Node::json;
+ std::string getHostName() const
+ {
+ std::string hostName;
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code ec,
- const std::vector<UnitStruct>& resp) {
- if (ec) {
- asyncResp->res.jsonValue = nlohmann::json::object();
- messages::addMessageToErrorJson(asyncResp->res.jsonValue,
- messages::internalError());
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
+ std::array<char, HOST_NAME_MAX> hostNameCStr;
+ if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
+ {
+ hostName = hostNameCStr.data();
+ }
+ return hostName;
+ }
- for (auto& unit : resp) {
- for (auto& kv : protocolToDBus) {
- if (kv.second.serviceName ==
- std::get<NET_PROTO_UNIT_NAME>(unit)) {
- continue;
- }
- const char* service = kv.first;
- const char* socketPath = kv.second.socketPath;
+ void getData(const std::shared_ptr<AsyncResp>& asyncResp)
+ {
+ Node::json["HostName"] = getHostName();
+ asyncResp->res.jsonValue = Node::json;
- asyncResp->res.jsonValue[service]["ProtocolEnabled"] =
- std::get<NET_PROTO_UNIT_SUB_STATE>(unit) == "running";
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::vector<UnitStruct>& resp) {
+ if (ec)
+ {
+ asyncResp->res.jsonValue = nlohmann::json::object();
+ messages::addMessageToErrorJson(asyncResp->res.jsonValue,
+ messages::internalError());
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
- crow::connections::systemBus->async_method_call(
- [ asyncResp, service{std::string(service)}, socketPath ](
- const boost::system::error_code ec,
- const sdbusplus::message::variant<std::vector<
- std::tuple<std::string, std::string>>>& resp) {
- if (ec) {
- messages::addMessageToJson(asyncResp->res.jsonValue,
- messages::internalError(),
- "/" + service);
- return;
+ for (auto& unit : resp)
+ {
+ for (auto& kv : protocolToDBus)
+ {
+ if (kv.second.serviceName ==
+ std::get<NET_PROTO_UNIT_NAME>(unit))
+ {
+ continue;
+ }
+ const char* service = kv.first;
+ const char* socketPath = kv.second.socketPath;
+
+ asyncResp->res.jsonValue[service]["ProtocolEnabled"] =
+ std::get<NET_PROTO_UNIT_SUB_STATE>(unit) ==
+ "running";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, service{std::string(service)},
+ socketPath](
+ const boost::system::error_code ec,
+ const sdbusplus::message::variant<std::vector<
+ std::tuple<std::string, std::string>>>&
+ resp) {
+ if (ec)
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::internalError(),
+ "/" + service);
+ return;
+ }
+ const std::vector<std::tuple<
+ std::string, std::string>>* responsePtr =
+ mapbox::getPtr<const std::vector<
+ std::tuple<std::string, std::string>>>(
+ resp);
+ if (responsePtr == nullptr ||
+ responsePtr->size() < 1)
+ {
+ return;
+ }
+
+ const std::string& listenStream =
+ std::get<NET_PROTO_LISTEN_STREAM>(
+ (*responsePtr)[0]);
+ std::size_t lastColonPos =
+ listenStream.rfind(":");
+ if (lastColonPos == std::string::npos)
+ {
+ // Not a port
+ return;
+ }
+ std::string portStr =
+ listenStream.substr(lastColonPos + 1);
+ char* endPtr = nullptr;
+ // Use strtol instead of stroi to avoid
+ // exceptions
+ long port =
+ std::strtol(portStr.c_str(), &endPtr, 10);
+
+ if (*endPtr != '\0' || portStr.empty())
+ {
+ // Invalid value
+ asyncResp->res.jsonValue[service]["Port"] =
+ nullptr;
+ }
+ else
+ {
+ // Everything OK
+ asyncResp->res.jsonValue[service]["Port"] =
+ port;
+ }
+ },
+ "org.freedesktop.systemd1", socketPath,
+ "org.freedesktop.DBus.Properties", "Get",
+ "org.freedesktop.systemd1.Socket", "Listen");
}
- const std::vector<std::tuple<std::string, std::string>>*
- responsePtr = mapbox::getPtr<const std::vector<
- std::tuple<std::string, std::string>>>(resp);
- if (responsePtr == nullptr || responsePtr->size() < 1) {
- return;
- }
-
- const std::string& listenStream =
- std::get<NET_PROTO_LISTEN_STREAM>((*responsePtr)[0]);
- std::size_t lastColonPos = listenStream.rfind(":");
- if (lastColonPos == std::string::npos) {
- // Not a port
- return;
- }
- std::string portStr = listenStream.substr(lastColonPos + 1);
- char* endPtr = nullptr;
- // Use strtol instead of stroi to avoid exceptions
- long port = std::strtol(portStr.c_str(), &endPtr, 10);
-
- if (*endPtr != '\0' || portStr.empty()) {
- // Invalid value
- asyncResp->res.jsonValue[service]["Port"] = nullptr;
- } else {
- // Everything OK
- asyncResp->res.jsonValue[service]["Port"] = port;
- }
- },
- "org.freedesktop.systemd1", socketPath,
- "org.freedesktop.DBus.Properties", "Get",
- "org.freedesktop.systemd1.Socket", "Listen");
- }
- }
- },
- "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager", "ListUnits");
- }
+ }
+ },
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager", "ListUnits");
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index ca1c375..2406250 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -19,312 +19,348 @@
#include "node.hpp"
#include "persistent_data_middleware.hpp"
-namespace redfish {
+namespace redfish
+{
class SessionCollection;
-class Sessions : public Node {
- public:
- Sessions(CrowApp& app)
- : Node(app, "/redfish/v1/SessionService/Sessions/<str>/", std::string()) {
- Node::json["@odata.type"] = "#Session.v1_0_2.Session";
- Node::json["@odata.context"] = "/redfish/v1/$metadata#Session.Session";
- Node::json["Name"] = "User Session";
- Node::json["Description"] = "Manager User Session";
+class Sessions : public Node
+{
+ public:
+ Sessions(CrowApp& app) :
+ Node(app, "/redfish/v1/SessionService/Sessions/<str>/", std::string())
+ {
+ Node::json["@odata.type"] = "#Session.v1_0_2.Session";
+ Node::json["@odata.context"] = "/redfish/v1/$metadata#Session.Session";
+ Node::json["Name"] = "User Session";
+ Node::json["Description"] = "Manager User Session";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- auto session =
- crow::persistent_data::SessionStore::getInstance().getSessionByUid(
- params[0]);
-
- if (session == nullptr) {
- messages::addMessageToErrorJson(
- res.jsonValue, messages::resourceNotFound("Session", params[0]));
-
- res.result(boost::beast::http::status::not_found);
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
}
- Node::json["Id"] = session->uniqueId;
- Node::json["UserName"] = session->username;
- Node::json["@odata.id"] =
- "/redfish/v1/SessionService/Sessions/" + session->uniqueId;
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ auto session =
+ crow::persistent_data::SessionStore::getInstance().getSessionByUid(
+ params[0]);
- res.jsonValue = Node::json;
- res.end();
- }
+ if (session == nullptr)
+ {
+ messages::addMessageToErrorJson(
+ res.jsonValue,
+ messages::resourceNotFound("Session", params[0]));
- void doDelete(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- // Need only 1 param which should be id of session to be deleted
- if (params.size() != 1) {
- // This should be handled by crow and never happen
- BMCWEB_LOG_ERROR
- << "Session DELETE has been called with invalid number of params";
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+ return;
+ }
- res.result(boost::beast::http::status::bad_request);
- messages::addMessageToErrorJson(res.jsonValue, messages::generalError());
+ Node::json["Id"] = session->uniqueId;
+ Node::json["UserName"] = session->username;
+ Node::json["@odata.id"] =
+ "/redfish/v1/SessionService/Sessions/" + session->uniqueId;
- res.end();
- return;
+ res.jsonValue = Node::json;
+ res.end();
}
- auto session =
- crow::persistent_data::SessionStore::getInstance().getSessionByUid(
- params[0]);
+ void doDelete(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ // Need only 1 param which should be id of session to be deleted
+ if (params.size() != 1)
+ {
+ // This should be handled by crow and never happen
+ BMCWEB_LOG_ERROR << "Session DELETE has been called with invalid "
+ "number of params";
- if (session == nullptr) {
- messages::addMessageToErrorJson(
- res.jsonValue, messages::resourceNotFound("Session", params[0]));
+ res.result(boost::beast::http::status::bad_request);
+ messages::addMessageToErrorJson(res.jsonValue,
+ messages::generalError());
- res.result(boost::beast::http::status::not_found);
- res.end();
- return;
+ res.end();
+ return;
+ }
+
+ auto session =
+ crow::persistent_data::SessionStore::getInstance().getSessionByUid(
+ params[0]);
+
+ if (session == nullptr)
+ {
+ messages::addMessageToErrorJson(
+ res.jsonValue,
+ messages::resourceNotFound("Session", params[0]));
+
+ res.result(boost::beast::http::status::not_found);
+ res.end();
+ return;
+ }
+
+ // DELETE should return representation of object that will be removed
+ doGet(res, req, params);
+
+ crow::persistent_data::SessionStore::getInstance().removeSession(
+ session);
}
- // DELETE should return representation of object that will be removed
- doGet(res, req, params);
-
- crow::persistent_data::SessionStore::getInstance().removeSession(session);
- }
-
- /**
- * This allows SessionCollection to reuse this class' doGet method, to
- * maintain consistency of returned data, as Collection's doPost should return
- * data for created member which should match member's doGet result in 100%
- */
- friend SessionCollection;
+ /**
+ * This allows SessionCollection to reuse this class' doGet method, to
+ * maintain consistency of returned data, as Collection's doPost should
+ * return data for created member which should match member's doGet result
+ * in 100%
+ */
+ friend SessionCollection;
};
-class SessionCollection : public Node {
- public:
- SessionCollection(CrowApp& app)
- : Node(app, "/redfish/v1/SessionService/Sessions/"), memberSession(app) {
- Node::json["@odata.type"] = "#SessionCollection.SessionCollection";
- Node::json["@odata.id"] = "/redfish/v1/SessionService/Sessions/";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#SessionCollection.SessionCollection";
- Node::json["Name"] = "Session Collection";
- Node::json["Description"] = "Session Collection";
- Node::json["Members@odata.count"] = 0;
- Node::json["Members"] = nlohmann::json::array();
+class SessionCollection : public Node
+{
+ public:
+ SessionCollection(CrowApp& app) :
+ Node(app, "/redfish/v1/SessionService/Sessions/"), memberSession(app)
+ {
+ Node::json["@odata.type"] = "#SessionCollection.SessionCollection";
+ Node::json["@odata.id"] = "/redfish/v1/SessionService/Sessions/";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#SessionCollection.SessionCollection";
+ Node::json["Name"] = "Session Collection";
+ Node::json["Description"] = "Session Collection";
+ Node::json["Members@odata.count"] = 0;
+ Node::json["Members"] = nlohmann::json::array();
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {}}};
- }
-
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- std::vector<const std::string*> sessionIds =
- crow::persistent_data::SessionStore::getInstance().getUniqueIds(
- false, crow::persistent_data::PersistenceType::TIMEOUT);
-
- Node::json["Members@odata.count"] = sessionIds.size();
- Node::json["Members"] = nlohmann::json::array();
- for (const std::string* uid : sessionIds) {
- Node::json["Members"].push_back(
- {{"@odata.id", "/redfish/v1/SessionService/Sessions/" + *uid}});
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {}}};
}
- res.jsonValue = Node::json;
- res.end();
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ std::vector<const std::string*> sessionIds =
+ crow::persistent_data::SessionStore::getInstance().getUniqueIds(
+ false, crow::persistent_data::PersistenceType::TIMEOUT);
- void doPost(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- boost::beast::http::status status;
- std::string username;
- bool userAuthSuccessful =
- authenticateUser(req, status, username, res.jsonValue);
- res.result(status);
+ Node::json["Members@odata.count"] = sessionIds.size();
+ Node::json["Members"] = nlohmann::json::array();
+ for (const std::string* uid : sessionIds)
+ {
+ Node::json["Members"].push_back(
+ {{"@odata.id", "/redfish/v1/SessionService/Sessions/" + *uid}});
+ }
- if (!userAuthSuccessful) {
- res.end();
- return;
+ res.jsonValue = Node::json;
+ res.end();
}
- // User is authenticated - create session for him
- auto session =
- crow::persistent_data::SessionStore::getInstance().generateUserSession(
- username);
- res.addHeader("X-Auth-Token", session->sessionToken);
+ void doPost(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ boost::beast::http::status status;
+ std::string username;
+ bool userAuthSuccessful =
+ authenticateUser(req, status, username, res.jsonValue);
+ res.result(status);
- res.addHeader("Location",
- "/redfish/v1/SessionService/Sessions/" + session->uniqueId);
+ if (!userAuthSuccessful)
+ {
+ res.end();
+ return;
+ }
- // Return data for created session
- memberSession.doGet(res, req, {session->uniqueId});
+ // User is authenticated - create session for him
+ auto session = crow::persistent_data::SessionStore::getInstance()
+ .generateUserSession(username);
+ res.addHeader("X-Auth-Token", session->sessionToken);
- // No need for res.end(), as it is called by doGet()
- }
+ res.addHeader("Location", "/redfish/v1/SessionService/Sessions/" +
+ session->uniqueId);
- /**
- * @brief Verifies data provided in request and tries to authenticate user
- *
- * @param[in] req Crow request containing authentication data
- * @param[out] httpRespCode HTTP Code that should be returned in response
- * @param[out] user Retrieved username - not filled on failure
- * @param[out] errJson JSON to which error messages will be written
- *
- * @return true if authentication was successful, false otherwise
- */
- bool authenticateUser(const crow::Request& req,
- boost::beast::http::status& httpRespCode,
- std::string& user, nlohmann::json& errJson) {
- // We need only UserName and Password - nothing more, nothing less
- static constexpr const unsigned int numberOfRequiredFieldsInReq = 2;
+ // Return data for created session
+ memberSession.doGet(res, req, {session->uniqueId});
- // call with exceptions disabled
- auto loginCredentials = nlohmann::json::parse(req.body, nullptr, false);
- if (loginCredentials.is_discarded()) {
- httpRespCode = boost::beast::http::status::bad_request;
-
- messages::addMessageToErrorJson(errJson, messages::malformedJSON());
-
- return false;
+ // No need for res.end(), as it is called by doGet()
}
- // Check that there are only as many fields as there should be
- if (loginCredentials.size() != numberOfRequiredFieldsInReq) {
- httpRespCode = boost::beast::http::status::bad_request;
+ /**
+ * @brief Verifies data provided in request and tries to authenticate user
+ *
+ * @param[in] req Crow request containing authentication data
+ * @param[out] httpRespCode HTTP Code that should be returned in response
+ * @param[out] user Retrieved username - not filled on failure
+ * @param[out] errJson JSON to which error messages will be written
+ *
+ * @return true if authentication was successful, false otherwise
+ */
+ bool authenticateUser(const crow::Request& req,
+ boost::beast::http::status& httpRespCode,
+ std::string& user, nlohmann::json& errJson)
+ {
+ // We need only UserName and Password - nothing more, nothing less
+ static constexpr const unsigned int numberOfRequiredFieldsInReq = 2;
- messages::addMessageToErrorJson(errJson, messages::malformedJSON());
+ // call with exceptions disabled
+ auto loginCredentials = nlohmann::json::parse(req.body, nullptr, false);
+ if (loginCredentials.is_discarded())
+ {
+ httpRespCode = boost::beast::http::status::bad_request;
- return false;
+ messages::addMessageToErrorJson(errJson, messages::malformedJSON());
+
+ return false;
+ }
+
+ // Check that there are only as many fields as there should be
+ if (loginCredentials.size() != numberOfRequiredFieldsInReq)
+ {
+ httpRespCode = boost::beast::http::status::bad_request;
+
+ messages::addMessageToErrorJson(errJson, messages::malformedJSON());
+
+ return false;
+ }
+
+ // Find fields that we need - UserName and Password
+ auto userIt = loginCredentials.find("UserName");
+ auto passIt = loginCredentials.find("Password");
+ if (userIt == loginCredentials.end() ||
+ passIt == loginCredentials.end())
+ {
+ httpRespCode = boost::beast::http::status::bad_request;
+
+ if (userIt == loginCredentials.end())
+ {
+ messages::addMessageToErrorJson(
+ errJson, messages::propertyMissing("UserName"));
+ }
+
+ if (passIt == loginCredentials.end())
+ {
+ messages::addMessageToErrorJson(
+ errJson, messages::propertyMissing("Password"));
+ }
+
+ return false;
+ }
+
+ // Check that given data is of valid type (string)
+ if (!userIt->is_string() || !passIt->is_string())
+ {
+ httpRespCode = boost::beast::http::status::bad_request;
+
+ if (!userIt->is_string())
+ {
+ messages::addMessageToErrorJson(
+ errJson, messages::propertyValueTypeError(userIt->dump(),
+ "UserName"));
+ }
+
+ if (!passIt->is_string())
+ {
+ messages::addMessageToErrorJson(
+ errJson, messages::propertyValueTypeError(userIt->dump(),
+ "Password"));
+ }
+
+ return false;
+ }
+
+ // Extract username and password
+ std::string username = userIt->get<const std::string>();
+ std::string password = passIt->get<const std::string>();
+
+ // Verify that required fields are not empty
+ if (username.empty() || password.empty())
+ {
+ httpRespCode = boost::beast::http::status::bad_request;
+
+ if (username.empty())
+ {
+ messages::addMessageToErrorJson(
+ errJson, messages::propertyMissing("UserName"));
+ }
+
+ if (password.empty())
+ {
+ messages::addMessageToErrorJson(
+ errJson, messages::propertyMissing("Password"));
+ }
+
+ return false;
+ }
+
+ // Finally - try to authenticate user
+ if (!pamAuthenticateUser(username, password))
+ {
+ httpRespCode = boost::beast::http::status::unauthorized;
+
+ messages::addMessageToErrorJson(
+ errJson,
+ messages::resourceAtUriUnauthorized(
+ std::string(req.url), "Invalid username or password"));
+
+ return false;
+ }
+
+ // User authenticated successfully
+ httpRespCode = boost::beast::http::status::ok;
+ user = username;
+
+ return true;
}
- // Find fields that we need - UserName and Password
- auto userIt = loginCredentials.find("UserName");
- auto passIt = loginCredentials.find("Password");
- if (userIt == loginCredentials.end() || passIt == loginCredentials.end()) {
- httpRespCode = boost::beast::http::status::bad_request;
-
- if (userIt == loginCredentials.end()) {
- messages::addMessageToErrorJson(errJson,
- messages::propertyMissing("UserName"));
- }
-
- if (passIt == loginCredentials.end()) {
- messages::addMessageToErrorJson(errJson,
- messages::propertyMissing("Password"));
- }
-
- return false;
- }
-
- // Check that given data is of valid type (string)
- if (!userIt->is_string() || !passIt->is_string()) {
- httpRespCode = boost::beast::http::status::bad_request;
-
- if (!userIt->is_string()) {
- messages::addMessageToErrorJson(
- errJson,
- messages::propertyValueTypeError(userIt->dump(), "UserName"));
- }
-
- if (!passIt->is_string()) {
- messages::addMessageToErrorJson(
- errJson,
- messages::propertyValueTypeError(userIt->dump(), "Password"));
- }
-
- return false;
- }
-
- // Extract username and password
- std::string username = userIt->get<const std::string>();
- std::string password = passIt->get<const std::string>();
-
- // Verify that required fields are not empty
- if (username.empty() || password.empty()) {
- httpRespCode = boost::beast::http::status::bad_request;
-
- if (username.empty()) {
- messages::addMessageToErrorJson(errJson,
- messages::propertyMissing("UserName"));
- }
-
- if (password.empty()) {
- messages::addMessageToErrorJson(errJson,
- messages::propertyMissing("Password"));
- }
-
- return false;
- }
-
- // Finally - try to authenticate user
- if (!pamAuthenticateUser(username, password)) {
- httpRespCode = boost::beast::http::status::unauthorized;
-
- messages::addMessageToErrorJson(
- errJson, messages::resourceAtUriUnauthorized(
- std::string(req.url), "Invalid username or password"));
-
- return false;
- }
-
- // User authenticated successfully
- httpRespCode = boost::beast::http::status::ok;
- user = username;
-
- return true;
- }
-
- /**
- * Member session to ensure consistency between collection's doPost and
- * member's doGet, as they should return 100% matching data
- */
- Sessions memberSession;
+ /**
+ * Member session to ensure consistency between collection's doPost and
+ * member's doGet, as they should return 100% matching data
+ */
+ Sessions memberSession;
};
-class SessionService : public Node {
- public:
- SessionService(CrowApp& app) : Node(app, "/redfish/v1/SessionService/") {
- Node::json["@odata.type"] = "#SessionService.v1_0_2.SessionService";
- Node::json["@odata.id"] = "/redfish/v1/SessionService/";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#SessionService.SessionService";
- Node::json["Name"] = "Session Service";
- Node::json["Id"] = "SessionService";
- Node::json["Description"] = "Session Service";
- Node::json["SessionTimeout"] =
- crow::persistent_data::SessionStore::getInstance()
- .getTimeoutInSeconds();
- Node::json["ServiceEnabled"] = true;
+class SessionService : public Node
+{
+ public:
+ SessionService(CrowApp& app) : Node(app, "/redfish/v1/SessionService/")
+ {
+ Node::json["@odata.type"] = "#SessionService.v1_0_2.SessionService";
+ Node::json["@odata.id"] = "/redfish/v1/SessionService/";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#SessionService.SessionService";
+ Node::json["Name"] = "Session Service";
+ Node::json["Id"] = "SessionService";
+ Node::json["Description"] = "Session Service";
+ Node::json["SessionTimeout"] =
+ crow::persistent_data::SessionStore::getInstance()
+ .getTimeoutInSeconds();
+ Node::json["ServiceEnabled"] = true;
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ }
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- res.jsonValue = Node::json;
- res.end();
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ res.jsonValue = Node::json;
+ res.end();
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp
index 72d7948..258eed3 100644
--- a/redfish-core/lib/roles.hpp
+++ b/redfish-core/lib/roles.hpp
@@ -17,74 +17,82 @@
#include "node.hpp"
-namespace redfish {
+namespace redfish
+{
-class Roles : public Node {
- public:
- Roles(CrowApp& app)
- : Node(app, "/redfish/v1/AccountService/Roles/Administrator/") {
- Node::json["@odata.id"] = "/redfish/v1/AccountService/Roles/Administrator";
- Node::json["@odata.type"] = "#Role.v1_0_2.Role";
- Node::json["@odata.context"] = "/redfish/v1/$metadata#Role.Role";
- Node::json["Id"] = "Administrator";
- Node::json["Name"] = "User Role";
- Node::json["Description"] = "Administrator User Role";
- Node::json["IsPredefined"] = true;
- Node::json["AssignedPrivileges"] = {"Login", "ConfigureManager",
- "ConfigureUsers", "ConfigureSelf",
- "ConfigureComponents"};
- Node::json["OemPrivileges"] = nlohmann::json::array();
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+class Roles : public Node
+{
+ public:
+ Roles(CrowApp& app) :
+ Node(app, "/redfish/v1/AccountService/Roles/Administrator/")
+ {
+ Node::json["@odata.id"] =
+ "/redfish/v1/AccountService/Roles/Administrator";
+ Node::json["@odata.type"] = "#Role.v1_0_2.Role";
+ Node::json["@odata.context"] = "/redfish/v1/$metadata#Role.Role";
+ Node::json["Id"] = "Administrator";
+ Node::json["Name"] = "User Role";
+ Node::json["Description"] = "Administrator User Role";
+ Node::json["IsPredefined"] = true;
+ Node::json["AssignedPrivileges"] = {"Login", "ConfigureManager",
+ "ConfigureUsers", "ConfigureSelf",
+ "ConfigureComponents"};
+ Node::json["OemPrivileges"] = nlohmann::json::array();
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ }
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- res.jsonValue = Node::json;
- res.end();
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ res.jsonValue = Node::json;
+ res.end();
+ }
};
-class RoleCollection : public Node {
- public:
- RoleCollection(CrowApp& app)
- : Node(app, "/redfish/v1/AccountService/Roles/") {
- Node::json["@odata.id"] = "/redfish/v1/AccountService/Roles";
- Node::json["@odata.type"] = "#RoleCollection.RoleCollection";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#RoleCollection.RoleCollection";
- Node::json["Name"] = "Roles Collection";
- Node::json["Description"] = "BMC User Roles";
- Node::json["Members@odata.count"] = 1;
- Node::json["Members"] = {
- {{"@odata.id", "/redfish/v1/AccountService/Roles/Administrator"}}};
+class RoleCollection : public Node
+{
+ public:
+ RoleCollection(CrowApp& app) :
+ Node(app, "/redfish/v1/AccountService/Roles/")
+ {
+ Node::json["@odata.id"] = "/redfish/v1/AccountService/Roles";
+ Node::json["@odata.type"] = "#RoleCollection.RoleCollection";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#RoleCollection.RoleCollection";
+ Node::json["Name"] = "Roles Collection";
+ Node::json["Description"] = "BMC User Roles";
+ Node::json["Members@odata.count"] = 1;
+ Node::json["Members"] = {
+ {{"@odata.id", "/redfish/v1/AccountService/Roles/Administrator"}}};
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+ }
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- res.jsonValue = Node::json;
- // This is a short term solution to work around a bug. GetSubroutes
- // accidentally recognizes the Roles/Administrator route as a subroute
- // (because it's hardcoded to a single entity). Remove this line when that
- // is resolved
- res.jsonValue.erase("Administrator");
- res.end();
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ res.jsonValue = Node::json;
+ // This is a short term solution to work around a bug. GetSubroutes
+ // accidentally recognizes the Roles/Administrator route as a subroute
+ // (because it's hardcoded to a single entity). Remove this line when
+ // that is resolved
+ res.jsonValue.erase("Administrator");
+ res.end();
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 7f9fa68..c390cd7 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -16,13 +16,15 @@
#pragma once
#include <math.h>
-#include <dbus_singleton.hpp>
+
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/range/algorithm/replace_copy_if.hpp>
+#include <dbus_singleton.hpp>
-namespace redfish {
+namespace redfish
+{
constexpr const char* dbusSensorPrefix = "/xyz/openbmc_project/sensors/";
@@ -41,32 +43,38 @@
* SensorsAsyncResp
* Gathers data needed for response processing after async calls are done
*/
-class SensorsAsyncResp {
- public:
- SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
- const std::initializer_list<const char*> types)
- : res(response), chassisId(chassisId), types(types) {
- res.jsonValue["@odata.id"] =
- "/redfish/v1/Chassis/" + chassisId + "/Thermal";
- }
-
- ~SensorsAsyncResp() {
- if (res.result() == boost::beast::http::status::internal_server_error) {
- // Reset the json object to clear out any data that made it in before the
- // error happened
- // todo(ed) handle error condition with proper code
- res.jsonValue = nlohmann::json::object();
+class SensorsAsyncResp
+{
+ public:
+ SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
+ const std::initializer_list<const char*> types) :
+ res(response),
+ chassisId(chassisId), types(types)
+ {
+ res.jsonValue["@odata.id"] =
+ "/redfish/v1/Chassis/" + chassisId + "/Thermal";
}
- res.end();
- }
- void setErrorStatus() {
- res.result(boost::beast::http::status::internal_server_error);
- }
+ ~SensorsAsyncResp()
+ {
+ if (res.result() == boost::beast::http::status::internal_server_error)
+ {
+ // Reset the json object to clear out any data that made it in
+ // before the error happened todo(ed) handle error condition with
+ // proper code
+ res.jsonValue = nlohmann::json::object();
+ }
+ res.end();
+ }
- crow::Response& res;
- std::string chassisId{};
- const std::vector<const char*> types;
+ void setErrorStatus()
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ }
+
+ crow::Response& res;
+ std::string chassisId{};
+ const std::vector<const char*> types;
};
/**
@@ -78,70 +86,84 @@
template <typename Callback>
void getConnections(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
const boost::container::flat_set<std::string>& sensorNames,
- Callback&& callback) {
- BMCWEB_LOG_DEBUG << "getConnections enter";
- const std::string path = "/xyz/openbmc_project/sensors";
- const std::array<std::string, 1> interfaces = {
- "xyz.openbmc_project.Sensor.Value"};
+ Callback&& callback)
+{
+ BMCWEB_LOG_DEBUG << "getConnections enter";
+ const std::string path = "/xyz/openbmc_project/sensors";
+ const std::array<std::string, 1> interfaces = {
+ "xyz.openbmc_project.Sensor.Value"};
- // Response handler for parsing objects subtree
- auto respHandler =
- [ callback{std::move(callback)}, SensorsAsyncResp, sensorNames ](
- const boost::system::error_code ec, const GetSubTreeType& subtree) {
- BMCWEB_LOG_DEBUG << "getConnections resp_handler enter";
- if (ec) {
- SensorsAsyncResp->setErrorStatus();
- BMCWEB_LOG_ERROR << "getConnections resp_handler: Dbus error " << ec;
- return;
- }
-
- BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " subtrees";
-
- // Make unique list of connections only for requested sensor types and
- // found in the chassis
- boost::container::flat_set<std::string> connections;
- // Intrinsic to avoid malloc. Most systems will have < 8 sensor producers
- connections.reserve(8);
-
- BMCWEB_LOG_DEBUG << "sensorNames list count: " << sensorNames.size();
- for (const std::string& tsensor : sensorNames) {
- BMCWEB_LOG_DEBUG << "Sensor to find: " << tsensor;
- }
-
- for (const std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>&
- object : subtree) {
- for (const char* type : SensorsAsyncResp->types) {
- if (boost::starts_with(object.first, type)) {
- auto lastPos = object.first.rfind('/');
- if (lastPos != std::string::npos) {
- std::string sensorName = object.first.substr(lastPos + 1);
-
- if (sensorNames.find(sensorName) != sensorNames.end()) {
- // For each Connection name
- for (const std::pair<std::string, std::vector<std::string>>&
- objData : object.second) {
- BMCWEB_LOG_DEBUG << "Adding connection: " << objData.first;
- connections.insert(objData.first);
- }
- }
- }
- break;
+ // Response handler for parsing objects subtree
+ auto respHandler = [callback{std::move(callback)}, SensorsAsyncResp,
+ sensorNames](const boost::system::error_code ec,
+ const GetSubTreeType& subtree) {
+ BMCWEB_LOG_DEBUG << "getConnections resp_handler enter";
+ if (ec)
+ {
+ SensorsAsyncResp->setErrorStatus();
+ BMCWEB_LOG_ERROR << "getConnections resp_handler: Dbus error "
+ << ec;
+ return;
}
- }
- }
- BMCWEB_LOG_DEBUG << "Found " << connections.size() << " connections";
- callback(std::move(connections));
- BMCWEB_LOG_DEBUG << "getConnections resp_handler exit";
- };
- // Make call to ObjectMapper to find all sensors objects
- crow::connections::systemBus->async_method_call(
- std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper", "xyz.openbmc_project.ObjectMapper",
- "GetSubTree", path, 2, interfaces);
- BMCWEB_LOG_DEBUG << "getConnections exit";
+ BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " subtrees";
+
+ // Make unique list of connections only for requested sensor types and
+ // found in the chassis
+ boost::container::flat_set<std::string> connections;
+ // Intrinsic to avoid malloc. Most systems will have < 8 sensor
+ // producers
+ connections.reserve(8);
+
+ BMCWEB_LOG_DEBUG << "sensorNames list count: " << sensorNames.size();
+ for (const std::string& tsensor : sensorNames)
+ {
+ BMCWEB_LOG_DEBUG << "Sensor to find: " << tsensor;
+ }
+
+ for (const std::pair<
+ std::string,
+ std::vector<std::pair<std::string, std::vector<std::string>>>>&
+ object : subtree)
+ {
+ for (const char* type : SensorsAsyncResp->types)
+ {
+ if (boost::starts_with(object.first, type))
+ {
+ auto lastPos = object.first.rfind('/');
+ if (lastPos != std::string::npos)
+ {
+ std::string sensorName =
+ object.first.substr(lastPos + 1);
+
+ if (sensorNames.find(sensorName) != sensorNames.end())
+ {
+ // For each Connection name
+ for (const std::pair<std::string,
+ std::vector<std::string>>&
+ objData : object.second)
+ {
+ BMCWEB_LOG_DEBUG << "Adding connection: "
+ << objData.first;
+ connections.insert(objData.first);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ BMCWEB_LOG_DEBUG << "Found " << connections.size() << " connections";
+ callback(std::move(connections));
+ BMCWEB_LOG_DEBUG << "getConnections resp_handler exit";
+ };
+
+ // Make call to ObjectMapper to find all sensors objects
+ crow::connections::systemBus->async_method_call(
+ std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, 2, interfaces);
+ BMCWEB_LOG_DEBUG << "getConnections exit";
}
/**
@@ -151,64 +173,74 @@
*/
template <typename Callback>
void getChassis(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
- Callback&& callback) {
- BMCWEB_LOG_DEBUG << "getChassis enter";
- // Process response from EntityManager and extract chassis data
- auto respHandler = [ callback{std::move(callback)}, SensorsAsyncResp ](
- const boost::system::error_code ec, ManagedObjectsVectorType& resp) {
- BMCWEB_LOG_DEBUG << "getChassis respHandler enter";
- if (ec) {
- BMCWEB_LOG_ERROR << "getChassis respHandler DBUS error: " << ec;
- SensorsAsyncResp->setErrorStatus();
- return;
- }
- boost::container::flat_set<std::string> sensorNames;
+ Callback&& callback)
+{
+ BMCWEB_LOG_DEBUG << "getChassis enter";
+ // Process response from EntityManager and extract chassis data
+ auto respHandler = [callback{std::move(callback)},
+ SensorsAsyncResp](const boost::system::error_code ec,
+ ManagedObjectsVectorType& resp) {
+ BMCWEB_LOG_DEBUG << "getChassis respHandler enter";
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "getChassis respHandler DBUS error: " << ec;
+ SensorsAsyncResp->setErrorStatus();
+ return;
+ }
+ boost::container::flat_set<std::string> sensorNames;
- // SensorsAsyncResp->chassisId
- bool foundChassis = false;
- std::vector<std::string> split;
- // Reserve space for
- // /xyz/openbmc_project/inventory/<name>/<subname> + 3 subnames
- split.reserve(8);
+ // SensorsAsyncResp->chassisId
+ bool foundChassis = false;
+ std::vector<std::string> split;
+ // Reserve space for
+ // /xyz/openbmc_project/inventory/<name>/<subname> + 3 subnames
+ split.reserve(8);
- for (const auto& objDictEntry : resp) {
- const std::string& objectPath =
- static_cast<const std::string&>(objDictEntry.first);
- boost::algorithm::split(split, objectPath, boost::is_any_of("/"));
- if (split.size() < 2) {
- BMCWEB_LOG_ERROR << "Got path that isn't long enough " << objectPath;
- split.clear();
- continue;
- }
- const std::string& sensorName = split.end()[-1];
- const std::string& chassisName = split.end()[-2];
+ for (const auto& objDictEntry : resp)
+ {
+ const std::string& objectPath =
+ static_cast<const std::string&>(objDictEntry.first);
+ boost::algorithm::split(split, objectPath, boost::is_any_of("/"));
+ if (split.size() < 2)
+ {
+ BMCWEB_LOG_ERROR << "Got path that isn't long enough "
+ << objectPath;
+ split.clear();
+ continue;
+ }
+ const std::string& sensorName = split.end()[-1];
+ const std::string& chassisName = split.end()[-2];
- if (chassisName != SensorsAsyncResp->chassisId) {
- split.clear();
- continue;
- }
- BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
- foundChassis = true;
- sensorNames.emplace(sensorName);
- split.clear();
+ if (chassisName != SensorsAsyncResp->chassisId)
+ {
+ split.clear();
+ continue;
+ }
+ BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
+ foundChassis = true;
+ sensorNames.emplace(sensorName);
+ split.clear();
+ };
+ BMCWEB_LOG_DEBUG << "Found " << sensorNames.size() << " Sensor names";
+
+ if (!foundChassis)
+ {
+ BMCWEB_LOG_INFO << "Unable to find chassis named "
+ << SensorsAsyncResp->chassisId;
+ SensorsAsyncResp->res.result(boost::beast::http::status::not_found);
+ }
+ else
+ {
+ callback(sensorNames);
+ }
+ BMCWEB_LOG_DEBUG << "getChassis respHandler exit";
};
- BMCWEB_LOG_DEBUG << "Found " << sensorNames.size() << " Sensor names";
- if (!foundChassis) {
- BMCWEB_LOG_INFO << "Unable to find chassis named "
- << SensorsAsyncResp->chassisId;
- SensorsAsyncResp->res.result(boost::beast::http::status::not_found);
- } else {
- callback(sensorNames);
- }
- BMCWEB_LOG_DEBUG << "getChassis respHandler exit";
- };
-
- // Make call to EntityManager to find all chassis objects
- crow::connections::systemBus->async_method_call(
- respHandler, "xyz.openbmc_project.EntityManager", "/",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- BMCWEB_LOG_DEBUG << "getChassis exit";
+ // Make call to EntityManager to find all chassis objects
+ crow::connections::systemBus->async_method_call(
+ respHandler, "xyz.openbmc_project.EntityManager", "/",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ BMCWEB_LOG_DEBUG << "getChassis exit";
}
/**
@@ -225,116 +257,146 @@
const boost::container::flat_map<
std::string, boost::container::flat_map<std::string, SensorVariant>>&
interfacesDict,
- nlohmann::json& sensor_json) {
- // We need a value interface before we can do anything with it
- auto valueIt = interfacesDict.find("xyz.openbmc_project.Sensor.Value");
- if (valueIt == interfacesDict.end()) {
- BMCWEB_LOG_ERROR << "Sensor doesn't have a value interface";
- return;
- }
-
- // Assume values exist as is (10^0 == 1) if no scale exists
- int64_t scaleMultiplier = 0;
-
- auto scaleIt = valueIt->second.find("Scale");
- // If a scale exists, pull value as int64, and use the scaling.
- if (scaleIt != valueIt->second.end()) {
- const int64_t* int64Value = mapbox::getPtr<const int64_t>(scaleIt->second);
- if (int64Value != nullptr) {
- scaleMultiplier = *int64Value;
+ nlohmann::json& sensor_json)
+{
+ // We need a value interface before we can do anything with it
+ auto valueIt = interfacesDict.find("xyz.openbmc_project.Sensor.Value");
+ if (valueIt == interfacesDict.end())
+ {
+ BMCWEB_LOG_ERROR << "Sensor doesn't have a value interface";
+ return;
}
- }
- sensor_json["MemberId"] = sensorName;
- sensor_json["Name"] = sensorName;
- sensor_json["Status"]["State"] = "Enabled";
- sensor_json["Status"]["Health"] = "OK";
+ // Assume values exist as is (10^0 == 1) if no scale exists
+ int64_t scaleMultiplier = 0;
- // Parameter to set to override the type we get from dbus, and force it to
- // int, regardless of what is available. This is used for schemas like fan,
- // that require integers, not floats.
- bool forceToInt = false;
-
- const char* unit = "Reading";
- if (sensorType == "temperature") {
- unit = "ReadingCelsius";
- sensor_json["@odata.type"] = "#Thermal.v1_3_0.Temperature";
- // TODO(ed) Documentation says that path should be type fan_tach,
- // implementation seems to implement fan
- } else if (sensorType == "fan" || sensorType == "fan_tach") {
- unit = "Reading";
- sensor_json["ReadingUnits"] = "RPM";
- sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
- forceToInt = true;
- } else if (sensorType == "voltage") {
- unit = "ReadingVolts";
- sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
- } else {
- BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
- return;
- }
- // Map of dbus interface name, dbus property name and redfish property_name
- std::vector<std::tuple<const char*, const char*, const char*>> properties;
- properties.reserve(7);
-
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
- "WarningHigh", "UpperThresholdNonCritical");
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
- "WarningLow", "LowerThresholdNonCritical");
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
- "CriticalHigh", "UpperThresholdCritical");
- properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
- "CriticalLow", "LowerThresholdCritical");
-
- if (sensorType == "temperature") {
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
- "MinReadingRangeTemp");
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
- "MaxReadingRangeTemp");
- } else {
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
- "MinReadingRange");
- properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
- "MaxReadingRange");
- }
-
- for (const std::tuple<const char*, const char*, const char*>& p :
- properties) {
- auto interfaceProperties = interfacesDict.find(std::get<0>(p));
- if (interfaceProperties != interfacesDict.end()) {
- auto valueIt = interfaceProperties->second.find(std::get<1>(p));
- if (valueIt != interfaceProperties->second.end()) {
- const SensorVariant& valueVariant = valueIt->second;
- nlohmann::json& valueIt = sensor_json[std::get<2>(p)];
-
- // Attempt to pull the int64 directly
- const int64_t* int64Value = mapbox::getPtr<const int64_t>(valueVariant);
-
- if (int64Value != nullptr) {
- if (forceToInt || scaleMultiplier >= 0) {
- valueIt = *int64Value * std::pow(10, scaleMultiplier);
- } else {
- valueIt = *int64Value *
- std::pow(10, static_cast<double>(scaleMultiplier));
- }
+ auto scaleIt = valueIt->second.find("Scale");
+ // If a scale exists, pull value as int64, and use the scaling.
+ if (scaleIt != valueIt->second.end())
+ {
+ const int64_t* int64Value =
+ mapbox::getPtr<const int64_t>(scaleIt->second);
+ if (int64Value != nullptr)
+ {
+ scaleMultiplier = *int64Value;
}
- // Attempt to pull the float directly
- const double* doubleValue = mapbox::getPtr<const double>(valueVariant);
-
- if (doubleValue != nullptr) {
- if (!forceToInt) {
- valueIt = *doubleValue *
- std::pow(10, static_cast<double>(scaleMultiplier));
- } else {
- valueIt = static_cast<int64_t>(*doubleValue *
- std::pow(10, scaleMultiplier));
- }
- }
- }
}
- }
- BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
+
+ sensor_json["MemberId"] = sensorName;
+ sensor_json["Name"] = sensorName;
+ sensor_json["Status"]["State"] = "Enabled";
+ sensor_json["Status"]["Health"] = "OK";
+
+ // Parameter to set to override the type we get from dbus, and force it to
+ // int, regardless of what is available. This is used for schemas like fan,
+ // that require integers, not floats.
+ bool forceToInt = false;
+
+ const char* unit = "Reading";
+ if (sensorType == "temperature")
+ {
+ unit = "ReadingCelsius";
+ sensor_json["@odata.type"] = "#Thermal.v1_3_0.Temperature";
+ // TODO(ed) Documentation says that path should be type fan_tach,
+ // implementation seems to implement fan
+ }
+ else if (sensorType == "fan" || sensorType == "fan_tach")
+ {
+ unit = "Reading";
+ sensor_json["ReadingUnits"] = "RPM";
+ sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
+ forceToInt = true;
+ }
+ else if (sensorType == "voltage")
+ {
+ unit = "ReadingVolts";
+ sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
+ return;
+ }
+ // Map of dbus interface name, dbus property name and redfish property_name
+ std::vector<std::tuple<const char*, const char*, const char*>> properties;
+ properties.reserve(7);
+
+ properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);
+ properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
+ "WarningHigh", "UpperThresholdNonCritical");
+ properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
+ "WarningLow", "LowerThresholdNonCritical");
+ properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
+ "CriticalHigh", "UpperThresholdCritical");
+ properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
+ "CriticalLow", "LowerThresholdCritical");
+
+ if (sensorType == "temperature")
+ {
+ properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
+ "MinReadingRangeTemp");
+ properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
+ "MaxReadingRangeTemp");
+ }
+ else
+ {
+ properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
+ "MinReadingRange");
+ properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
+ "MaxReadingRange");
+ }
+
+ for (const std::tuple<const char*, const char*, const char*>& p :
+ properties)
+ {
+ auto interfaceProperties = interfacesDict.find(std::get<0>(p));
+ if (interfaceProperties != interfacesDict.end())
+ {
+ auto valueIt = interfaceProperties->second.find(std::get<1>(p));
+ if (valueIt != interfaceProperties->second.end())
+ {
+ const SensorVariant& valueVariant = valueIt->second;
+ nlohmann::json& valueIt = sensor_json[std::get<2>(p)];
+
+ // Attempt to pull the int64 directly
+ const int64_t* int64Value =
+ mapbox::getPtr<const int64_t>(valueVariant);
+
+ if (int64Value != nullptr)
+ {
+ if (forceToInt || scaleMultiplier >= 0)
+ {
+ valueIt = *int64Value * std::pow(10, scaleMultiplier);
+ }
+ else
+ {
+ valueIt =
+ *int64Value *
+ std::pow(10, static_cast<double>(scaleMultiplier));
+ }
+ }
+ // Attempt to pull the float directly
+ const double* doubleValue =
+ mapbox::getPtr<const double>(valueVariant);
+
+ if (doubleValue != nullptr)
+ {
+ if (!forceToInt)
+ {
+ valueIt =
+ *doubleValue *
+ std::pow(10, static_cast<double>(scaleMultiplier));
+ }
+ else
+ {
+ valueIt = static_cast<int64_t>(
+ *doubleValue * std::pow(10, scaleMultiplier));
+ }
+ }
+ }
+ }
+ }
+ BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
}
/**
@@ -342,106 +404,140 @@
* chassis.
* @param SensorsAsyncResp Pointer to object holding response data
*/
-void getChassisData(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp) {
- BMCWEB_LOG_DEBUG << "getChassisData enter";
- auto getChassisCb = [&, SensorsAsyncResp](
- boost::container::flat_set<std::string>&
- sensorNames) {
- BMCWEB_LOG_DEBUG << "getChassisCb enter";
- auto getConnectionCb =
- [&, SensorsAsyncResp, sensorNames](
- const boost::container::flat_set<std::string>& connections) {
- BMCWEB_LOG_DEBUG << "getConnectionCb enter";
- // Get managed objects from all services exposing sensors
- for (const std::string& connection : connections) {
- // Response handler to process managed objects
- auto getManagedObjectsCb = [&, SensorsAsyncResp, sensorNames](
- const boost::system::error_code ec,
- ManagedObjectsVectorType& resp) {
- BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter";
- if (ec) {
- BMCWEB_LOG_ERROR << "getManagedObjectsCb DBUS error: " << ec;
- SensorsAsyncResp->setErrorStatus();
- return;
- }
- // Go through all objects and update response with
- // sensor data
- for (const auto& objDictEntry : resp) {
- const std::string& objPath =
- static_cast<const std::string&>(objDictEntry.first);
- BMCWEB_LOG_DEBUG << "getManagedObjectsCb parsing object "
- << objPath;
+void getChassisData(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp)
+{
+ BMCWEB_LOG_DEBUG << "getChassisData enter";
+ auto getChassisCb = [&, SensorsAsyncResp](
+ boost::container::flat_set<std::string>&
+ sensorNames) {
+ BMCWEB_LOG_DEBUG << "getChassisCb enter";
+ auto getConnectionCb =
+ [&, SensorsAsyncResp, sensorNames](
+ const boost::container::flat_set<std::string>& connections) {
+ BMCWEB_LOG_DEBUG << "getConnectionCb enter";
+ // Get managed objects from all services exposing sensors
+ for (const std::string& connection : connections)
+ {
+ // Response handler to process managed objects
+ auto getManagedObjectsCb =
+ [&, SensorsAsyncResp,
+ sensorNames](const boost::system::error_code ec,
+ ManagedObjectsVectorType& resp) {
+ BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter";
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "getManagedObjectsCb DBUS error: " << ec;
+ SensorsAsyncResp->setErrorStatus();
+ return;
+ }
+ // Go through all objects and update response with
+ // sensor data
+ for (const auto& objDictEntry : resp)
+ {
+ const std::string& objPath =
+ static_cast<const std::string&>(
+ objDictEntry.first);
+ BMCWEB_LOG_DEBUG
+ << "getManagedObjectsCb parsing object "
+ << objPath;
- std::vector<std::string> split;
- // Reserve space for
- // /xyz/openbmc_project/sensors/<name>/<subname>
- split.reserve(6);
- boost::algorithm::split(split, objPath, boost::is_any_of("/"));
- if (split.size() < 6) {
- BMCWEB_LOG_ERROR << "Got path that isn't long enough "
- << objPath;
- continue;
- }
- // These indexes aren't intuitive, as boost::split puts an empty
- // string at the beggining
- const std::string& sensorType = split[4];
- const std::string& sensorName = split[5];
- BMCWEB_LOG_DEBUG << "sensorName " << sensorName
- << " sensorType " << sensorType;
- if (sensorNames.find(sensorName) == sensorNames.end()) {
- BMCWEB_LOG_ERROR << sensorName << " not in sensor list ";
- continue;
- }
+ std::vector<std::string> split;
+ // Reserve space for
+ // /xyz/openbmc_project/sensors/<name>/<subname>
+ split.reserve(6);
+ boost::algorithm::split(split, objPath,
+ boost::is_any_of("/"));
+ if (split.size() < 6)
+ {
+ BMCWEB_LOG_ERROR
+ << "Got path that isn't long enough "
+ << objPath;
+ continue;
+ }
+ // These indexes aren't intuitive, as
+ // boost::split puts an empty string at the
+ // beggining
+ const std::string& sensorType = split[4];
+ const std::string& sensorName = split[5];
+ BMCWEB_LOG_DEBUG << "sensorName " << sensorName
+ << " sensorType "
+ << sensorType;
+ if (sensorNames.find(sensorName) ==
+ sensorNames.end())
+ {
+ BMCWEB_LOG_ERROR << sensorName
+ << " not in sensor list ";
+ continue;
+ }
- const char* fieldName = nullptr;
- if (sensorType == "temperature") {
- fieldName = "Temperatures";
- } else if (sensorType == "fan" || sensorType == "fan_tach") {
- fieldName = "Fans";
- } else if (sensorType == "voltage") {
- fieldName = "Voltages";
- } else if (sensorType == "current") {
- fieldName = "PowerSupply";
- } else if (sensorType == "power") {
- fieldName = "PowerSupply";
- } else {
- BMCWEB_LOG_ERROR << "Unsure how to handle sensorType "
- << sensorType;
- continue;
- }
+ const char* fieldName = nullptr;
+ if (sensorType == "temperature")
+ {
+ fieldName = "Temperatures";
+ }
+ else if (sensorType == "fan" ||
+ sensorType == "fan_tach")
+ {
+ fieldName = "Fans";
+ }
+ else if (sensorType == "voltage")
+ {
+ fieldName = "Voltages";
+ }
+ else if (sensorType == "current")
+ {
+ fieldName = "PowerSupply";
+ }
+ else if (sensorType == "power")
+ {
+ fieldName = "PowerSupply";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR
+ << "Unsure how to handle sensorType "
+ << sensorType;
+ continue;
+ }
- nlohmann::json& tempArray =
- SensorsAsyncResp->res.jsonValue[fieldName];
+ nlohmann::json& tempArray =
+ SensorsAsyncResp->res.jsonValue[fieldName];
- // Create the array if it doesn't yet exist
- if (tempArray.is_array() == false) {
- tempArray = nlohmann::json::array();
- }
+ // Create the array if it doesn't yet exist
+ if (tempArray.is_array() == false)
+ {
+ tempArray = nlohmann::json::array();
+ }
- tempArray.push_back(
- {{"@odata.id", "/redfish/v1/Chassis/" +
- SensorsAsyncResp->chassisId +
- "/Thermal#/" + sensorName}});
- nlohmann::json& sensorJson = tempArray.back();
- objectInterfacesToJson(sensorName, sensorType,
- objDictEntry.second, sensorJson);
- }
- BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit";
+ tempArray.push_back(
+ {{"@odata.id",
+ "/redfish/v1/Chassis/" +
+ SensorsAsyncResp->chassisId +
+ "/Thermal#/" + sensorName}});
+ nlohmann::json& sensorJson = tempArray.back();
+ objectInterfacesToJson(sensorName, sensorType,
+ objDictEntry.second,
+ sensorJson);
+ }
+ BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit";
+ };
+ crow::connections::systemBus->async_method_call(
+ getManagedObjectsCb, connection, "/",
+ "org.freedesktop.DBus.ObjectManager",
+ "GetManagedObjects");
+ };
+ BMCWEB_LOG_DEBUG << "getConnectionCb exit";
};
- crow::connections::systemBus->async_method_call(
- getManagedObjectsCb, connection, "/",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- };
- BMCWEB_LOG_DEBUG << "getConnectionCb exit";
- };
- // get connections and then pass it to get sensors
- getConnections(SensorsAsyncResp, sensorNames, std::move(getConnectionCb));
- BMCWEB_LOG_DEBUG << "getChassisCb exit";
- };
+ // get connections and then pass it to get sensors
+ getConnections(SensorsAsyncResp, sensorNames,
+ std::move(getConnectionCb));
+ BMCWEB_LOG_DEBUG << "getChassisCb exit";
+ };
- // get chassis information related to sensors
- getChassis(SensorsAsyncResp, std::move(getChassisCb));
- BMCWEB_LOG_DEBUG << "getChassisData exit";
+ // get chassis information related to sensors
+ getChassis(SensorsAsyncResp, std::move(getChassisCb));
+ BMCWEB_LOG_DEBUG << "getChassisData exit";
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 6fa9632..d2c5163 100644
--- a/redfish-core/lib/service_root.hpp
+++ b/redfish-core/lib/service_root.hpp
@@ -15,62 +15,69 @@
*/
#pragma once
-#include <systemd/sd-id128.h>
#include "node.hpp"
-namespace redfish {
+#include <systemd/sd-id128.h>
-class ServiceRoot : public Node {
- public:
- ServiceRoot(CrowApp& app) : Node(app, "/redfish/v1/") {
- Node::json["@odata.type"] = "#ServiceRoot.v1_1_1.ServiceRoot";
- Node::json["@odata.id"] = "/redfish/v1/";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#ServiceRoot.ServiceRoot";
- Node::json["Id"] = "RootService";
- Node::json["Name"] = "Root Service";
- Node::json["RedfishVersion"] = "1.1.0";
- Node::json["Links"]["Sessions"] = {
- {"@odata.id", "/redfish/v1/SessionService/Sessions"}};
+namespace redfish
+{
- Node::json["UUID"] = getUuid();
+class ServiceRoot : public Node
+{
+ public:
+ ServiceRoot(CrowApp& app) : Node(app, "/redfish/v1/")
+ {
+ Node::json["@odata.type"] = "#ServiceRoot.v1_1_1.ServiceRoot";
+ Node::json["@odata.id"] = "/redfish/v1/";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#ServiceRoot.ServiceRoot";
+ Node::json["Id"] = "RootService";
+ Node::json["Name"] = "Root Service";
+ Node::json["RedfishVersion"] = "1.1.0";
+ Node::json["Links"]["Sessions"] = {
+ {"@odata.id", "/redfish/v1/SessionService/Sessions"}};
- entityPrivileges = {
- {boost::beast::http::verb::get, {}},
- {boost::beast::http::verb::head, {}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ Node::json["UUID"] = getUuid();
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- res.jsonValue = Node::json;
- res.end();
- }
-
- const std::string getUuid() {
- // If we are using a version of systemd that can get the app specific uuid,
- // use that
-#ifdef sd_id128_get_machine_app_specific
- std::array<char, SD_ID128_STRING_MAX> string;
- sd_id128_t id = SD_ID128_NULL;
-
- // This ID needs to match the one in ipmid
- int r = sd_id128_get_machine_app_specific(
- SD_ID128_MAKE(e0, e1, 73, 76, 64, 61, 47, da, a5, 0c, d0, cc, 64, 12,
- 45, 78),
- &id);
- if (r < 0) {
- return "00000000-0000-0000-0000-000000000000";
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {}},
+ {boost::beast::http::verb::head, {}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- return string.data();
+
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ res.jsonValue = Node::json;
+ res.end();
+ }
+
+ const std::string getUuid()
+ {
+ // If we are using a version of systemd that can get the app specific
+ // uuid, use that
+#ifdef sd_id128_get_machine_app_specific
+ std::array<char, SD_ID128_STRING_MAX> string;
+ sd_id128_t id = SD_ID128_NULL;
+
+ // This ID needs to match the one in ipmid
+ int r = sd_id128_get_machine_app_specific(
+ SD_ID128_MAKE(e0, e1, 73, 76, 64, 61, 47, da, a5, 0c, d0, cc, 64,
+ 12, 45, 78),
+ &id);
+ if (r < 0)
+ {
+ return "00000000-0000-0000-0000-000000000000";
+ }
+ return string.data();
#else
- return "00000000-0000-0000-0000-000000000000";
+ return "00000000-0000-0000-0000-000000000000";
#endif
- }
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index b7f91b9..cd49883 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -15,36 +15,44 @@
*/
#pragma once
+#include "boost/container/flat_map.hpp"
+#include "node.hpp"
+
#include <error_messages.hpp>
#include <utils/json_utils.hpp>
-#include "node.hpp"
-#include "boost/container/flat_map.hpp"
-namespace redfish {
+namespace redfish
+{
/**
* SystemAsyncResp
* Gathers data needed for response processing after async calls are done
*/
-class SystemAsyncResp {
- public:
- SystemAsyncResp(crow::Response &response) : res(response) {}
-
- ~SystemAsyncResp() {
- if (res.result() != (boost::beast::http::status::ok)) {
- // Reset the json object to clear out any data that made it in before the
- // error happened
- // todo(ed) handle error condition with proper code
- res.jsonValue = messages::internalError();
+class SystemAsyncResp
+{
+ public:
+ SystemAsyncResp(crow::Response &response) : res(response)
+ {
}
- res.end();
- }
- void setErrorStatus() {
- res.result(boost::beast::http::status::internal_server_error);
- }
+ ~SystemAsyncResp()
+ {
+ if (res.result() != (boost::beast::http::status::ok))
+ {
+ // Reset the json object to clear out any data that made it in
+ // before the error happened todo(ed) handle error condition with
+ // proper code
+ res.jsonValue = messages::internalError();
+ }
+ res.end();
+ }
- crow::Response &res;
+ void setErrorStatus()
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ }
+
+ crow::Response &res;
};
/**
@@ -59,628 +67,853 @@
* This perhaps shall be different file, which has to be chosen on compile time
* depending on OEM needs
*/
-class OnDemandSystemsProvider {
- public:
- template <typename CallbackFunc>
- void getBaseboardList(CallbackFunc &&callback) {
- BMCWEB_LOG_DEBUG << "Get list of available boards.";
- crow::connections::systemBus->async_method_call(
- [callback{std::move(callback)}](const boost::system::error_code ec,
- const std::vector<std::string> &resp) {
- // Callback requires vector<string> to retrieve all available board
- // list.
- std::vector<std::string> boardList;
- if (ec) {
- // Something wrong on DBus, the error_code is not important at this
- // moment, just return success=false, and empty output. Since size
- // of vector may vary depending on information from Entity Manager,
- // and empty output could not be treated same way as error.
- callback(false, boardList);
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
- // Iterate over all retrieved ObjectPaths.
- for (const std::string &objpath : resp) {
- std::size_t lastPos = objpath.rfind("/");
- if (lastPos != std::string::npos) {
- boardList.emplace_back(objpath.substr(lastPos + 1));
- }
- }
- // Finally make a callback with useful data
- callback(true, boardList);
- },
- "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.Board"});
- };
-
- /**
- * @brief Retrieves computer system properties over dbus
- *
- * @param[in] aResp Shared pointer for completing asynchronous calls
- * @param[in] name Computer system name from request
- *
- * @return None.
- */
- void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp,
- const std::string &name) {
- const std::array<const char *, 5> interfaces = {
- "xyz.openbmc_project.Inventory.Decorator.Asset",
- "xyz.openbmc_project.Inventory.Item.Cpu",
- "xyz.openbmc_project.Inventory.Item.Dimm",
- "xyz.openbmc_project.Inventory.Item.System",
- "xyz.openbmc_project.Common.UUID",
+class OnDemandSystemsProvider
+{
+ public:
+ template <typename CallbackFunc>
+ void getBaseboardList(CallbackFunc &&callback)
+ {
+ BMCWEB_LOG_DEBUG << "Get list of available boards.";
+ crow::connections::systemBus->async_method_call(
+ [callback{std::move(callback)}](
+ const boost::system::error_code ec,
+ const std::vector<std::string> &resp) {
+ // Callback requires vector<string> to retrieve all available
+ // board list.
+ std::vector<std::string> boardList;
+ if (ec)
+ {
+ // Something wrong on DBus, the error_code is not important
+ // at this moment, just return success=false, and empty
+ // output. Since size of vector may vary depending on
+ // information from Entity Manager, and empty output could
+ // not be treated same way as error.
+ callback(false, boardList);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Got " << resp.size() << " boards.";
+ // Iterate over all retrieved ObjectPaths.
+ for (const std::string &objpath : resp)
+ {
+ std::size_t lastPos = objpath.rfind("/");
+ if (lastPos != std::string::npos)
+ {
+ boardList.emplace_back(objpath.substr(lastPos + 1));
+ }
+ }
+ // Finally make a callback with useful data
+ callback(true, boardList);
+ },
+ "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.Board"});
};
- BMCWEB_LOG_DEBUG << "Get available system components.";
- crow::connections::systemBus->async_method_call(
- [ name, aResp{std::move(aResp)} ](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>>
- &subtree) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error";
- aResp->setErrorStatus();
- return;
- }
- bool foundName = false;
- // 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.size() < 1) {
- continue;
- }
- // Check if computer system exist
- if (boost::ends_with(path, name)) {
- foundName = true;
- BMCWEB_LOG_DEBUG << "Found name: " << name;
- const std::string connectionName = connectionNames[0].first;
- crow::connections::systemBus->async_method_call(
- [ aResp, name(std::string(name)) ](
- const boost::system::error_code ec,
- const std::vector<std::pair<std::string, VariantType>>
- &propertiesList) {
- if (ec) {
- BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
- aResp->setErrorStatus();
- return;
+
+ /**
+ * @brief Retrieves computer system properties over dbus
+ *
+ * @param[in] aResp Shared pointer for completing asynchronous calls
+ * @param[in] name Computer system name from request
+ *
+ * @return None.
+ */
+ void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp,
+ const std::string &name)
+ {
+ const std::array<const char *, 5> interfaces = {
+ "xyz.openbmc_project.Inventory.Decorator.Asset",
+ "xyz.openbmc_project.Inventory.Item.Cpu",
+ "xyz.openbmc_project.Inventory.Item.Dimm",
+ "xyz.openbmc_project.Inventory.Item.System",
+ "xyz.openbmc_project.Common.UUID",
+ };
+ BMCWEB_LOG_DEBUG << "Get available system components.";
+ crow::connections::systemBus->async_method_call(
+ [name, aResp{std::move(aResp)}](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, std::vector<std::pair<
+ std::string, std::vector<std::string>>>>>
+ &subtree) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error";
+ aResp->setErrorStatus();
+ return;
+ }
+ bool foundName = false;
+ // 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.size() < 1)
+ {
+ continue;
}
- BMCWEB_LOG_DEBUG << "Got " << propertiesList.size()
- << "properties for system";
- for (const std::pair<std::string, VariantType> &property :
- propertiesList) {
- const std::string *value =
- mapbox::getPtr<const std::string>(property.second);
- if (value != nullptr) {
- aResp->res.jsonValue[property.first] = *value;
- }
- }
- aResp->res.jsonValue["Name"] = name;
- aResp->res.jsonValue["Id"] =
- aResp->res.jsonValue["SerialNumber"];
- },
- connectionName, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
- } else {
- // This is not system, so check if it's cpu, dimm, UUID or BiosVer
- for (auto const &s : connectionNames) {
- for (auto const &i : s.second) {
- if (boost::ends_with(i, "Dimm")) {
- BMCWEB_LOG_DEBUG << "Found Dimm, now get it properties.";
- crow::connections::systemBus->async_method_call(
- [&, aResp](const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, VariantType>> &properties) {
- if (ec) {
- BMCWEB_LOG_ERROR << "DBUS response error " << ec;
- aResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << properties.size()
- << "Dimm properties.";
- for (const auto &p : properties) {
- if (p.first == "MemorySize") {
- const std::string *value =
- mapbox::getPtr<const std::string>(p.second);
- if ((value != nullptr) && (*value != "NULL")) {
- // Remove units char
- int32_t unitCoeff;
- if (boost::ends_with(*value, "MB")) {
- unitCoeff = 1000;
- } else if (boost::ends_with(*value, "KB")) {
- unitCoeff = 1000000;
- } else {
- BMCWEB_LOG_ERROR
- << "Unsupported memory units";
- aResp->setErrorStatus();
- return;
+ // Check if computer system exist
+ if (boost::ends_with(path, name))
+ {
+ foundName = true;
+ BMCWEB_LOG_DEBUG << "Found name: " << name;
+ const std::string connectionName =
+ connectionNames[0].first;
+ crow::connections::systemBus->async_method_call(
+ [aResp, name(std::string(name))](
+ const boost::system::error_code ec,
+ const std::vector<
+ std::pair<std::string, VariantType>>
+ &propertiesList) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "DBUS response error: "
+ << ec;
+ aResp->setErrorStatus();
+ return;
}
-
- auto memSize = boost::lexical_cast<int>(
- value->substr(0, value->length() - 2));
- aResp->res.jsonValue["TotalSystemMemoryGiB"] +=
- memSize * unitCoeff;
- aResp->res.jsonValue["MemorySummary"]["Status"]
- ["State"] = "Enabled";
- }
- }
- }
- },
- s.first, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Inventory.Item.Dimm");
- } else if (boost::ends_with(i, "Cpu")) {
- BMCWEB_LOG_DEBUG << "Found Cpu, now get it properties.";
- crow::connections::systemBus->async_method_call(
- [&, aResp](const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, VariantType>> &properties) {
- if (ec) {
- BMCWEB_LOG_ERROR << "DBUS response error " << ec;
- aResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << properties.size()
- << "Cpu properties.";
- for (const auto &p : properties) {
- if (p.first == "ProcessorFamily") {
- const std::string *value =
- mapbox::getPtr<const std::string>(p.second);
- if (value != nullptr) {
- aResp->res
- .jsonValue["ProcessorSummary"]["Count"] =
- aResp->res
- .jsonValue["ProcessorSummary"]["Count"]
- .get<int>() +
- 1;
- aResp->res.jsonValue["ProcessorSummary"]
- ["Status"]["State"] =
- "Enabled";
- aResp->res
- .jsonValue["ProcessorSummary"]["Model"] =
- *value;
- }
- }
- }
- },
- s.first, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Inventory.Item.Cpu");
- } else if (boost::ends_with(i, "UUID")) {
- BMCWEB_LOG_DEBUG << "Found UUID, now get it properties.";
- crow::connections::systemBus->async_method_call(
- [aResp](const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string, VariantType>> &properties) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- aResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << properties.size()
- << "UUID properties.";
- for (const std::pair<std::string, VariantType> &p :
- properties) {
- if (p.first == "BIOSVer") {
- const std::string *value =
- mapbox::getPtr<const std::string>(p.second);
- if (value != nullptr) {
- aResp->res.jsonValue["BiosVersion"] = *value;
- }
- }
- if (p.first == "UUID") {
- const std::string *value =
- mapbox::getPtr<const std::string>(p.second);
- BMCWEB_LOG_DEBUG << "UUID = " << *value
- << " length " << value->length();
- if (value != nullptr) {
- // Workaround for to short return str in smbios
- // demo app, 32 bytes are described by spec
- if (value->length() > 0 &&
- value->length() < 32) {
- std::string correctedValue = *value;
- correctedValue.append(32 - value->length(),
- '0');
- value = &correctedValue;
- } else if (value->length() == 32) {
- aResp->res.jsonValue["UUID"] =
- value->substr(0, 8) + "-" +
- value->substr(8, 4) + "-" +
- value->substr(12, 4) + "-" +
- value->substr(16, 4) + "-" +
- value->substr(20, 12);
+ BMCWEB_LOG_DEBUG << "Got "
+ << propertiesList.size()
+ << "properties for system";
+ for (const std::pair<std::string, VariantType>
+ &property : propertiesList)
+ {
+ const std::string *value =
+ mapbox::getPtr<const std::string>(
+ property.second);
+ if (value != nullptr)
+ {
+ aResp->res.jsonValue[property.first] =
+ *value;
+ }
}
- }
+ aResp->res.jsonValue["Name"] = name;
+ aResp->res.jsonValue["Id"] =
+ aResp->res.jsonValue["SerialNumber"];
+ },
+ connectionName, path,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Inventory.Decorator.Asset");
+ }
+ else
+ {
+ // This is not system, so check if it's cpu, dimm, UUID
+ // or BiosVer
+ for (auto const &s : connectionNames)
+ {
+ for (auto const &i : s.second)
+ {
+ if (boost::ends_with(i, "Dimm"))
+ {
+ BMCWEB_LOG_DEBUG
+ << "Found Dimm, now get it properties.";
+ crow::connections::systemBus->async_method_call(
+ [&, aResp](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, VariantType>>
+ &properties) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "DBUS response error "
+ << ec;
+ aResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG
+ << "Got " << properties.size()
+ << "Dimm properties.";
+ for (const auto &p : properties)
+ {
+ if (p.first == "MemorySize")
+ {
+ const std::string *value =
+ mapbox::getPtr<
+ const std::string>(
+ p.second);
+ if ((value != nullptr) &&
+ (*value != "NULL"))
+ {
+ // Remove units char
+ int32_t unitCoeff;
+ if (boost::ends_with(
+ *value, "MB"))
+ {
+ unitCoeff = 1000;
+ }
+ else if (boost::
+ ends_with(
+ *value,
+ "KB"))
+ {
+ unitCoeff = 1000000;
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR
+ << "Unsupported"
+ " memory "
+ "units";
+ aResp
+ ->setErrorStatus();
+ return;
+ }
+
+ auto memSize =
+ boost::lexical_cast<
+ int>(value->substr(
+ 0,
+ value->length() -
+ 2));
+ aResp->res.jsonValue
+ ["TotalSystemMemory"
+ "GiB"] +=
+ memSize * unitCoeff;
+ aResp->res.jsonValue
+ ["MemorySummary"]
+ ["Status"]
+ ["State"] =
+ "Enabled";
+ }
+ }
+ }
+ },
+ s.first, path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ "xyz.openbmc_project.Inventory.Item."
+ "Dimm");
+ }
+ else if (boost::ends_with(i, "Cpu"))
+ {
+ BMCWEB_LOG_DEBUG
+ << "Found Cpu, now get it properties.";
+ crow::connections::systemBus
+ ->async_method_call(
+ [&, aResp](
+ const boost::system::error_code
+ ec,
+ const std::vector<std::pair<
+ std::string, VariantType>>
+ &properties) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR
+ << "DBUS response "
+ "error "
+ << ec;
+ aResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG
+ << "Got "
+ << properties.size()
+ << "Cpu properties.";
+ for (const auto &p : properties)
+ {
+ if (p.first ==
+ "ProcessorFamily")
+ {
+ const std::string
+ *value =
+ mapbox::getPtr<
+ const std::
+ string>(
+ p.second);
+ if (value != nullptr)
+ {
+ aResp->res.jsonValue
+ ["ProcessorSumm"
+ "ary"]
+ ["Count"] =
+ aResp->res
+ .jsonValue
+ ["Proce"
+ "ssorS"
+ "ummar"
+ "y"]
+ ["Coun"
+ "t"]
+ .get<
+ int>() +
+ 1;
+ aResp->res.jsonValue
+ ["ProcessorSumm"
+ "ary"]
+ ["Status"]
+ ["State"] =
+ "Enabled";
+ aResp->res.jsonValue
+ ["ProcessorSumm"
+ "ary"]
+ ["Model"] =
+ *value;
+ }
+ }
+ }
+ },
+ s.first, path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ "xyz.openbmc_project.Inventory."
+ "Item.Cpu");
+ }
+ else if (boost::ends_with(i, "UUID"))
+ {
+ BMCWEB_LOG_DEBUG
+ << "Found UUID, now get it properties.";
+ crow::connections::systemBus->async_method_call(
+ [aResp](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, VariantType>>
+ &properties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG
+ << "DBUS response error "
+ << ec;
+ aResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG
+ << "Got " << properties.size()
+ << "UUID properties.";
+ for (const std::pair<std::string,
+ VariantType>
+ &p : properties)
+ {
+ if (p.first == "BIOSVer")
+ {
+ const std::string *value =
+ mapbox::getPtr<
+ const std::string>(
+ p.second);
+ if (value != nullptr)
+ {
+ aResp->res.jsonValue
+ ["BiosVersion"] =
+ *value;
+ }
+ }
+ if (p.first == "UUID")
+ {
+ const std::string *value =
+ mapbox::getPtr<
+ const std::string>(
+ p.second);
+ BMCWEB_LOG_DEBUG
+ << "UUID = " << *value
+ << " length "
+ << value->length();
+ if (value != nullptr)
+ {
+ // Workaround for to
+ // short return str in
+ // smbios demo app, 32
+ // bytes are described
+ // by spec
+ if (value->length() >
+ 0 &&
+ value->length() <
+ 32)
+ {
+ std::string
+ correctedValue =
+ *value;
+ correctedValue.append(
+ 32 -
+ value
+ ->length(),
+ '0');
+ value =
+ &correctedValue;
+ }
+ else if (
+ value->length() ==
+ 32)
+ {
+ aResp->res.jsonValue
+ ["UUID"] =
+ value->substr(
+ 0, 8) +
+ "-" +
+ value->substr(
+ 8, 4) +
+ "-" +
+ value->substr(
+ 12, 4) +
+ "-" +
+ value->substr(
+ 16, 4) +
+ "-" +
+ value->substr(
+ 20, 12);
+ }
+ }
+ }
+ }
+ },
+ s.first, path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll",
+ "xyz.openbmc_project.Common.UUID");
+ }
}
- }
- },
- s.first, path, "org.freedesktop.DBus.Properties",
- "GetAll", "xyz.openbmc_project.Common.UUID");
- }
- }
- }
- }
- }
- if (foundName == false) {
- aResp->setErrorStatus();
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
- }
-
- /**
- * @brief Retrieves identify led group properties over dbus
- *
- * @param[in] aResp Shared pointer for completing asynchronous calls.
- * @param[in] callback Callback for process retrieved data.
- *
- * @return None.
- */
- template <typename CallbackFunc>
- void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp,
- CallbackFunc &&callback) {
- BMCWEB_LOG_DEBUG << "Get led groups";
- crow::connections::systemBus->async_method_call(
- [
- aResp{std::move(aResp)}, &callback
- ](const boost::system::error_code &ec, const ManagedObjectsType &resp) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- aResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
- for (const auto &objPath : resp) {
- const std::string &path = objPath.first;
- if (path.rfind("enclosure_identify") != std::string::npos) {
- for (const auto &interface : objPath.second) {
- if (interface.first == "xyz.openbmc_project.Led.Group") {
- for (const auto &property : interface.second) {
- if (property.first == "Asserted") {
- const bool *asserted =
- mapbox::getPtr<const bool>(property.second);
- if (nullptr != asserted) {
- callback(*asserted, aResp);
- } else {
- callback(false, aResp);
- }
+ }
}
- }
}
- }
- }
- }
- },
- "xyz.openbmc_project.LED.GroupManager",
- "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
- "GetManagedObjects");
- }
+ if (foundName == false)
+ {
+ aResp->setErrorStatus();
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
+ }
- template <typename CallbackFunc>
- void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp,
- CallbackFunc &&callback) {
- BMCWEB_LOG_DEBUG << "Get identify led properties";
- crow::connections::systemBus->async_method_call(
- [ aResp{std::move(aResp)}, &callback ](
- const boost::system::error_code ec,
- const PropertiesType &properties) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- aResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << properties.size() << "led properties.";
- std::string output;
- for (const auto &property : properties) {
- if (property.first == "State") {
- const std::string *s =
- mapbox::getPtr<std::string>(property.second);
- if (nullptr != s) {
- BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
- const auto pos = s->rfind('.');
- if (pos != std::string::npos) {
- auto led = s->substr(pos + 1);
- for (const std::pair<const char *, const char *> &p :
- std::array<std::pair<const char *, const char *>, 3>{
- {{"On", "Lit"},
- {"Blink", "Blinking"},
- {"Off", "Off"}}}) {
- if (led == p.first) {
- output = p.second;
+ /**
+ * @brief Retrieves identify led group properties over dbus
+ *
+ * @param[in] aResp Shared pointer for completing asynchronous calls.
+ * @param[in] callback Callback for process retrieved data.
+ *
+ * @return None.
+ */
+ template <typename CallbackFunc>
+ void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp,
+ CallbackFunc &&callback)
+ {
+ BMCWEB_LOG_DEBUG << "Get led groups";
+ crow::connections::systemBus->async_method_call(
+ [aResp{std::move(aResp)},
+ &callback](const boost::system::error_code &ec,
+ const ManagedObjectsType &resp) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ aResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Got " << resp.size()
+ << "led group objects.";
+ for (const auto &objPath : resp)
+ {
+ const std::string &path = objPath.first;
+ if (path.rfind("enclosure_identify") != std::string::npos)
+ {
+ for (const auto &interface : objPath.second)
+ {
+ if (interface.first ==
+ "xyz.openbmc_project.Led.Group")
+ {
+ for (const auto &property : interface.second)
+ {
+ if (property.first == "Asserted")
+ {
+ const bool *asserted =
+ mapbox::getPtr<const bool>(
+ property.second);
+ if (nullptr != asserted)
+ {
+ callback(*asserted, aResp);
+ }
+ else
+ {
+ callback(false, aResp);
+ }
+ }
+ }
+ }
+ }
}
- }
}
- }
- }
- }
- callback(output, aResp);
- },
- "xyz.openbmc_project.LED.Controller.identify",
- "/xyz/openbmc_project/led/physical/identify",
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Led.Physical");
- }
+ },
+ "xyz.openbmc_project.LED.GroupManager",
+ "/xyz/openbmc_project/led/groups",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ }
- /**
- * @brief Retrieves host state properties over dbus
- *
- * @param[in] aResp Shared pointer for completing asynchronous calls.
- *
- * @return None.
- */
- void getHostState(std::shared_ptr<SystemAsyncResp> aResp) {
- BMCWEB_LOG_DEBUG << "Get host information.";
- crow::connections::systemBus->async_method_call(
- [aResp{std::move(aResp)}](const boost::system::error_code ec,
- const PropertiesType &properties) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- aResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Got " << properties.size() << "host properties.";
- for (const auto &property : properties) {
- if (property.first == "CurrentHostState") {
- const std::string *s =
- mapbox::getPtr<const std::string>(property.second);
- BMCWEB_LOG_DEBUG << "Host state: " << *s;
- if (nullptr != s) {
- const auto pos = s->rfind('.');
- if (pos != std::string::npos) {
- // Verify Host State
- if (s->substr(pos + 1) == "Running") {
- aResp->res.jsonValue["PowerState"] = "On";
- aResp->res.jsonValue["Status"]["State"] = "Enabled";
- } else {
- aResp->res.jsonValue["PowerState"] = "Off";
- aResp->res.jsonValue["Status"]["State"] = "Disabled";
- }
+ template <typename CallbackFunc>
+ void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp,
+ CallbackFunc &&callback)
+ {
+ BMCWEB_LOG_DEBUG << "Get identify led properties";
+ crow::connections::systemBus->async_method_call(
+ [aResp{std::move(aResp)},
+ &callback](const boost::system::error_code ec,
+ const PropertiesType &properties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ aResp->setErrorStatus();
+ return;
}
- }
- }
- }
- },
- "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.State.Host");
- }
+ BMCWEB_LOG_DEBUG << "Got " << properties.size()
+ << "led properties.";
+ std::string output;
+ for (const auto &property : properties)
+ {
+ if (property.first == "State")
+ {
+ const std::string *s =
+ mapbox::getPtr<std::string>(property.second);
+ if (nullptr != s)
+ {
+ BMCWEB_LOG_DEBUG << "Identify Led State: " << *s;
+ const auto pos = s->rfind('.');
+ if (pos != std::string::npos)
+ {
+ auto led = s->substr(pos + 1);
+ for (const std::pair<const char *, const char *>
+ &p :
+ std::array<
+ std::pair<const char *, const char *>,
+ 3>{{{"On", "Lit"},
+ {"Blink", "Blinking"},
+ {"Off", "Off"}}})
+ {
+ if (led == p.first)
+ {
+ output = p.second;
+ }
+ }
+ }
+ }
+ }
+ }
+ callback(output, aResp);
+ },
+ "xyz.openbmc_project.LED.Controller.identify",
+ "/xyz/openbmc_project/led/physical/identify",
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Led.Physical");
+ }
+
+ /**
+ * @brief Retrieves host state properties over dbus
+ *
+ * @param[in] aResp Shared pointer for completing asynchronous calls.
+ *
+ * @return None.
+ */
+ void getHostState(std::shared_ptr<SystemAsyncResp> aResp)
+ {
+ BMCWEB_LOG_DEBUG << "Get host information.";
+ crow::connections::systemBus->async_method_call(
+ [aResp{std::move(aResp)}](const boost::system::error_code ec,
+ const PropertiesType &properties) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ aResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Got " << properties.size()
+ << "host properties.";
+ for (const auto &property : properties)
+ {
+ if (property.first == "CurrentHostState")
+ {
+ const std::string *s =
+ mapbox::getPtr<const std::string>(property.second);
+ BMCWEB_LOG_DEBUG << "Host state: " << *s;
+ if (nullptr != s)
+ {
+ const auto pos = s->rfind('.');
+ if (pos != std::string::npos)
+ {
+ // Verify Host State
+ if (s->substr(pos + 1) == "Running")
+ {
+ aResp->res.jsonValue["PowerState"] = "On";
+ aResp->res.jsonValue["Status"]["State"] =
+ "Enabled";
+ }
+ else
+ {
+ aResp->res.jsonValue["PowerState"] = "Off";
+ aResp->res.jsonValue["Status"]["State"] =
+ "Disabled";
+ }
+ }
+ }
+ }
+ }
+ },
+ "xyz.openbmc_project.State.Host",
+ "/xyz/openbmc_project/state/host0",
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.State.Host");
+ }
};
/**
* SystemsCollection derived class for delivering ComputerSystems Collection
* Schema
*/
-class SystemsCollection : public Node {
- public:
- SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/") {
- Node::json["@odata.type"] =
- "#ComputerSystemCollection.ComputerSystemCollection";
- Node::json["@odata.id"] = "/redfish/v1/Systems";
- Node::json["@odata.context"] =
- "/redfish/v1/"
- "$metadata#ComputerSystemCollection.ComputerSystemCollection";
- Node::json["Name"] = "Computer System Collection";
+class SystemsCollection : public Node
+{
+ public:
+ SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/")
+ {
+ Node::json["@odata.type"] =
+ "#ComputerSystemCollection.ComputerSystemCollection";
+ Node::json["@odata.id"] = "/redfish/v1/Systems";
+ Node::json["@odata.context"] =
+ "/redfish/v1/"
+ "$metadata#ComputerSystemCollection.ComputerSystemCollection";
+ Node::json["Name"] = "Computer System Collection";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
+ }
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // Get board list, and call the below callback for JSON preparation
- provider.getBaseboardList(
- [&](const bool &success, const std::vector<std::string> &output) {
- if (success) {
- // ... prepare json array with appropriate @odata.id links
- nlohmann::json boardArray = nlohmann::json::array();
- for (const std::string &boardItem : output) {
- boardArray.push_back(
- {{"@odata.id", "/redfish/v1/Systems/" + boardItem}});
+ private:
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // Get board list, and call the below callback for JSON preparation
+ provider.getBaseboardList([&](const bool &success,
+ const std::vector<std::string> &output) {
+ if (success)
+ {
+ // ... prepare json array with appropriate @odata.id links
+ nlohmann::json boardArray = nlohmann::json::array();
+ for (const std::string &boardItem : output)
+ {
+ boardArray.push_back(
+ {{"@odata.id", "/redfish/v1/Systems/" + boardItem}});
+ }
+ // Then attach members, count size and return,
+ Node::json["Members"] = boardArray;
+ Node::json["Members@odata.count"] = boardArray.size();
+ res.jsonValue = Node::json;
}
- // Then attach members, count size and return,
- Node::json["Members"] = boardArray;
- Node::json["Members@odata.count"] = boardArray.size();
- res.jsonValue = Node::json;
- } else {
- // ... otherwise, return INTERNALL ERROR
- res.result(boost::beast::http::status::internal_server_error);
- }
- res.end();
+ else
+ {
+ // ... otherwise, return INTERNALL ERROR
+ res.result(boost::beast::http::status::internal_server_error);
+ }
+ res.end();
});
- }
+ }
- OnDemandSystemsProvider provider;
+ OnDemandSystemsProvider provider;
};
/**
* Systems override class for delivering ComputerSystems Schema
*/
-class Systems : public Node {
- public:
- /*
- * Default Constructor
- */
- Systems(CrowApp &app)
- : Node(app, "/redfish/v1/Systems/<str>/", std::string()) {
- Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
- Node::json["SystemType"] = "Physical";
- Node::json["Description"] = "Computer System";
- Node::json["Boot"]["BootSourceOverrideEnabled"] =
- "Disabled"; // TODO(Dawid), get real boot data
- Node::json["Boot"]["BootSourceOverrideTarget"] =
- "None"; // TODO(Dawid), get real boot data
- Node::json["Boot"]["BootSourceOverrideMode"] =
- "Legacy"; // TODO(Dawid), get real boot data
- Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
- "None", "Pxe", "Hdd", "Cd",
- "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot data
- Node::json["ProcessorSummary"]["Count"] = int(0);
- Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
- Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
- Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
+class Systems : public Node
+{
+ public:
+ /*
+ * Default Constructor
+ */
+ Systems(CrowApp &app) :
+ Node(app, "/redfish/v1/Systems/<str>/", std::string())
+ {
+ Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
+ Node::json["SystemType"] = "Physical";
+ Node::json["Description"] = "Computer System";
+ Node::json["Boot"]["BootSourceOverrideEnabled"] =
+ "Disabled"; // TODO(Dawid), get real boot data
+ Node::json["Boot"]["BootSourceOverrideTarget"] =
+ "None"; // TODO(Dawid), get real boot data
+ Node::json["Boot"]["BootSourceOverrideMode"] =
+ "Legacy"; // TODO(Dawid), get real boot data
+ Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] =
+ {"None", "Pxe", "Hdd", "Cd",
+ "BiosSetup", "UefiShell", "Usb"}; // TODO(Dawid), get real boot
+ // data
+ Node::json["ProcessorSummary"]["Count"] = int(0);
+ Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
+ Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
+ Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- OnDemandSystemsProvider provider;
-
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // Check if there is required param, truly entering this shall be
- // impossible
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- const std::string &name = params[0];
+ private:
+ OnDemandSystemsProvider provider;
- res.jsonValue = Node::json;
- res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // Check if there is required param, truly entering this shall be
+ // impossible
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
- auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+ const std::string &name = params[0];
- provider.getLedGroupIdentify(
- asyncResp, [&](const bool &asserted,
- const std::shared_ptr<SystemAsyncResp> &aResp) {
- if (asserted) {
- // If led group is asserted, then another call is needed to
- // get led status
- provider.getLedIdentify(
- aResp, [](const std::string &ledStatus,
- const std::shared_ptr<SystemAsyncResp> &aResp) {
- if (!ledStatus.empty()) {
- aResp->res.jsonValue["IndicatorLED"] = ledStatus;
- }
- });
- } else {
- aResp->res.jsonValue["IndicatorLED"] = "Off";
- }
- });
- provider.getComputerSystem(asyncResp, name);
- provider.getHostState(asyncResp);
- }
+ res.jsonValue = Node::json;
+ res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
- void doPatch(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- // Check if there is required param, truly entering this shall be
- // impossible
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
- }
- // Parse JSON request body
- nlohmann::json patch;
- if (!json_util::processJsonFromRequest(res, req, patch)) {
- return;
- }
- // Find key with new led value
- const std::string &name = params[0];
- const std::string *reqLedState = nullptr;
- json_util::Result r = json_util::getString(
- "IndicatorLED", patch, reqLedState,
- static_cast<int>(json_util::MessageSetting::TYPE_ERROR) |
- static_cast<int>(json_util::MessageSetting::MISSING),
- res.jsonValue, std::string("/" + name + "/IndicatorLED"));
- if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr)) {
- res.result(boost::beast::http::status::bad_request);
- res.end();
- return;
- }
- // Verify key value
- std::string dbusLedState;
- for (const auto &p : boost::container::flat_map<const char *, const char *>{
- {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}}) {
- if (*reqLedState == p.second) {
- dbusLedState = p.first;
- }
+ auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+
+ provider.getLedGroupIdentify(
+ asyncResp, [&](const bool &asserted,
+ const std::shared_ptr<SystemAsyncResp> &aResp) {
+ if (asserted)
+ {
+ // If led group is asserted, then another call is needed to
+ // get led status
+ provider.getLedIdentify(
+ aResp,
+ [](const std::string &ledStatus,
+ const std::shared_ptr<SystemAsyncResp> &aResp) {
+ if (!ledStatus.empty())
+ {
+ aResp->res.jsonValue["IndicatorLED"] =
+ ledStatus;
+ }
+ });
+ }
+ else
+ {
+ aResp->res.jsonValue["IndicatorLED"] = "Off";
+ }
+ });
+ provider.getComputerSystem(asyncResp, name);
+ provider.getHostState(asyncResp);
}
- // Update led status
- auto asyncResp = std::make_shared<SystemAsyncResp>(res);
- res.jsonValue = Node::json;
- res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
-
- provider.getHostState(asyncResp);
- provider.getComputerSystem(asyncResp, name);
-
- if (dbusLedState.empty()) {
- messages::addMessageToJsonRoot(
- res.jsonValue,
- messages::propertyValueNotInList(*reqLedState, "IndicatorLED"));
- } else {
- // Update led group
- BMCWEB_LOG_DEBUG << "Update led group.";
- crow::connections::systemBus->async_method_call(
- [&, asyncResp{std::move(asyncResp)} ](
- const boost::system::error_code ec) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- asyncResp->setErrorStatus();
- return;
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ // Check if there is required param, truly entering this shall be
+ // impossible
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+ // Parse JSON request body
+ nlohmann::json patch;
+ if (!json_util::processJsonFromRequest(res, req, patch))
+ {
+ return;
+ }
+ // Find key with new led value
+ const std::string &name = params[0];
+ const std::string *reqLedState = nullptr;
+ json_util::Result r = json_util::getString(
+ "IndicatorLED", patch, reqLedState,
+ static_cast<int>(json_util::MessageSetting::TYPE_ERROR) |
+ static_cast<int>(json_util::MessageSetting::MISSING),
+ res.jsonValue, std::string("/" + name + "/IndicatorLED"));
+ if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr))
+ {
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
+ return;
+ }
+ // Verify key value
+ std::string dbusLedState;
+ for (const auto &p :
+ boost::container::flat_map<const char *, const char *>{
+ {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}})
+ {
+ if (*reqLedState == p.second)
+ {
+ dbusLedState = p.first;
}
- BMCWEB_LOG_DEBUG << "Led group update done.";
- },
- "xyz.openbmc_project.LED.GroupManager",
- "/xyz/openbmc_project/led/groups/enclosure_identify",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Led.Group", "Asserted",
- sdbusplus::message::variant<bool>(
- (dbusLedState == "Off" ? false : true)));
- // Update identify led status
- BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
- crow::connections::systemBus->async_method_call(
- [&, asyncResp{std::move(asyncResp)} ](
- const boost::system::error_code ec) {
- if (ec) {
- BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
- asyncResp->setErrorStatus();
- return;
- }
- BMCWEB_LOG_DEBUG << "Led state update done.";
- res.jsonValue["IndicatorLED"] = *reqLedState;
- },
- "xyz.openbmc_project.LED.Controller.identify",
- "/xyz/openbmc_project/led/physical/identify",
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Led.Physical", "State",
- sdbusplus::message::variant<std::string>(
- "xyz.openbmc_project.Led.Physical.Action." + dbusLedState));
+ }
+
+ // Update led status
+ auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+ res.jsonValue = Node::json;
+ res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
+
+ provider.getHostState(asyncResp);
+ provider.getComputerSystem(asyncResp, name);
+
+ if (dbusLedState.empty())
+ {
+ messages::addMessageToJsonRoot(
+ res.jsonValue,
+ messages::propertyValueNotInList(*reqLedState, "IndicatorLED"));
+ }
+ else
+ {
+ // Update led group
+ BMCWEB_LOG_DEBUG << "Update led group.";
+ crow::connections::systemBus->async_method_call(
+ [&, asyncResp{std::move(asyncResp)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ asyncResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Led group update done.";
+ },
+ "xyz.openbmc_project.LED.GroupManager",
+ "/xyz/openbmc_project/led/groups/enclosure_identify",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Led.Group", "Asserted",
+ sdbusplus::message::variant<bool>(
+ (dbusLedState == "Off" ? false : true)));
+ // Update identify led status
+ BMCWEB_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
+ crow::connections::systemBus->async_method_call(
+ [&, asyncResp{std::move(asyncResp)}](
+ const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ asyncResp->setErrorStatus();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Led state update done.";
+ res.jsonValue["IndicatorLED"] = *reqLedState;
+ },
+ "xyz.openbmc_project.LED.Controller.identify",
+ "/xyz/openbmc_project/led/physical/identify",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Led.Physical", "State",
+ sdbusplus::message::variant<std::string>(
+ "xyz.openbmc_project.Led.Physical.Action." + dbusLedState));
+ }
}
- }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp
index 8fb291b..37b0f43 100644
--- a/redfish-core/lib/thermal.hpp
+++ b/redfish-core/lib/thermal.hpp
@@ -18,44 +18,49 @@
#include "node.hpp"
#include "sensors.hpp"
-namespace redfish {
+namespace redfish
+{
-class Thermal : public Node {
- public:
- Thermal(CrowApp& app)
- : Node((app), "/redfish/v1/Chassis/<str>/Thermal/", std::string()) {
- Node::json["@odata.type"] = "#Thermal.v1_4_0.Thermal";
- Node::json["@odata.context"] = "/redfish/v1/$metadata#Thermal.Thermal";
- Node::json["Id"] = "Thermal";
- Node::json["Name"] = "Thermal";
+class Thermal : public Node
+{
+ public:
+ Thermal(CrowApp& app) :
+ Node((app), "/redfish/v1/Chassis/<str>/Thermal/", std::string())
+ {
+ Node::json["@odata.type"] = "#Thermal.v1_4_0.Thermal";
+ Node::json["@odata.context"] = "/redfish/v1/$metadata#Thermal.Thermal";
+ Node::json["Id"] = "Thermal";
+ Node::json["Name"] = "Thermal";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
- {boost::beast::http::verb::put, {{"ConfigureManager"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
- {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
- }
-
- private:
- void doGet(crow::Response& res, const crow::Request& req,
- const std::vector<std::string>& params) override {
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+ {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
}
- const std::string& chassisName = params[0];
- res.jsonValue = Node::json;
- auto asyncResp = std::make_shared<SensorsAsyncResp>(
- res, chassisName,
- std::initializer_list<const char*>{
- "/xyz/openbmc_project/sensors/fan",
- "/xyz/openbmc_project/sensors/temperature"});
- getChassisData(asyncResp);
- }
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.end();
+ return;
+ }
+ const std::string& chassisName = params[0];
+
+ res.jsonValue = Node::json;
+ auto asyncResp = std::make_shared<SensorsAsyncResp>(
+ res, chassisName,
+ std::initializer_list<const char*>{
+ "/xyz/openbmc_project/sensors/fan",
+ "/xyz/openbmc_project/sensors/temperature"});
+ getChassisData(asyncResp);
+ }
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 677b6d1..658937d 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -16,381 +16,450 @@
#pragma once
#include "node.hpp"
+
#include <boost/container/flat_map.hpp>
-namespace redfish {
+namespace redfish
+{
static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
-class UpdateService : public Node {
- public:
- UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/") {
- Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
- Node::json["@odata.id"] = "/redfish/v1/UpdateService";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#UpdateService.UpdateService";
- Node::json["Id"] = "UpdateService";
- Node::json["Description"] = "Service for Software Update";
- Node::json["Name"] = "Update Service";
- Node::json["HttpPushUri"] = "/redfish/v1/UpdateService";
- // UpdateService cannot be disabled
- Node::json["ServiceEnabled"] = true;
- Node::json["FirmwareInventory"] = {
- {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
+class UpdateService : public Node
+{
+ public:
+ UpdateService(CrowApp &app) : Node(app, "/redfish/v1/UpdateService/")
+ {
+ Node::json["@odata.type"] = "#UpdateService.v1_2_0.UpdateService";
+ Node::json["@odata.id"] = "/redfish/v1/UpdateService";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#UpdateService.UpdateService";
+ Node::json["Id"] = "UpdateService";
+ Node::json["Description"] = "Service for Software Update";
+ Node::json["Name"] = "Update Service";
+ Node::json["HttpPushUri"] = "/redfish/v1/UpdateService";
+ // UpdateService cannot be disabled
+ Node::json["ServiceEnabled"] = true;
+ Node::json["FirmwareInventory"] = {
+ {"@odata.id", "/redfish/v1/UpdateService/FirmwareInventory"}};
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- res.jsonValue = Node::json;
- res.end();
- }
- static void activateImage(const std::string &objPath) {
- crow::connections::systemBus->async_method_call(
- [objPath](const boost::system::error_code error_code) {
- if (error_code) {
- BMCWEB_LOG_DEBUG << "error_code = " << error_code;
- BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
- }
- },
- "xyz.openbmc_project.Software.BMC.Updater", objPath,
- "org.freedesktop.DBus.Properties", "Set",
- "xyz.openbmc_project.Software.Activation", "RequestedActivation",
- sdbusplus::message::variant<std::string>(
- "xyz.openbmc_project.Software.Activation.RequestedActivations."
- "Active"));
- }
- void doPost(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- BMCWEB_LOG_DEBUG << "doPost...";
-
- // Only allow one FW update at a time
- if (fwUpdateMatcher != nullptr) {
- res.addHeader("Retry-After", "30");
- res.result(boost::beast::http::status::service_unavailable);
- res.jsonValue = messages::serviceTemporarilyUnavailable("3");
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- // Make this const static so it survives outside this method
- static boost::asio::deadline_timer timeout(*req.ioService,
- boost::posix_time::seconds(5));
- timeout.expires_from_now(boost::posix_time::seconds(5));
-
- timeout.async_wait([&res](const boost::system::error_code &ec) {
- fwUpdateMatcher = nullptr;
- 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;
- }
-
- res.result(boost::beast::http::status::internal_server_error);
- res.jsonValue = redfish::messages::internalError();
- res.end();
- });
-
- auto callback = [&res](sdbusplus::message::message &m) {
- BMCWEB_LOG_DEBUG << "Match fired";
- bool flag = false;
-
- if (m.is_method_error()) {
- BMCWEB_LOG_DEBUG << "Dbus method error!!!";
+ private:
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ res.jsonValue = Node::json;
res.end();
- return;
- }
- std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string,
- sdbusplus::message::variant<std::string>>>>>
- interfaces_properties;
+ }
+ static void activateImage(const std::string &objPath)
+ {
+ crow::connections::systemBus->async_method_call(
+ [objPath](const boost::system::error_code error_code) {
+ if (error_code)
+ {
+ BMCWEB_LOG_DEBUG << "error_code = " << error_code;
+ BMCWEB_LOG_DEBUG << "error msg = " << error_code.message();
+ }
+ },
+ "xyz.openbmc_project.Software.BMC.Updater", objPath,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Software.Activation", "RequestedActivation",
+ sdbusplus::message::variant<std::string>(
+ "xyz.openbmc_project.Software.Activation.RequestedActivations."
+ "Active"));
+ }
+ void doPost(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ BMCWEB_LOG_DEBUG << "doPost...";
- sdbusplus::message::object_path objPath;
-
- m.read(objPath, interfaces_properties); // Read in the object path
- // that was just created
- // std::string str_objpath = objPath.str; // keep a copy for
- // constructing response message
- BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath;
- for (auto &interface : interfaces_properties) {
- BMCWEB_LOG_DEBUG << "interface = " << interface.first;
-
- if (interface.first == "xyz.openbmc_project.Software.Activation") {
- // cancel timer only when xyz.openbmc_project.Software.Activation
- // interface is added
- boost::system::error_code ec;
- timeout.cancel(ec);
- if (ec) {
- BMCWEB_LOG_ERROR << "error canceling timer " << ec;
- }
- UpdateService::activateImage(objPath.str); // str_objpath);
- res.jsonValue = redfish::messages::success();
- BMCWEB_LOG_DEBUG << "ending response";
- res.end();
- fwUpdateMatcher = nullptr;
- }
- }
- };
-
- fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
- *crow::connections::systemBus,
- "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
- "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
- callback);
-
- std::string filepath(
- "/tmp/images/" +
- boost::uuids::to_string(boost::uuids::random_generator()()));
- BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
- std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
- std::ofstream::trunc);
- out << req.body;
- out.close();
- BMCWEB_LOG_DEBUG << "file upload complete!!";
- }
-};
-
-class SoftwareInventoryCollection : public Node {
- public:
- template <typename CrowApp>
- SoftwareInventoryCollection(CrowApp &app)
- : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/") {
- Node::json["@odata.type"] =
- "#SoftwareInventoryCollection.SoftwareInventoryCollection";
- Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory";
- Node::json["@odata.context"] =
- "/redfish/v1/"
- "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
- Node::json["Name"] = "Software Inventory Collection";
-
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
-
- private:
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
- res.jsonValue = Node::json;
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>>
- &subtree) {
- if (ec) {
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
+ // Only allow one FW update at a time
+ if (fwUpdateMatcher != nullptr)
+ {
+ res.addHeader("Retry-After", "30");
+ res.result(boost::beast::http::status::service_unavailable);
+ res.jsonValue = messages::serviceTemporarilyUnavailable("3");
+ res.end();
return;
- }
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
+ }
+ // Make this const static so it survives outside this method
+ static boost::asio::deadline_timer timeout(
+ *req.ioService, boost::posix_time::seconds(5));
- for (auto &obj : subtree) {
- const std::vector<std::pair<std::string, std::vector<std::string>>>
- &connections = obj.second;
+ timeout.expires_from_now(boost::posix_time::seconds(5));
- for (auto &conn : connections) {
- const std::string &connectionName = conn.first;
- BMCWEB_LOG_DEBUG << "connectionName = " << connectionName;
- BMCWEB_LOG_DEBUG << "obj.first = " << obj.first;
-
- crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code error_code,
- const VariantType &activation) {
- BMCWEB_LOG_DEBUG << "safe returned in lambda function";
- if (error_code) {
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- const std::string *sw_inv_purpose =
- mapbox::getPtr<const std::string>(activation);
- if (sw_inv_purpose == nullptr) {
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
- std::size_t last_pos = sw_inv_purpose->rfind(".");
- if (last_pos == std::string::npos) {
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
- nlohmann::json &members =
- asyncResp->res.jsonValue["Members"];
- members.push_back(
- {{"@odata.id",
- "/redfish/v1/UpdateService/FirmwareInventory/" +
- sw_inv_purpose->substr(last_pos + 1)}});
- asyncResp->res.jsonValue["Members@odata.count"] =
- members.size();
- },
- connectionName, obj.first, "org.freedesktop.DBus.Properties",
- "Get", "xyz.openbmc_project.Software.Activation",
- "Activation");
+ timeout.async_wait([&res](const boost::system::error_code &ec) {
+ fwUpdateMatcher = nullptr;
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ // expected, we were canceled before the timer completed.
+ return;
}
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/software", int32_t(1),
- std::array<const char *, 1>{"xyz.openbmc_project.Software.Version"});
- }
+ 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;
+ }
+
+ res.result(boost::beast::http::status::internal_server_error);
+ res.jsonValue = redfish::messages::internalError();
+ res.end();
+ });
+
+ auto callback = [&res](sdbusplus::message::message &m) {
+ BMCWEB_LOG_DEBUG << "Match fired";
+ bool flag = false;
+
+ if (m.is_method_error())
+ {
+ BMCWEB_LOG_DEBUG << "Dbus method error!!!";
+ res.end();
+ return;
+ }
+ std::vector<std::pair<
+ std::string,
+ std::vector<std::pair<
+ std::string, sdbusplus::message::variant<std::string>>>>>
+ interfaces_properties;
+
+ sdbusplus::message::object_path objPath;
+
+ m.read(objPath, interfaces_properties); // Read in the object path
+ // that was just created
+ // std::string str_objpath = objPath.str; // keep a copy for
+ // constructing response message
+ BMCWEB_LOG_DEBUG << "obj path = " << objPath.str; // str_objpath;
+ for (auto &interface : interfaces_properties)
+ {
+ BMCWEB_LOG_DEBUG << "interface = " << interface.first;
+
+ if (interface.first ==
+ "xyz.openbmc_project.Software.Activation")
+ {
+ // cancel timer only when
+ // xyz.openbmc_project.Software.Activation interface is
+ // added
+ boost::system::error_code ec;
+ timeout.cancel(ec);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "error canceling timer " << ec;
+ }
+ UpdateService::activateImage(objPath.str); // str_objpath);
+ res.jsonValue = redfish::messages::success();
+ BMCWEB_LOG_DEBUG << "ending response";
+ res.end();
+ fwUpdateMatcher = nullptr;
+ }
+ }
+ };
+
+ fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
+ *crow::connections::systemBus,
+ "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+ "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
+ callback);
+
+ std::string filepath(
+ "/tmp/images/" +
+ boost::uuids::to_string(boost::uuids::random_generator()()));
+ BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
+ std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
+ std::ofstream::trunc);
+ out << req.body;
+ out.close();
+ BMCWEB_LOG_DEBUG << "file upload complete!!";
+ }
};
-class SoftwareInventory : public Node {
- public:
- template <typename CrowApp>
- SoftwareInventory(CrowApp &app)
- : Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
- std::string()) {
- Node::json["@odata.type"] = "#SoftwareInventory.v1_1_0.SoftwareInventory";
- Node::json["@odata.context"] =
- "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
- Node::json["Name"] = "Software Inventory";
- Node::json["Updateable"] = false;
- Node::json["Status"]["Health"] = "OK";
- Node::json["Status"]["HealthRollup"] = "OK";
- Node::json["Status"]["State"] = "Enabled";
- entityPrivileges = {
- {boost::beast::http::verb::get, {{"Login"}}},
- {boost::beast::http::verb::head, {{"Login"}}},
- {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
- {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
- }
+class SoftwareInventoryCollection : public Node
+{
+ public:
+ template <typename CrowApp>
+ SoftwareInventoryCollection(CrowApp &app) :
+ Node(app, "/redfish/v1/UpdateService/FirmwareInventory/")
+ {
+ Node::json["@odata.type"] =
+ "#SoftwareInventoryCollection.SoftwareInventoryCollection";
+ Node::json["@odata.id"] = "/redfish/v1/UpdateService/FirmwareInventory";
+ Node::json["@odata.context"] =
+ "/redfish/v1/"
+ "$metadata#SoftwareInventoryCollection.SoftwareInventoryCollection";
+ Node::json["Name"] = "Software Inventory Collection";
- private:
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> ¶ms) override {
- std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
- res.jsonValue = Node::json;
-
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.jsonValue = messages::internalError();
- res.end();
- return;
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
}
- std::shared_ptr<std::string> sw_id =
- std::make_shared<std::string>(params[0]);
+ private:
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ res.jsonValue = Node::json;
- res.jsonValue["@odata.id"] =
- "/redfish/v1/UpdateService/FirmwareInventory/" + *sw_id;
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, sw_id](
- const boost::system::error_code ec,
- const std::vector<std::pair<
- std::string,
- std::vector<std::pair<std::string, std::vector<std::string>>>>>
- &subtree) {
- BMCWEB_LOG_DEBUG << "doGet callback...";
- if (ec) {
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
-
- for (const std::pair<std::string,
- std::vector<std::pair<std::string,
- std::vector<std::string>>>>
- &obj : subtree) {
- if (boost::ends_with(obj.first, *sw_id) != true) {
- continue;
- }
-
- if (obj.second.size() <= 1) {
- continue;
- }
-
- crow::connections::systemBus->async_method_call(
- [asyncResp, sw_id](
- const boost::system::error_code error_code,
- const boost::container::flat_map<std::string, VariantType>
- &propertiesList) {
- if (error_code) {
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, std::vector<std::pair<
+ std::string, std::vector<std::string>>>>>
+ &subtree) {
+ if (ec)
+ {
asyncResp->res.result(
boost::beast::http::status::internal_server_error);
return;
- }
- boost::container::flat_map<std::string,
- VariantType>::const_iterator it =
- propertiesList.find("Purpose");
- if (it == propertiesList.end()) {
- BMCWEB_LOG_DEBUG << "Can't find property \"Purpose\"!";
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
- const std::string *sw_inv_purpose =
- mapbox::getPtr<const std::string>(it->second);
- if (sw_inv_purpose == nullptr) {
- BMCWEB_LOG_DEBUG << "wrong types for property\"Purpose\"!";
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
+ }
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
- BMCWEB_LOG_DEBUG << "sw_inv_purpose = " << *sw_inv_purpose;
- if (boost::ends_with(*sw_inv_purpose, "." + *sw_id)) {
- it = propertiesList.find("Version");
- if (it == propertiesList.end()) {
- BMCWEB_LOG_DEBUG << "Can't find property \"Version\"!";
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
+ for (auto &obj : subtree)
+ {
+ const std::vector<
+ std::pair<std::string, std::vector<std::string>>>
+ &connections = obj.second;
+
+ for (auto &conn : connections)
+ {
+ const std::string &connectionName = conn.first;
+ BMCWEB_LOG_DEBUG << "connectionName = "
+ << connectionName;
+ BMCWEB_LOG_DEBUG << "obj.first = " << obj.first;
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+ const boost::system::error_code error_code,
+ const VariantType &activation) {
+ BMCWEB_LOG_DEBUG
+ << "safe returned in lambda function";
+ if (error_code)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+
+ const std::string *sw_inv_purpose =
+ mapbox::getPtr<const std::string>(
+ activation);
+ if (sw_inv_purpose == nullptr)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+ std::size_t last_pos =
+ sw_inv_purpose->rfind(".");
+ if (last_pos == std::string::npos)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+ nlohmann::json &members =
+ asyncResp->res.jsonValue["Members"];
+ members.push_back(
+ {{"@odata.id", "/redfish/v1/UpdateService/"
+ "FirmwareInventory/" +
+ sw_inv_purpose->substr(
+ last_pos + 1)}});
+ asyncResp->res
+ .jsonValue["Members@odata.count"] =
+ members.size();
+ },
+ connectionName, obj.first,
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Software.Activation",
+ "Activation");
}
-
- const std::string *version =
- mapbox::getPtr<const std::string>(it->second);
-
- if (version != nullptr) {
- BMCWEB_LOG_DEBUG << "Can't find property \"Version\"!";
- asyncResp->res.result(
- boost::beast::http::status::internal_server_error);
- return;
- }
- asyncResp->res.jsonValue["Version"] = *version;
- asyncResp->res.jsonValue["Id"] = *sw_id;
- }
- },
- obj.second[0].first, obj.first,
- "org.freedesktop.DBus.Properties", "GetAll",
- "xyz.openbmc_project.Software.Version");
- }
- },
- "xyz.openbmc_project.ObjectMapper",
- "/xyz/openbmc_project/object_mapper",
- "xyz.openbmc_project.ObjectMapper", "GetSubTree",
- "/xyz/openbmc_project/software", int32_t(1),
- std::array<const char *, 1>{"xyz.openbmc_project.Software.Version"});
- }
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/software", int32_t(1),
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Software.Version"});
+ }
};
-} // namespace redfish
+class SoftwareInventory : public Node
+{
+ public:
+ template <typename CrowApp>
+ SoftwareInventory(CrowApp &app) :
+ Node(app, "/redfish/v1/UpdateService/FirmwareInventory/<str>/",
+ std::string())
+ {
+ Node::json["@odata.type"] =
+ "#SoftwareInventory.v1_1_0.SoftwareInventory";
+ Node::json["@odata.context"] =
+ "/redfish/v1/$metadata#SoftwareInventory.SoftwareInventory";
+ Node::json["Name"] = "Software Inventory";
+ Node::json["Updateable"] = false;
+ Node::json["Status"]["Health"] = "OK";
+ Node::json["Status"]["HealthRollup"] = "OK";
+ Node::json["Status"]["State"] = "Enabled";
+ entityPrivileges = {
+ {boost::beast::http::verb::get, {{"Login"}}},
+ {boost::beast::http::verb::head, {{"Login"}}},
+ {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+ {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
+ }
+
+ private:
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ res.jsonValue = Node::json;
+
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.jsonValue = messages::internalError();
+ res.end();
+ return;
+ }
+
+ std::shared_ptr<std::string> sw_id =
+ std::make_shared<std::string>(params[0]);
+
+ res.jsonValue["@odata.id"] =
+ "/redfish/v1/UpdateService/FirmwareInventory/" + *sw_id;
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, sw_id](
+ const boost::system::error_code ec,
+ const std::vector<std::pair<
+ std::string, std::vector<std::pair<
+ std::string, std::vector<std::string>>>>>
+ &subtree) {
+ BMCWEB_LOG_DEBUG << "doGet callback...";
+ if (ec)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::internal_server_error);
+ return;
+ }
+
+ for (const std::pair<
+ std::string,
+ std::vector<
+ std::pair<std::string, std::vector<std::string>>>>
+ &obj : subtree)
+ {
+ if (boost::ends_with(obj.first, *sw_id) != true)
+ {
+ continue;
+ }
+
+ if (obj.second.size() <= 1)
+ {
+ continue;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ sw_id](const boost::system::error_code error_code,
+ const boost::container::flat_map<
+ std::string, VariantType> &propertiesList) {
+ if (error_code)
+ {
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+ boost::container::flat_map<
+ std::string, VariantType>::const_iterator it =
+ propertiesList.find("Purpose");
+ if (it == propertiesList.end())
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't find property \"Purpose\"!";
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+ const std::string *sw_inv_purpose =
+ mapbox::getPtr<const std::string>(it->second);
+ if (sw_inv_purpose == nullptr)
+ {
+ BMCWEB_LOG_DEBUG
+ << "wrong types for property\"Purpose\"!";
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "sw_inv_purpose = "
+ << *sw_inv_purpose;
+ if (boost::ends_with(*sw_inv_purpose, "." + *sw_id))
+ {
+ it = propertiesList.find("Version");
+ if (it == propertiesList.end())
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't find property \"Version\"!";
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+
+ const std::string *version =
+ mapbox::getPtr<const std::string>(
+ it->second);
+
+ if (version != nullptr)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Can't find property \"Version\"!";
+ asyncResp->res.result(
+ boost::beast::http::status::
+ internal_server_error);
+ return;
+ }
+ asyncResp->res.jsonValue["Version"] = *version;
+ asyncResp->res.jsonValue["Id"] = *sw_id;
+ }
+ },
+ obj.second[0].first, obj.first,
+ "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Software.Version");
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/software", int32_t(1),
+ std::array<const char *, 1>{
+ "xyz.openbmc_project.Software.Version"});
+ }
+};
+
+} // namespace redfish
diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
index 4773e3d..a807762 100644
--- a/redfish-core/src/error_messages.cpp
+++ b/redfish-core/src/error_messages.cpp
@@ -13,78 +13,93 @@
// See the License for the specific language governing permissions and
// limitations under the License.
*/
-#include <error_messages.hpp>
#include <crow/logging.h>
-namespace redfish {
+#include <error_messages.hpp>
-namespace messages {
+namespace redfish
+{
+
+namespace messages
+{
void addMessageToErrorJson(nlohmann::json& target,
- const nlohmann::json& message) {
- auto& error = target["error"];
+ const nlohmann::json& message)
+{
+ auto& error = target["error"];
- // If this is the first error message, fill in the information from the first
- // error message to the top level struct
- if (!error.is_object()) {
- auto message_id_iterator = message.find("MessageId");
- if (message_id_iterator == message.end()) {
- BMCWEB_LOG_CRITICAL << "Attempt to add error message without MessageId";
- return;
- }
+ // If this is the first error message, fill in the information from the
+ // first error message to the top level struct
+ if (!error.is_object())
+ {
+ auto message_id_iterator = message.find("MessageId");
+ if (message_id_iterator == message.end())
+ {
+ BMCWEB_LOG_CRITICAL
+ << "Attempt to add error message without MessageId";
+ return;
+ }
- auto message_field_iterator = message.find("Message");
- if (message_field_iterator == message.end()) {
- BMCWEB_LOG_CRITICAL << "Attempt to add error message without Message";
- return;
- }
- // clang-format off
+ auto message_field_iterator = message.find("Message");
+ if (message_field_iterator == message.end())
+ {
+ BMCWEB_LOG_CRITICAL
+ << "Attempt to add error message without Message";
+ return;
+ }
+ // clang-format off
error = {
{"code", *message_id_iterator},
{"message", *message_field_iterator}
};
- // clang-format on
- } else {
- // More than 1 error occurred, so the message has to be generic
- error["code"] = std::string(messageVersionPrefix) + "GeneralError";
- error["message"] =
- "A general error has occurred. See ExtendedInfo for more"
- "information.";
- }
+ // clang-format on
+ }
+ else
+ {
+ // More than 1 error occurred, so the message has to be generic
+ error["code"] = std::string(messageVersionPrefix) + "GeneralError";
+ error["message"] =
+ "A general error has occurred. See ExtendedInfo for more"
+ "information.";
+ }
- // This check could technically be done in in the default construction
- // branch above, but because we need the pointer to the extended info field
- // anyway, it's more efficient to do it here.
- auto& extended_info = error[messages::messageAnnotation];
- if (!extended_info.is_array()) {
- extended_info = nlohmann::json::array();
- }
+ // This check could technically be done in in the default construction
+ // branch above, but because we need the pointer to the extended info field
+ // anyway, it's more efficient to do it here.
+ auto& extended_info = error[messages::messageAnnotation];
+ if (!extended_info.is_array())
+ {
+ extended_info = nlohmann::json::array();
+ }
- extended_info.push_back(message);
+ extended_info.push_back(message);
}
-void addMessageToJsonRoot(nlohmann::json& target,
- const nlohmann::json& message) {
- if (!target[messages::messageAnnotation].is_array()) {
- // Force object to be an array
- target[messages::messageAnnotation] = nlohmann::json::array();
- }
+void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message)
+{
+ if (!target[messages::messageAnnotation].is_array())
+ {
+ // Force object to be an array
+ target[messages::messageAnnotation] = nlohmann::json::array();
+ }
- target[messages::messageAnnotation].push_back(message);
+ target[messages::messageAnnotation].push_back(message);
}
void addMessageToJson(nlohmann::json& target, const nlohmann::json& message,
- const std::string& fieldPath) {
- nlohmann::json_pointer<nlohmann::json> extendedInfo(
- fieldPath + messages::messageAnnotation);
+ const std::string& fieldPath)
+{
+ nlohmann::json_pointer<nlohmann::json> extendedInfo(
+ fieldPath + messages::messageAnnotation);
- if (!target[extendedInfo].is_array()) {
- // Force object to be an array
- target[extendedInfo] = nlohmann::json::array();
- }
+ if (!target[extendedInfo].is_array())
+ {
+ // Force object to be an array
+ target[extendedInfo] = nlohmann::json::array();
+ }
- // Object exists and it is an array so we can just push in the message
- target[extendedInfo].push_back(message);
+ // Object exists and it is an array so we can just push in the message
+ target[extendedInfo].push_back(message);
}
/*********************************
@@ -98,17 +113,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json resourceInUse() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceInUse"},
- {"Message",
- "The change to the requested resource failed because the resource is in "
- "use or in transition."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the condition and resubmit the request if the operation "
- "failed."}};
+nlohmann::json resourceInUse()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceInUse"},
+ {"Message", "The change to the requested resource failed because the "
+ "resource is in "
+ "use or in transition."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Remove the condition and resubmit the request if the operation "
+ "failed."}};
}
/**
@@ -118,16 +134,17 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json malformedJSON() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.MalformedJSON"},
- {"Message",
- "The request body submitted was malformed JSON and could not be parsed "
- "by the receiving service."},
- {"Severity", "Critical"},
- {"Resolution",
- "Ensure that the request body is valid JSON and resubmit the request."}};
+nlohmann::json malformedJSON()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.MalformedJSON"},
+ {"Message", "The request body submitted was malformed JSON and could "
+ "not be parsed "
+ "by the receiving service."},
+ {"Severity", "Critical"},
+ {"Resolution", "Ensure that the request body is valid JSON and "
+ "resubmit the request."}};
}
/**
@@ -137,15 +154,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json resourceMissingAtURI(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceMissingAtURI"},
- {"Message", "The resource at the URI " + arg1 + " was not found."},
- {"Severity", "Critical"},
- {"Resolution",
- "Place a valid resource at the URI or correct the URI and resubmit the "
- "request."}};
+nlohmann::json resourceMissingAtURI(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceMissingAtURI"},
+ {"Message", "The resource at the URI " + arg1 + " was not found."},
+ {"Severity", "Critical"},
+ {"Resolution", "Place a valid resource at the URI or correct the URI "
+ "and resubmit the "
+ "request."}};
}
/**
@@ -157,17 +175,19 @@
*/
nlohmann::json actionParameterValueFormatError(const std::string& arg1,
const std::string& arg2,
- const std::string& arg3) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionParameterValueFormatError"},
- {"Message",
- "The value " + arg1 + " for the parameter " + arg2 + " in the action " +
- arg3 + " is of a different format than the parameter can accept."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the value for the parameter in the request body and resubmit "
- "the request if the operation failed."}};
+ const std::string& arg3)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionParameterValueFormatError"},
+ {"Message",
+ "The value " + arg1 + " for the parameter " + arg2 +
+ " in the action " + arg3 +
+ " is of a different format than the parameter can accept."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Correct the value for the parameter in the request body and resubmit "
+ "the request if the operation failed."}};
}
/**
@@ -177,17 +197,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json internalError() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.InternalError"},
- {"Message",
- "The request failed due to an internal service error. The service is "
- "still operational."},
- {"Severity", "Critical"},
- {"Resolution",
- "Resubmit the request. If the problem persists, consider resetting the "
- "service."}};
+nlohmann::json internalError()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.InternalError"},
+ {"Message",
+ "The request failed due to an internal service error. The service is "
+ "still operational."},
+ {"Severity", "Critical"},
+ {"Resolution", "Resubmit the request. If the problem persists, "
+ "consider resetting the "
+ "service."}};
}
/**
@@ -197,16 +218,17 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json unrecognizedRequestBody() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.UnrecognizedRequestBody"},
- {"Message",
- "The service detected a malformed request body that it was unable to "
- "interpret."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the request body and resubmit the request if it failed."}};
+nlohmann::json unrecognizedRequestBody()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.UnrecognizedRequestBody"},
+ {"Message",
+ "The service detected a malformed request body that it was unable to "
+ "interpret."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Correct the request body and resubmit the request if it failed."}};
}
/**
@@ -217,17 +239,18 @@
* @endinternal
*/
nlohmann::json resourceAtUriUnauthorized(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceAtUriUnauthorized"},
- {"Message", "While accessing the resource at " + arg1 +
- ", the service received an authorization error " + arg2 +
- "."},
- {"Severity", "Critical"},
- {"Resolution",
- "Ensure that the appropriate access is provided for the service in "
- "order for it to access the URI."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceAtUriUnauthorized"},
+ {"Message", "While accessing the resource at " + arg1 +
+ ", the service received an authorization error " +
+ arg2 + "."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Ensure that the appropriate access is provided for the service in "
+ "order for it to access the URI."}};
}
/**
@@ -238,17 +261,18 @@
* @endinternal
*/
nlohmann::json actionParameterUnknown(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionParameterUnknown"},
- {"Message", "The action " + arg1 +
- " was submitted with the invalid parameter " + arg2 +
- "."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the invalid parameter and resubmit the request if the "
- "operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionParameterUnknown"},
+ {"Message", "The action " + arg1 +
+ " was submitted with the invalid parameter " + arg2 +
+ "."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Correct the invalid parameter and resubmit the request if the "
+ "operation failed."}};
}
/**
@@ -258,15 +282,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json resourceCannotBeDeleted() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceCannotBeDeleted"},
- {"Message",
- "The delete request failed because the resource requested cannot be "
- "deleted."},
- {"Severity", "Critical"},
- {"Resolution", "Do not attempt to delete a non-deletable resource."}};
+nlohmann::json resourceCannotBeDeleted()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceCannotBeDeleted"},
+ {"Message",
+ "The delete request failed because the resource requested cannot be "
+ "deleted."},
+ {"Severity", "Critical"},
+ {"Resolution", "Do not attempt to delete a non-deletable resource."}};
}
/**
@@ -276,15 +301,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json propertyDuplicate(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyDuplicate"},
- {"Message", "The property " + arg1 + " was duplicated in the request."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the duplicate property from the request body and resubmit the "
- "request if the operation failed."}};
+nlohmann::json propertyDuplicate(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyDuplicate"},
+ {"Message", "The property " + arg1 + " was duplicated in the request."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Remove the duplicate property from the request body and resubmit the "
+ "request if the operation failed."}};
}
/**
@@ -294,15 +320,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json serviceTemporarilyUnavailable(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ServiceTemporarilyUnavailable"},
- {"Message", "The service is temporarily unavailable. Retry in " + arg1 +
- " seconds."},
- {"Severity", "Critical"},
- {"Resolution",
- "Wait for the indicated retry duration and retry the operation."}};
+nlohmann::json serviceTemporarilyUnavailable(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ServiceTemporarilyUnavailable"},
+ {"Message", "The service is temporarily unavailable. Retry in " +
+ arg1 + " seconds."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Wait for the indicated retry duration and retry the operation."}};
}
/**
@@ -314,17 +341,18 @@
*/
nlohmann::json resourceAlreadyExists(const std::string& arg1,
const std::string& arg2,
- const std::string& arg3) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceAlreadyExists"},
- {"Message", "The requested resource of type " + arg1 +
- " with the property " + arg2 + " with the value " + arg3 +
- " already exists."},
- {"Severity", "Critical"},
- {"Resolution",
- "Do not repeat the create operation as the resource has already been "
- "created."}};
+ const std::string& arg3)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceAlreadyExists"},
+ {"Message", "The requested resource of type " + arg1 +
+ " with the property " + arg2 + " with the value " +
+ arg3 + " already exists."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Do not repeat the create operation as the resource has already been "
+ "created."}};
}
/**
@@ -334,15 +362,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json accountForSessionNoLongerExists() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.AccountForSessionNoLongerExists"},
- {"Message",
- "The account for the current session has been removed, thus the current "
- "session has been removed as well."},
- {"Severity", "OK"},
- {"Resolution", "Attempt to connect with a valid account."}};
+nlohmann::json accountForSessionNoLongerExists()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.AccountForSessionNoLongerExists"},
+ {"Message", "The account for the current session has been removed, "
+ "thus the current "
+ "session has been removed as well."},
+ {"Severity", "OK"},
+ {"Resolution", "Attempt to connect with a valid account."}};
}
/**
@@ -352,16 +381,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json createFailedMissingReqProperties(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.CreateFailedMissingReqProperties"},
- {"Message", "The create operation failed because the required property " +
- arg1 + " was missing from the request."},
- {"Severity", "Critical"},
- {"Resolution",
- "Correct the body to include the required property with a valid value "
- "and resubmit the request if the operation failed."}};
+nlohmann::json createFailedMissingReqProperties(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.CreateFailedMissingReqProperties"},
+ {"Message",
+ "The create operation failed because the required property " + arg1 +
+ " was missing from the request."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Correct the body to include the required property with a valid value "
+ "and resubmit the request if the operation failed."}};
}
/**
@@ -372,17 +403,18 @@
* @endinternal
*/
nlohmann::json propertyValueFormatError(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyValueFormatError"},
- {"Message",
- "The value " + arg1 + " for the property " + arg2 +
- " is of a different format than the property can accept."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the value for the property in the request body and resubmit "
- "the request if the operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyValueFormatError"},
+ {"Message",
+ "The value " + arg1 + " for the property " + arg2 +
+ " is of a different format than the property can accept."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Correct the value for the property in the request body and resubmit "
+ "the request if the operation failed."}};
}
/**
@@ -393,16 +425,17 @@
* @endinternal
*/
nlohmann::json propertyValueNotInList(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyValueNotInList"},
- {"Message", "The value " + arg1 + " for the property " + arg2 +
- " is not in the list of acceptable values."},
- {"Severity", "Warning"},
- {"Resolution",
- "Choose a value from the enumeration list that the implementation can "
- "support and resubmit the request if the operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyValueNotInList"},
+ {"Message", "The value " + arg1 + " for the property " + arg2 +
+ " is not in the list of acceptable values."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Choose a value from the enumeration list that the implementation can "
+ "support and resubmit the request if the operation failed."}};
}
/**
@@ -412,16 +445,17 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json resourceAtUriInUnknownFormat(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceAtUriInUnknownFormat"},
- {"Message", "The resource at " + arg1 +
- " is in a format not recognized by the service."},
- {"Severity", "Critical"},
- {"Resolution",
- "Place an image or resource or file that is recognized by the service "
- "at the URI."}};
+nlohmann::json resourceAtUriInUnknownFormat(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceAtUriInUnknownFormat"},
+ {"Message", "The resource at " + arg1 +
+ " is in a format not recognized by the service."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Place an image or resource or file that is recognized by the service "
+ "at the URI."}};
}
/**
@@ -431,17 +465,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json serviceInUnknownState() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ServiceInUnknownState"},
- {"Message",
- "The operation failed because the service is in an unknown state and "
- "can no longer take incoming requests."},
- {"Severity", "Critical"},
- {"Resolution",
- "Restart the service and resubmit the request if the operation "
- "failed."}};
+nlohmann::json serviceInUnknownState()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ServiceInUnknownState"},
+ {"Message",
+ "The operation failed because the service is in an unknown state and "
+ "can no longer take incoming requests."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Restart the service and resubmit the request if the operation "
+ "failed."}};
}
/**
@@ -451,18 +486,19 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json eventSubscriptionLimitExceeded() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.EventSubscriptionLimitExceeded"},
- {"Message",
- "The event subscription failed due to the number of simultaneous "
- "subscriptions exceeding the limit of the implementation."},
- {"Severity", "Critical"},
- {"Resolution",
- "Reduce the number of other subscriptions before trying to establish "
- "the event subscription or increase the limit of simultaneous "
- "subscriptions (if supported)."}};
+nlohmann::json eventSubscriptionLimitExceeded()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.EventSubscriptionLimitExceeded"},
+ {"Message",
+ "The event subscription failed due to the number of simultaneous "
+ "subscriptions exceeding the limit of the implementation."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Reduce the number of other subscriptions before trying to establish "
+ "the event subscription or increase the limit of simultaneous "
+ "subscriptions (if supported)."}};
}
/**
@@ -473,16 +509,17 @@
* @endinternal
*/
nlohmann::json actionParameterMissing(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionParameterMissing"},
- {"Message", "The action " + arg1 + " requires the parameter " + arg2 +
- " to be present in the request body."},
- {"Severity", "Critical"},
- {"Resolution",
- "Supply the action with the required parameter in the request body when "
- "the request is resubmitted."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionParameterMissing"},
+ {"Message", "The action " + arg1 + " requires the parameter " + arg2 +
+ " to be present in the request body."},
+ {"Severity", "Critical"},
+ {"Resolution", "Supply the action with the required parameter in the "
+ "request body when "
+ "the request is resubmitted."}};
}
/**
@@ -492,15 +529,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json stringValueTooLong(const std::string& arg1, const int& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.StringValueTooLong"},
- {"Message", "The string " + arg1 + " exceeds the length limit " +
- std::to_string(arg2) + "."},
- {"Severity", "Warning"},
- {"Resolution",
- "Resubmit the request with an appropriate string length."}};
+nlohmann::json stringValueTooLong(const std::string& arg1, const int& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.StringValueTooLong"},
+ {"Message", "The string " + arg1 + " exceeds the length limit " +
+ std::to_string(arg2) + "."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Resubmit the request with an appropriate string length."}};
}
/**
@@ -511,16 +549,18 @@
* @endinternal
*/
nlohmann::json propertyValueTypeError(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyValueTypeError"},
- {"Message", "The value " + arg1 + " for the property " + arg2 +
- " is of a different type than the property can accept."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the value for the property in the request body and resubmit "
- "the request if the operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyValueTypeError"},
+ {"Message",
+ "The value " + arg1 + " for the property " + arg2 +
+ " is of a different type than the property can accept."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Correct the value for the property in the request body and resubmit "
+ "the request if the operation failed."}};
}
/**
@@ -531,15 +571,16 @@
* @endinternal
*/
nlohmann::json resourceNotFound(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceNotFound"},
- {"Message", "The requested resource of type " + arg1 + " named " + arg2 +
- " was not found."},
- {"Severity", "Critical"},
- {"Resolution",
- "Provide a valid resource identifier and resubmit the request."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceNotFound"},
+ {"Message", "The requested resource of type " + arg1 + " named " +
+ arg2 + " was not found."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Provide a valid resource identifier and resubmit the request."}};
}
/**
@@ -549,16 +590,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json couldNotEstablishConnection(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.CouldNotEstablishConnection"},
- {"Message", "The service failed to establish a Connection with the URI " +
- arg1 + "."},
- {"Severity", "Critical"},
- {"Resolution",
- "Ensure that the URI contains a valid and reachable node name, protocol "
- "information and other URI components."}};
+nlohmann::json couldNotEstablishConnection(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.CouldNotEstablishConnection"},
+ {"Message",
+ "The service failed to establish a Connection with the URI " + arg1 +
+ "."},
+ {"Severity", "Critical"},
+ {"Resolution", "Ensure that the URI contains a valid and reachable "
+ "node name, protocol "
+ "information and other URI components."}};
}
/**
@@ -568,17 +611,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json propertyNotWritable(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyNotWritable"},
- {"Message",
- "The property " + arg1 +
- " is a read only property and cannot be assigned a value."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the property from the request body and resubmit the request if "
- "the operation failed."}};
+nlohmann::json propertyNotWritable(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyNotWritable"},
+ {"Message",
+ "The property " + arg1 +
+ " is a read only property and cannot be assigned a value."},
+ {"Severity", "Warning"},
+ {"Resolution", "Remove the property from the request body and resubmit "
+ "the request if "
+ "the operation failed."}};
}
/**
@@ -589,16 +633,18 @@
* @endinternal
*/
nlohmann::json queryParameterValueTypeError(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.QueryParameterValueTypeError"},
- {"Message", "The value " + arg1 + " for the query parameter " + arg2 +
- " is of a different type than the parameter can accept."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the value for the query parameter in the request and resubmit "
- "the request if the operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.QueryParameterValueTypeError"},
+ {"Message",
+ "The value " + arg1 + " for the query parameter " + arg2 +
+ " is of a different type than the parameter can accept."},
+ {"Severity", "Warning"},
+ {"Resolution", "Correct the value for the query parameter in the "
+ "request and resubmit "
+ "the request if the operation failed."}};
}
/**
@@ -608,17 +654,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json serviceShuttingDown() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ServiceShuttingDown"},
- {"Message",
- "The operation failed because the service is shutting down and can no "
- "longer take incoming requests."},
- {"Severity", "Critical"},
- {"Resolution",
- "When the service becomes available, resubmit the request if the "
- "operation failed."}};
+nlohmann::json serviceShuttingDown()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ServiceShuttingDown"},
+ {"Message",
+ "The operation failed because the service is shutting down and can no "
+ "longer take incoming requests."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "When the service becomes available, resubmit the request if the "
+ "operation failed."}};
}
/**
@@ -629,18 +676,19 @@
* @endinternal
*/
nlohmann::json actionParameterDuplicate(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionParameterDuplicate"},
- {"Message",
- "The action " + arg1 +
- " was submitted with more than one value for the parameter " + arg2 +
- "."},
- {"Severity", "Warning"},
- {"Resolution",
- "Resubmit the action with only one instance of the parameter in the "
- "request body if the operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionParameterDuplicate"},
+ {"Message",
+ "The action " + arg1 +
+ " was submitted with more than one value for the parameter " +
+ arg2 + "."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Resubmit the action with only one instance of the parameter in the "
+ "request body if the operation failed."}};
}
/**
@@ -651,16 +699,17 @@
* @endinternal
*/
nlohmann::json actionParameterNotSupported(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionParameterNotSupported"},
- {"Message", "The parameter " + arg1 + " for the action " + arg2 +
- " is not supported on the target resource."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the parameter supplied and resubmit the request if the "
- "operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionParameterNotSupported"},
+ {"Message", "The parameter " + arg1 + " for the action " + arg2 +
+ " is not supported on the target resource."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Remove the parameter supplied and resubmit the request if the "
+ "operation failed."}};
}
/**
@@ -671,14 +720,16 @@
* @endinternal
*/
nlohmann::json sourceDoesNotSupportProtocol(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.SourceDoesNotSupportProtocol"},
- {"Message", "The other end of the Connection at " + arg1 +
- " does not support the specified protocol " + arg2 + "."},
- {"Severity", "Critical"},
- {"Resolution", "Change protocols or URIs. "}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.SourceDoesNotSupportProtocol"},
+ {"Message", "The other end of the Connection at " + arg1 +
+ " does not support the specified protocol " + arg2 +
+ "."},
+ {"Severity", "Critical"},
+ {"Resolution", "Change protocols or URIs. "}};
}
/**
@@ -688,13 +739,14 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json accountRemoved() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.AccountRemoved"},
- {"Message", "The account was successfully removed."},
- {"Severity", "OK"},
- {"Resolution", "No resolution is required."}};
+nlohmann::json accountRemoved()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.AccountRemoved"},
+ {"Message", "The account was successfully removed."},
+ {"Severity", "OK"},
+ {"Resolution", "No resolution is required."}};
}
/**
@@ -704,16 +756,17 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json accessDenied(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.AccessDenied"},
- {"Message", "While attempting to establish a Connection to " + arg1 +
- ", the service denied access."},
- {"Severity", "Critical"},
- {"Resolution",
- "Attempt to ensure that the URI is correct and that the service has the "
- "appropriate credentials."}};
+nlohmann::json accessDenied(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.AccessDenied"},
+ {"Message", "While attempting to establish a Connection to " + arg1 +
+ ", the service denied access."},
+ {"Severity", "Critical"},
+ {"Resolution", "Attempt to ensure that the URI is correct and that the "
+ "service has the "
+ "appropriate credentials."}};
}
/**
@@ -723,15 +776,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json queryNotSupported() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.QueryNotSupported"},
- {"Message", "Querying is not supported by the implementation."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the query parameters and resubmit the request if the operation "
- "failed."}};
+nlohmann::json queryNotSupported()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.QueryNotSupported"},
+ {"Message", "Querying is not supported by the implementation."},
+ {"Severity", "Warning"},
+ {"Resolution", "Remove the query parameters and resubmit the request "
+ "if the operation "
+ "failed."}};
}
/**
@@ -741,17 +795,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json createLimitReachedForResource() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.CreateLimitReachedForResource"},
- {"Message",
- "The create operation failed because the resource has reached the limit "
- "of possible resources."},
- {"Severity", "Critical"},
- {"Resolution",
- "Either delete resources and resubmit the request if the operation "
- "failed or do not resubmit the request."}};
+nlohmann::json createLimitReachedForResource()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.CreateLimitReachedForResource"},
+ {"Message", "The create operation failed because the resource has "
+ "reached the limit "
+ "of possible resources."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Either delete resources and resubmit the request if the operation "
+ "failed or do not resubmit the request."}};
}
/**
@@ -761,14 +816,15 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json generalError() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.GeneralError"},
- {"Message",
- "A general error has occurred. See ExtendedInfo for more information."},
- {"Severity", "Critical"},
- {"Resolution", "See ExtendedInfo for more information."}};
+nlohmann::json generalError()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.GeneralError"},
+ {"Message", "A general error has occurred. See ExtendedInfo for more "
+ "information."},
+ {"Severity", "Critical"},
+ {"Resolution", "See ExtendedInfo for more information."}};
}
/**
@@ -778,13 +834,14 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json success() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.Success"},
- {"Message", "Successfully Completed Request"},
- {"Severity", "OK"},
- {"Resolution", "None"}};
+nlohmann::json success()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.Success"},
+ {"Message", "Successfully Completed Request"},
+ {"Severity", "OK"},
+ {"Resolution", "None"}};
}
/**
@@ -794,13 +851,14 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json created() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.Created"},
- {"Message", "The resource has been created successfully"},
- {"Severity", "OK"},
- {"Resolution", "None"}};
+nlohmann::json created()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.Created"},
+ {"Message", "The resource has been created successfully"},
+ {"Severity", "OK"},
+ {"Resolution", "None"}};
}
/**
@@ -810,17 +868,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json propertyUnknown(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyUnknown"},
- {"Message",
- "The property " + arg1 +
- " is not in the list of valid properties for the resource."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the unknown property from the request body and resubmit the "
- "request if the operation failed."}};
+nlohmann::json propertyUnknown(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyUnknown"},
+ {"Message",
+ "The property " + arg1 +
+ " is not in the list of valid properties for the resource."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Remove the unknown property from the request body and resubmit the "
+ "request if the operation failed."}};
}
/**
@@ -830,14 +889,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json noValidSession() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.NoValidSession"},
- {"Message",
- "There is no valid session established with the implementation."},
- {"Severity", "Critical"},
- {"Resolution", "Establish as session before attempting any operations."}};
+nlohmann::json noValidSession()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.NoValidSession"},
+ {"Message",
+ "There is no valid session established with the implementation."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Establish as session before attempting any operations."}};
}
/**
@@ -847,15 +908,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json invalidObject(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.InvalidObject"},
- {"Message", "The object at " + arg1 + " is invalid."},
- {"Severity", "Critical"},
- {"Resolution",
- "Either the object is malformed or the URI is not correct. Correct the "
- "condition and resubmit the request if it failed."}};
+nlohmann::json invalidObject(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.InvalidObject"},
+ {"Message", "The object at " + arg1 + " is invalid."},
+ {"Severity", "Critical"},
+ {"Resolution", "Either the object is malformed or the URI is not "
+ "correct. Correct the "
+ "condition and resubmit the request if it failed."}};
}
/**
@@ -865,17 +927,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json resourceInStandby() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceInStandby"},
- {"Message",
- "The request could not be performed because the resource is in "
- "standby."},
- {"Severity", "Critical"},
- {"Resolution",
- "Ensure that the resource is in the correct power state and resubmit "
- "the request."}};
+nlohmann::json resourceInStandby()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceInStandby"},
+ {"Message",
+ "The request could not be performed because the resource is in "
+ "standby."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Ensure that the resource is in the correct power state and resubmit "
+ "the request."}};
}
/**
@@ -887,17 +950,19 @@
*/
nlohmann::json actionParameterValueTypeError(const std::string& arg1,
const std::string& arg2,
- const std::string& arg3) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionParameterValueTypeError"},
- {"Message", "The value " + arg1 + " for the parameter " + arg2 +
- " in the action " + arg3 +
- " is of a different type than the parameter can accept."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the value for the parameter in the request body and resubmit "
- "the request if the operation failed."}};
+ const std::string& arg3)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionParameterValueTypeError"},
+ {"Message",
+ "The value " + arg1 + " for the parameter " + arg2 +
+ " in the action " + arg3 +
+ " is of a different type than the parameter can accept."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Correct the value for the parameter in the request body and resubmit "
+ "the request if the operation failed."}};
}
/**
@@ -907,18 +972,19 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json sessionLimitExceeded() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.SessionLimitExceeded"},
- {"Message",
- "The session establishment failed due to the number of simultaneous "
- "sessions exceeding the limit of the implementation."},
- {"Severity", "Critical"},
- {"Resolution",
- "Reduce the number of other sessions before trying to establish the "
- "session or increase the limit of simultaneous sessions (if "
- "supported)."}};
+nlohmann::json sessionLimitExceeded()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.SessionLimitExceeded"},
+ {"Message",
+ "The session establishment failed due to the number of simultaneous "
+ "sessions exceeding the limit of the implementation."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Reduce the number of other sessions before trying to establish the "
+ "session or increase the limit of simultaneous sessions (if "
+ "supported)."}};
}
/**
@@ -928,16 +994,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json actionNotSupported(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ActionNotSupported"},
- {"Message", "The action " + arg1 + " is not supported by the resource."},
- {"Severity", "Critical"},
- {"Resolution",
- "The action supplied cannot be resubmitted to the implementation. "
- "Perhaps the action was invalid, the wrong resource was the target or "
- "the implementation documentation may be of assistance."}};
+nlohmann::json actionNotSupported(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ActionNotSupported"},
+ {"Message",
+ "The action " + arg1 + " is not supported by the resource."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "The action supplied cannot be resubmitted to the implementation. "
+ "Perhaps the action was invalid, the wrong resource was the target or "
+ "the implementation documentation may be of assistance."}};
}
/**
@@ -947,15 +1015,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json invalidIndex(const int& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.InvalidIndex"},
- {"Message", "The index " + std::to_string(arg1) +
- " is not a valid offset into the array."},
- {"Severity", "Warning"},
- {"Resolution",
- "Verify the index value provided is within the bounds of the array."}};
+nlohmann::json invalidIndex(const int& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.InvalidIndex"},
+ {"Message", "The index " + std::to_string(arg1) +
+ " is not a valid offset into the array."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Verify the index value provided is within the bounds of the array."}};
}
/**
@@ -965,16 +1034,17 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json emptyJSON() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.EmptyJSON"},
- {"Message",
- "The request body submitted contained an empty JSON object and the "
- "service is unable to process it."},
- {"Severity", "Warning"},
- {"Resolution",
- "Add properties in the JSON object and resubmit the request."}};
+nlohmann::json emptyJSON()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.EmptyJSON"},
+ {"Message",
+ "The request body submitted contained an empty JSON object and the "
+ "service is unable to process it."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Add properties in the JSON object and resubmit the request."}};
}
/**
@@ -984,15 +1054,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json queryNotSupportedOnResource() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.QueryNotSupportedOnResource"},
- {"Message", "Querying is not supported on the requested resource."},
- {"Severity", "Warning"},
- {"Resolution",
- "Remove the query parameters and resubmit the request if the operation "
- "failed."}};
+nlohmann::json queryNotSupportedOnResource()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.QueryNotSupportedOnResource"},
+ {"Message", "Querying is not supported on the requested resource."},
+ {"Severity", "Warning"},
+ {"Resolution", "Remove the query parameters and resubmit the request "
+ "if the operation "
+ "failed."}};
}
/**
@@ -1002,18 +1073,19 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json insufficientPrivilege() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.InsufficientPrivilege"},
- {"Message",
- "There are insufficient privileges for the account or credentials "
- "associated with the current session to perform the requested "
- "operation."},
- {"Severity", "Critical"},
- {"Resolution",
- "Either abandon the operation or change the associated access rights "
- "and resubmit the request if the operation failed."}};
+nlohmann::json insufficientPrivilege()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.InsufficientPrivilege"},
+ {"Message",
+ "There are insufficient privileges for the account or credentials "
+ "associated with the current session to perform the requested "
+ "operation."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Either abandon the operation or change the associated access rights "
+ "and resubmit the request if the operation failed."}};
}
/**
@@ -1024,14 +1096,15 @@
* @endinternal
*/
nlohmann::json propertyValueModified(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyValueModified"},
- {"Message", "The property " + arg1 + " was assigned the value " + arg2 +
- " due to modification by the service."},
- {"Severity", "Warning"},
- {"Resolution", "No resolution is required."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyValueModified"},
+ {"Message", "The property " + arg1 + " was assigned the value " + arg2 +
+ " due to modification by the service."},
+ {"Severity", "Warning"},
+ {"Resolution", "No resolution is required."}};
}
/**
@@ -1041,15 +1114,16 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json accountNotModified() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.AccountNotModified"},
- {"Message", "The account modification request failed."},
- {"Severity", "Warning"},
- {"Resolution",
- "The modification may have failed due to permission issues or issues "
- "with the request body."}};
+nlohmann::json accountNotModified()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.AccountNotModified"},
+ {"Message", "The account modification request failed."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "The modification may have failed due to permission issues or issues "
+ "with the request body."}};
}
/**
@@ -1060,17 +1134,18 @@
* @endinternal
*/
nlohmann::json queryParameterValueFormatError(const std::string& arg1,
- const std::string& arg2) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.QueryParameterValueFormatError"},
- {"Message",
- "The value " + arg1 + " for the parameter " + arg2 +
- " is of a different format than the parameter can accept."},
- {"Severity", "Warning"},
- {"Resolution",
- "Correct the value for the query parameter in the request and resubmit "
- "the request if the operation failed."}};
+ const std::string& arg2)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.QueryParameterValueFormatError"},
+ {"Message",
+ "The value " + arg1 + " for the parameter " + arg2 +
+ " is of a different format than the parameter can accept."},
+ {"Severity", "Warning"},
+ {"Resolution", "Correct the value for the query parameter in the "
+ "request and resubmit "
+ "the request if the operation failed."}};
}
/**
@@ -1080,17 +1155,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json propertyMissing(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.PropertyMissing"},
- {"Message",
- "The property " + arg1 +
- " is a required property and must be included in the request."},
- {"Severity", "Warning"},
- {"Resolution",
- "Ensure that the property is in the request body and has a valid value "
- "and resubmit the request if the operation failed."}};
+nlohmann::json propertyMissing(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.PropertyMissing"},
+ {"Message",
+ "The property " + arg1 +
+ " is a required property and must be included in the request."},
+ {"Severity", "Warning"},
+ {"Resolution", "Ensure that the property is in the request body and "
+ "has a valid value "
+ "and resubmit the request if the operation failed."}};
}
/**
@@ -1100,17 +1176,18 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json resourceExhaustion(const std::string& arg1) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.ResourceExhaustion"},
- {"Message", "The resource " + arg1 +
- " was unable to satisfy the request "
- "due to unavailability of "
- "resources."},
- {"Severity", "Critical"},
- {"Resolution",
- "Ensure that the resources are available and resubmit the request."}};
+nlohmann::json resourceExhaustion(const std::string& arg1)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.ResourceExhaustion"},
+ {"Message", "The resource " + arg1 +
+ " was unable to satisfy the request "
+ "due to unavailability of "
+ "resources."},
+ {"Severity", "Critical"},
+ {"Resolution",
+ "Ensure that the resources are available and resubmit the request."}};
}
/**
@@ -1120,13 +1197,14 @@
* See header file for more information
* @endinternal
*/
-nlohmann::json accountModified() {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.AccountModified"},
- {"Message", "The account was successfully modified."},
- {"Severity", "OK"},
- {"Resolution", "No resolution is required."}};
+nlohmann::json accountModified()
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.AccountModified"},
+ {"Message", "The account was successfully modified."},
+ {"Severity", "OK"},
+ {"Resolution", "No resolution is required."}};
}
/**
@@ -1138,24 +1216,26 @@
*/
nlohmann::json queryParameterOutOfRange(const std::string& arg1,
const std::string& arg2,
- const std::string& arg3) {
- return nlohmann::json{
- {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
- {"MessageId", "Base.1.2.0.QueryParameterOutOfRange"},
- {"Message", "The value " + arg1 + " for the query parameter " + arg2 +
- " is out of range " + arg3 + "."},
- {"Severity", "Warning"},
- {"Resolution",
- "Reduce the value for the query parameter to a value that is within "
- "range, such as a start or count value that is within bounds of the "
- "number of resources in a collection or a page that is within the range "
- "of valid pages."}};
+ const std::string& arg3)
+{
+ return nlohmann::json{
+ {"@odata.type", "/redfish/v1/$metadata#Message.v1_0_0.Message"},
+ {"MessageId", "Base.1.2.0.QueryParameterOutOfRange"},
+ {"Message", "The value " + arg1 + " for the query parameter " + arg2 +
+ " is out of range " + arg3 + "."},
+ {"Severity", "Warning"},
+ {"Resolution",
+ "Reduce the value for the query parameter to a value that is within "
+ "range, such as a start or count value that is within bounds of the "
+ "number of resources in a collection or a page that is within the "
+ "range "
+ "of valid pages."}};
}
/*********************************
* AUTOGENERATED FUNCTIONS END *
*********************************/
-} // namespace messages
+} // namespace messages
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/src/utils/json_utils.cpp b/redfish-core/src/utils/json_utils.cpp
index 5d81c21..868601f 100644
--- a/redfish-core/src/utils/json_utils.cpp
+++ b/redfish-core/src/utils/json_utils.cpp
@@ -14,440 +14,512 @@
// limitations under the License.
*/
#include "utils/json_utils.hpp"
+
#include <error_messages.hpp>
-namespace redfish {
+namespace redfish
+{
-namespace json_util {
+namespace json_util
+{
Result getString(const char* fieldName, const nlohmann::json& json,
- const std::string*& output) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ const std::string*& output)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- output = fieldIt->get_ptr<const std::string*>();
+ output = fieldIt->get_ptr<const std::string*>();
- // Verify type - we know that it exists, so nullptr means wrong type
- if (output == nullptr) {
- return Result::WRONG_TYPE;
- }
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (output == nullptr)
+ {
+ return Result::WRONG_TYPE;
+ }
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getObject(const char* fieldName, const nlohmann::json& json,
- nlohmann::json* output) {
- // Verify input pointer
- if (output == nullptr) {
- return Result::NULL_POINTER;
- }
+ nlohmann::json* output)
+{
+ // Verify input pointer
+ if (output == nullptr)
+ {
+ return Result::NULL_POINTER;
+ }
- // Find field
- auto fieldIt = json.find(fieldName);
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- // Verify type
- if (!fieldIt->is_object()) {
- return Result::WRONG_TYPE;
- }
+ // Verify type
+ if (!fieldIt->is_object())
+ {
+ return Result::WRONG_TYPE;
+ }
- // Extract value
- *output = *fieldIt;
+ // Extract value
+ *output = *fieldIt;
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getArray(const char* fieldName, const nlohmann::json& json,
- nlohmann::json* output) {
- // Verify input pointer
- if (output == nullptr) {
- return Result::NULL_POINTER;
- }
+ nlohmann::json* output)
+{
+ // Verify input pointer
+ if (output == nullptr)
+ {
+ return Result::NULL_POINTER;
+ }
- // Find field
- auto fieldIt = json.find(fieldName);
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- // Verify type
- if (!fieldIt->is_array()) {
- return Result::WRONG_TYPE;
- }
+ // Verify type
+ if (!fieldIt->is_array())
+ {
+ return Result::WRONG_TYPE;
+ }
- // Extract value
- *output = *fieldIt;
+ // Extract value
+ *output = *fieldIt;
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getInt(const char* fieldName, const nlohmann::json& json,
- int64_t& output) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ int64_t& output)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
+ const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- return Result::WRONG_TYPE;
- }
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ return Result::WRONG_TYPE;
+ }
- // Extract value
- output = *retVal;
+ // Extract value
+ output = *retVal;
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getUnsigned(const char* fieldName, const nlohmann::json& json,
- uint64_t& output) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ uint64_t& output)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
+ const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- return Result::WRONG_TYPE;
- }
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ return Result::WRONG_TYPE;
+ }
- // Extract value
- output = *retVal;
+ // Extract value
+ output = *retVal;
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
-Result getBool(const char* fieldName, const nlohmann::json& json,
- bool& output) {
- // Find field
- auto fieldIt = json.find(fieldName);
+Result getBool(const char* fieldName, const nlohmann::json& json, bool& output)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- const bool* retVal = fieldIt->get_ptr<const bool*>();
+ const bool* retVal = fieldIt->get_ptr<const bool*>();
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- return Result::WRONG_TYPE;
- }
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ return Result::WRONG_TYPE;
+ }
- // Extract value
- output = *retVal;
+ // Extract value
+ output = *retVal;
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getDouble(const char* fieldName, const nlohmann::json& json,
- double& output) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ double& output)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- return Result::NOT_EXIST;
- }
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ return Result::NOT_EXIST;
+ }
- const double* retVal = fieldIt->get_ptr<const double*>();
+ const double* retVal = fieldIt->get_ptr<const double*>();
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- return Result::WRONG_TYPE;
- }
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ return Result::WRONG_TYPE;
+ }
- // Extract value
- output = *retVal;
+ // Extract value
+ output = *retVal;
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getString(const char* fieldName, const nlohmann::json& json,
const std::string*& output, uint8_t msgCfgMap,
- nlohmann::json& msgJson, const std::string&& fieldPath) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ nlohmann::json& msgJson, const std::string&& fieldPath)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::NOT_EXIST;
- }
+ output = fieldIt->get_ptr<const std::string*>();
- output = fieldIt->get_ptr<const std::string*>();
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (output == nullptr)
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Verify type - we know that it exists, so nullptr means wrong type
- if (output == nullptr) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ return Result::WRONG_TYPE;
}
- return Result::WRONG_TYPE;
- }
-
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getObject(const char* fieldName, const nlohmann::json& json,
nlohmann::json* output, uint8_t msgCfgMap,
- nlohmann::json& msgJson, const std::string&& fieldPath) {
- // Verify input pointer
- if (output == nullptr) {
- return Result::NULL_POINTER;
- }
-
- // Find field
- auto fieldIt = json.find(fieldName);
-
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ nlohmann::json& msgJson, const std::string&& fieldPath)
+{
+ // Verify input pointer
+ if (output == nullptr)
+ {
+ return Result::NULL_POINTER;
}
- return Result::NOT_EXIST;
- }
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify type
- if (!fieldIt->is_object()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::WRONG_TYPE;
- }
+ // Verify type
+ if (!fieldIt->is_object())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Extract value
- *output = *fieldIt;
+ return Result::WRONG_TYPE;
+ }
- return Result::SUCCESS;
+ // Extract value
+ *output = *fieldIt;
+
+ return Result::SUCCESS;
}
Result getArray(const char* fieldName, const nlohmann::json& json,
nlohmann::json* output, uint8_t msgCfgMap,
- nlohmann::json& msgJson, const std::string&& fieldPath) {
- // Verify input pointer
- if (output == nullptr) {
- return Result::NULL_POINTER;
- }
-
- // Find field
- auto fieldIt = json.find(fieldName);
-
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ nlohmann::json& msgJson, const std::string&& fieldPath)
+{
+ // Verify input pointer
+ if (output == nullptr)
+ {
+ return Result::NULL_POINTER;
}
- return Result::NOT_EXIST;
- }
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify type
- if (!fieldIt->is_array()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::WRONG_TYPE;
- }
+ // Verify type
+ if (!fieldIt->is_array())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Extract value
- *output = *fieldIt;
+ return Result::WRONG_TYPE;
+ }
- return Result::SUCCESS;
+ // Extract value
+ *output = *fieldIt;
+
+ return Result::SUCCESS;
}
Result getInt(const char* fieldName, const nlohmann::json& json,
int64_t& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
- const std::string&& fieldPath) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ const std::string&& fieldPath)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::NOT_EXIST;
- }
+ const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
- const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ return Result::WRONG_TYPE;
}
- return Result::WRONG_TYPE;
- }
+ // Extract value
+ output = *retVal;
- // Extract value
- output = *retVal;
-
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getUnsigned(const char* fieldName, const nlohmann::json& json,
uint64_t& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
- const std::string&& fieldPath) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ const std::string&& fieldPath)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::NOT_EXIST;
- }
+ const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
- const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ return Result::WRONG_TYPE;
}
- return Result::WRONG_TYPE;
- }
+ // Extract value
+ output = *retVal;
- // Extract value
- output = *retVal;
-
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getBool(const char* fieldName, const nlohmann::json& json, bool& output,
uint8_t msgCfgMap, nlohmann::json& msgJson,
- const std::string&& fieldPath) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ const std::string&& fieldPath)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::NOT_EXIST;
- }
+ const bool* retVal = fieldIt->get_ptr<const bool*>();
- const bool* retVal = fieldIt->get_ptr<const bool*>();
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ return Result::WRONG_TYPE;
}
- return Result::WRONG_TYPE;
- }
+ // Extract value
+ output = *retVal;
- // Extract value
- output = *retVal;
-
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
Result getDouble(const char* fieldName, const nlohmann::json& json,
double& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
- const std::string&& fieldPath) {
- // Find field
- auto fieldIt = json.find(fieldName);
+ const std::string&& fieldPath)
+{
+ // Find field
+ auto fieldIt = json.find(fieldName);
- // Verify existence
- if (fieldIt == json.end()) {
- if (msgCfgMap & static_cast<int>(MessageSetting::MISSING)) {
- messages::addMessageToJson(msgJson, messages::propertyMissing(fieldName),
- fieldPath);
+ // Verify existence
+ if (fieldIt == json.end())
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
+ {
+ messages::addMessageToJson(
+ msgJson, messages::propertyMissing(fieldName), fieldPath);
+ }
+
+ return Result::NOT_EXIST;
}
- return Result::NOT_EXIST;
- }
+ const double* retVal = fieldIt->get_ptr<const double*>();
- const double* retVal = fieldIt->get_ptr<const double*>();
+ // Verify type - we know that it exists, so nullptr means wrong type
+ if (retVal == nullptr)
+ {
+ if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
+ {
+ messages::addMessageToJson(
+ msgJson,
+ messages::propertyValueTypeError(fieldIt->dump(), fieldName),
+ fieldPath);
+ }
- // Verify type - we know that it exists, so nullptr means wrong type
- if (retVal == nullptr) {
- if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR)) {
- messages::addMessageToJson(
- msgJson, messages::propertyValueTypeError(fieldIt->dump(), fieldName),
- fieldPath);
+ return Result::WRONG_TYPE;
}
- return Result::WRONG_TYPE;
- }
+ // Extract value
+ output = *retVal;
- // Extract value
- output = *retVal;
-
- return Result::SUCCESS;
+ return Result::SUCCESS;
}
bool processJsonFromRequest(crow::Response& res, const crow::Request& req,
- nlohmann::json& reqJson) {
- reqJson = nlohmann::json::parse(req.body, nullptr, false);
+ nlohmann::json& reqJson)
+{
+ reqJson = nlohmann::json::parse(req.body, nullptr, false);
- if (reqJson.is_discarded()) {
- messages::addMessageToErrorJson(res.jsonValue, messages::malformedJSON());
+ if (reqJson.is_discarded())
+ {
+ messages::addMessageToErrorJson(res.jsonValue,
+ messages::malformedJSON());
- res.result(boost::beast::http::status::bad_request);
- res.end();
+ res.result(boost::beast::http::status::bad_request);
+ res.end();
- return false;
- }
+ return false;
+ }
- return true;
+ return true;
}
-} // namespace json_util
+} // namespace json_util
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/ut/privileges_test.cpp b/redfish-core/ut/privileges_test.cpp
index 92cd6c4..d857290 100644
--- a/redfish-core/ut/privileges_test.cpp
+++ b/redfish-core/ut/privileges_test.cpp
@@ -1,114 +1,127 @@
+#include "nlohmann/json.hpp"
#include "privileges.hpp"
+
#include <fstream>
#include <string>
-#include "nlohmann/json.hpp"
+
#include "gmock/gmock.h"
using namespace redfish;
-TEST(PrivilegeTest, PrivilegeConstructor) {
- Privileges privileges{"Login", "ConfigureManager"};
+TEST(PrivilegeTest, PrivilegeConstructor)
+{
+ Privileges privileges{"Login", "ConfigureManager"};
- EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
- ::testing::UnorderedElementsAre(
- ::testing::Pointee(&"Login"[0]),
- ::testing::Pointee(&"ConfigureManager"[0])));
+ EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+ ::testing::UnorderedElementsAre(
+ ::testing::Pointee(&"Login"[0]),
+ ::testing::Pointee(&"ConfigureManager"[0])));
}
-TEST(PrivilegeTest, PrivilegeCheckForNoPrivilegesRequired) {
- Privileges userPrivileges{"Login"};
+TEST(PrivilegeTest, PrivilegeCheckForNoPrivilegesRequired)
+{
+ Privileges userPrivileges{"Login"};
- OperationMap entityPrivileges{{boost::beast::http::verb::get, {{"Login"}}}};
+ OperationMap entityPrivileges{{boost::beast::http::verb::get, {{"Login"}}}};
- EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_TRUE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, PrivilegeCheckForSingleCaseSuccess) {
- auto userPrivileges = Privileges{"Login"};
- OperationMap entityPrivileges{{boost::beast::http::verb::get, {}}};
+TEST(PrivilegeTest, PrivilegeCheckForSingleCaseSuccess)
+{
+ auto userPrivileges = Privileges{"Login"};
+ OperationMap entityPrivileges{{boost::beast::http::verb::get, {}}};
- EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_TRUE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, PrivilegeCheckForSingleCaseFailure) {
- auto userPrivileges = Privileges{"Login"};
- OperationMap entityPrivileges{
- {boost::beast::http::verb::get, {{"ConfigureManager"}}}};
+TEST(PrivilegeTest, PrivilegeCheckForSingleCaseFailure)
+{
+ auto userPrivileges = Privileges{"Login"};
+ OperationMap entityPrivileges{
+ {boost::beast::http::verb::get, {{"ConfigureManager"}}}};
- EXPECT_FALSE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_FALSE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, PrivilegeCheckForANDCaseSuccess) {
- auto userPrivileges =
- Privileges{"Login", "ConfigureManager", "ConfigureSelf"};
- OperationMap entityPrivileges{
- {boost::beast::http::verb::get,
- {{"Login", "ConfigureManager", "ConfigureSelf"}}}};
+TEST(PrivilegeTest, PrivilegeCheckForANDCaseSuccess)
+{
+ auto userPrivileges =
+ Privileges{"Login", "ConfigureManager", "ConfigureSelf"};
+ OperationMap entityPrivileges{
+ {boost::beast::http::verb::get,
+ {{"Login", "ConfigureManager", "ConfigureSelf"}}}};
- EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_TRUE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, PrivilegeCheckForANDCaseFailure) {
- auto userPrivileges = Privileges{"Login", "ConfigureManager"};
- OperationMap entityPrivileges{
- {boost::beast::http::verb::get,
- {{"Login", "ConfigureManager", "ConfigureSelf"}}}};
+TEST(PrivilegeTest, PrivilegeCheckForANDCaseFailure)
+{
+ auto userPrivileges = Privileges{"Login", "ConfigureManager"};
+ OperationMap entityPrivileges{
+ {boost::beast::http::verb::get,
+ {{"Login", "ConfigureManager", "ConfigureSelf"}}}};
- EXPECT_FALSE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_FALSE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, PrivilegeCheckForORCaseSuccess) {
- auto userPrivileges = Privileges{"ConfigureManager"};
- OperationMap entityPrivileges{
- {boost::beast::http::verb::get, {{"Login"}, {"ConfigureManager"}}}};
+TEST(PrivilegeTest, PrivilegeCheckForORCaseSuccess)
+{
+ auto userPrivileges = Privileges{"ConfigureManager"};
+ OperationMap entityPrivileges{
+ {boost::beast::http::verb::get, {{"Login"}, {"ConfigureManager"}}}};
- EXPECT_TRUE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_TRUE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, PrivilegeCheckForORCaseFailure) {
- auto userPrivileges = Privileges{"ConfigureComponents"};
- OperationMap entityPrivileges = OperationMap(
- {{boost::beast::http::verb::get, {{"Login"}, {"ConfigureManager"}}}});
+TEST(PrivilegeTest, PrivilegeCheckForORCaseFailure)
+{
+ auto userPrivileges = Privileges{"ConfigureComponents"};
+ OperationMap entityPrivileges = OperationMap(
+ {{boost::beast::http::verb::get, {{"Login"}, {"ConfigureManager"}}}});
- EXPECT_FALSE(isMethodAllowedWithPrivileges(boost::beast::http::verb::get,
- entityPrivileges, userPrivileges));
+ EXPECT_FALSE(isMethodAllowedWithPrivileges(
+ boost::beast::http::verb::get, entityPrivileges, userPrivileges));
}
-TEST(PrivilegeTest, DefaultPrivilegeBitsetsAreEmpty) {
- Privileges privileges;
+TEST(PrivilegeTest, DefaultPrivilegeBitsetsAreEmpty)
+{
+ Privileges privileges;
- EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
- ::testing::IsEmpty());
+ EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+ ::testing::IsEmpty());
- EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::OEM),
- ::testing::IsEmpty());
+ EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::OEM),
+ ::testing::IsEmpty());
}
-TEST(PrivilegeTest, GetActivePrivilegeNames) {
- Privileges privileges;
+TEST(PrivilegeTest, GetActivePrivilegeNames)
+{
+ Privileges privileges;
- EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
- ::testing::IsEmpty());
+ EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+ ::testing::IsEmpty());
- std::array<const char*, 5> expectedPrivileges{
- "Login", "ConfigureManager", "ConfigureUsers", "ConfigureComponents",
- "ConfigureSelf"};
+ std::array<const char*, 5> expectedPrivileges{
+ "Login", "ConfigureManager", "ConfigureUsers", "ConfigureComponents",
+ "ConfigureSelf"};
- for (const auto& privilege : expectedPrivileges) {
- EXPECT_TRUE(privileges.setSinglePrivilege(privilege));
- }
+ for (const auto& privilege : expectedPrivileges)
+ {
+ EXPECT_TRUE(privileges.setSinglePrivilege(privilege));
+ }
- EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
- ::testing::UnorderedElementsAre(
- ::testing::Pointee(expectedPrivileges[0]),
- ::testing::Pointee(expectedPrivileges[1]),
- ::testing::Pointee(expectedPrivileges[2]),
- ::testing::Pointee(expectedPrivileges[3]),
- ::testing::Pointee(expectedPrivileges[4])));
+ EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+ ::testing::UnorderedElementsAre(
+ ::testing::Pointee(expectedPrivileges[0]),
+ ::testing::Pointee(expectedPrivileges[1]),
+ ::testing::Pointee(expectedPrivileges[2]),
+ ::testing::Pointee(expectedPrivileges[3]),
+ ::testing::Pointee(expectedPrivileges[4])));
}