summaryrefslogtreecommitdiff
path: root/redfish-core/lib
diff options
context:
space:
mode:
Diffstat (limited to 'redfish-core/lib')
-rw-r--r--redfish-core/lib/account_service.hpp69
-rw-r--r--redfish-core/lib/chassis.hpp415
-rw-r--r--redfish-core/lib/ethernet.hpp3448
-rw-r--r--redfish-core/lib/managers.hpp182
-rw-r--r--redfish-core/lib/network_protocol.hpp311
-rw-r--r--redfish-core/lib/redfish_sessions.hpp604
-rw-r--r--redfish-core/lib/roles.hpp134
-rw-r--r--redfish-core/lib/sensors.hpp788
-rw-r--r--redfish-core/lib/service_root.hpp99
-rw-r--r--redfish-core/lib/systems.hpp1431
-rw-r--r--redfish-core/lib/thermal.hpp75
-rw-r--r--redfish-core/lib/update_service.hpp771
12 files changed, 4589 insertions, 3738 deletions
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 47b4c4c7b6..c58cafd633 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 b1c20a538a..7b68a270ad 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 @@ using PropertiesType = boost::container::flat_map<std::string, VariantType>;
* 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> &params) 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> &params) 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";
-
- 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 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";
- private:
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> &params) 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> &params) 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;
+ }
+
+ 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;
+ }
- // Couldn't find an object with that name. return an error
- res.result(boost::beast::http::status::not_found);
+ // Couldn't find an object with that name. return an error
+ res.result(boost::beast::http::status::not_found);
- 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"});
- }
+ 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"});
+ }
- // Chassis Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandChassisProvider chassisProvider;
-}; // namespace redfish
+ // Chassis Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandChassisProvider chassisProvider;
+}; // namespace redfish
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 01111a4e5f..0c642798b5 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 @@ using GetManagedObjectsType = boost::container::flat_map<
* 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 @@ struct EthernetInterfaceData {
* 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;
-
- // 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;
- }
+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;
}
- 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);
+
+ // 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);
}
- 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 &ethifaceId,
- const GetManagedObjectsType &dbus_data,
- EthernetInterfaceData &eth_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");
+
+ // 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 &ethifaceId,
+ const GetManagedObjectsType &dbus_data,
+ EthernetInterfaceData &eth_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);
+ 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");
- }
+ 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);
+ // 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");
+ }
- 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");
+ }
}
- // 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 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 &ethifaceId,
- 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 extracts data for single ethernet ipv4 address
+ void extractIPv4Data(const std::string &ethifaceId,
+ 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));
+ }
+ }
}
- 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:
/**
- * 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 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.
*/
- 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;
- }
+ 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));
+ };
- if (bits != nullptr) {
- *bits = 0;
- }
+ /**
+ * @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("."));
- 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;
+ if (bytesInMask.size() != ipV4AddressSectionsCount)
+ {
+ 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)++;
+ 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;
}
- } else {
- firstZeroInByteHit = true;
- }
+
+ 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;
}
- }
- previousValue = value;
+ return true;
}
- 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;
- }
+ /**
+ * @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));
};
- 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;
- }
+ /**
+ * @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));
};
- 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;
- }
+ /**
+ * @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));
};
- 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) + "/");
- }
+ /**
+ * @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");
};
- 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 "";
+ /**
+ * @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");
}
- 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;
+ /**
+ * @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);
}
- // 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 &ethifaceId,
- 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;
- }
+ /**
+ * @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 "";
+ }
- // Find interface
- if (resp.find("/xyz/openbmc_project/network/" + ethifaceId) ==
- resp.end()) {
- // Interface has not been found
- callback(false, ethData, ipv4Data);
- 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;
+ }
- extractEthernetInterfaceData(ethifaceId, resp, ethData);
- extractIPv4Data(ethifaceId, resp, ipv4Data);
+ // If we are still here, that means that value has not been found
+ return "";
+ }
- // 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));
+ /**
+ * 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 &ethifaceId,
+ 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;
}
- }
- }
- }
- // Finally make a callback with useful data
- callback(true, ifaceList);
- },
- "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
- "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
- };
+
+ // 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> &params) 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();
- });
- }
-
- // Ethernet Provider object
- // TODO(Pawel) consider move it to singleton
- OnDemandEthernetProvider ethernetProvider;
+ "/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> &params) 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";
-
- 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 &eth_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;
+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"}}}};
}
- const std::string pathStart = (pathPrefix == "/") ? "" : pathPrefix;
- nlohmann::json &paramsJson =
- (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;
- }
+ // TODO(kkowalsk) Find a suitable class/namespace for this
+ static void handleVlanPatch(const std::string &ifaceId,
+ const nlohmann::json &input,
+ const EthernetInterfaceData &eth_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;
+ }
- // 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;
- }
- }
+ const std::string pathStart = (pathPrefix == "/") ? "" : pathPrefix;
+ nlohmann::json &paramsJson =
+ (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;
+ }
- // Do not proceed if input has not been valid
- if (inputInvalid) {
- 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);
- // 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;
+ inputInvalid = true;
+ }
+ else
+ {
+ // Load actual data into field values if they were not provided
+ if (inputVlanEnabledState == json_util::Result::NOT_EXIST)
+ {
+ inputVlanEnabled = 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;
+
+ if (inputVlanIdState == json_util::Result::NOT_EXIST)
+ {
+ inputVlanId = *eth_data.vlanId;
}
- });
- }
- }
+ }
- private:
- void handleHostnamePatch(const nlohmann::json &input,
- const EthernetInterfaceData &eth_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;
- }
+ // Do not proceed if input has not been valid
+ if (inputInvalid)
+ {
+ 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;
+ // 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;
+ }
+ });
+ }
}
- 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");
+ private:
+ void handleHostnamePatch(const nlohmann::json &input,
+ const EthernetInterfaceData &eth_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;
+ }
+ });
+ }
}
-
- if (subnetMaskFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::propertyMissing("SubnetMask"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/SubnetMask");
+ else
+ {
+ messages::addMessageToJson(
+ asyncResp->res.jsonValue,
+ messages::propertyValueTypeError(input.dump(), "HostName"),
+ "/HostName");
}
+ }
- if (addressOriginFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue,
- messages::propertyMissing("AddressOrigin"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/AddressOrigin");
+ 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;
}
- if (gatewayFieldState == json_util::Result::NOT_EXIST) {
- errorDetected = true;
- messages::addMessageToJson(
- asyncResp->res.jsonValue, messages::propertyMissing("Gateway"),
- "/IPv4Addresses/" + std::to_string(entryIdx) + "/Gateway");
+ // 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;
}
- // If any error occured do not proceed with current entry, but do not
- // end loop
- if (errorDetected) {
- errorDetected = false;
- continue;
- }
+ 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;
+ }
- // 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);
- }
+ // 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 &eth_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));
+ nlohmann::json
+ parseInterfaceData(const std::string &ifaceId,
+ const EthernetInterfaceData &eth_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";
}
- }
- 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> &params) 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;
- }
+ // ... 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);
+ }
- 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 &eth_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> &params) 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;
+ return jsonResponse;
}
- const std::string &ifaceId = params[0];
-
- nlohmann::json patchReq;
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
+ }
- if (!json_util::processJsonFromRequest(res, req, patchReq)) {
- 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 &eth_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();
+ });
}
- // 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 &eth_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);
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
- }
-
- 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()));
- }
- }
- }
- });
- }
+ }
+
+ // 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 &eth_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;
+ // Ethernet Provider object
+ // TODO(Pawel) consider move it to singleton
+ OnDemandEthernetProvider ethernetProvider;
};
class VlanNetworkInterfaceCollection;
@@ -1350,422 +1585,499 @@ class VlanNetworkInterfaceCollection;
/**
* 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";
-
- 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 &eth_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> &params) 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;
+ 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"}}}};
}
- 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 &eth_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;
- if (!verifyNames(res, parentIfaceId, ifaceId)) {
- return;
+ 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 &eth_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));
+ messages::resourceNotFound("VLAN Network Interface", iface));
res.result(boost::beast::http::status::not_found);
- }
- res.end();
- });
- }
-
- void doPatch(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> &params) override {
- if (params.size() != 2) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- return;
+ res.end();
+
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
- const std::string &parentIfaceId = params[0];
- const std::string &ifaceId = params[1];
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
+ }
- if (!verifyNames(res, parentIfaceId, ifaceId)) {
- return;
- }
+ const std::string &parentIfaceId = params[0];
+ const std::string &ifaceId = params[1];
- nlohmann::json patchReq;
+ if (!verifyNames(res, parentIfaceId, ifaceId))
+ {
+ return;
+ }
- 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](const bool &success,
+ const EthernetInterfaceData &eth_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();
+ });
}
- // 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 &eth_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);
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
- }
-
- 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> &params) override {
- if (params.size() != 2) {
- res.result(boost::beast::http::status::internal_server_error);
- res.end();
- 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 &eth_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);
+ });
}
- const std::string &parentIfaceId = params[0];
- const std::string &ifaceId = params[1];
+ void doDelete(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
+ }
- 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 &eth_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();
+ }
+ });
}
- // Get single eth interface data, and call the below callback for JSON
- // preparation
- ethernetProvider.getEthernetIfaceData(
- ifaceId, [&, parentIfaceId, ifaceId](
- const bool &success, const EthernetInterfaceData &eth_data,
- const std::vector<IPv4AddressData> &ipv4_data) {
- if (success && eth_data.vlanId != nullptr) {
- res.jsonValue =
- parseInterfaceData(parentIfaceId, ifaceId, eth_data, ipv4_data);
+ /**
+ * 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;
- // 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;
+ // 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";
-
- 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> &params) 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;
+ 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"}}}};
}
- // 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];
-
- // 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}});
- }
- }
+ private:
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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();
- 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();
+ return;
}
- } else {
- // No success, best what we can do is return INTERNALL ERROR
- res.result(boost::beast::http::status::internal_server_error);
- }
- res.end();
- });
- }
-
- void doPost(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> &params) 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];
+
+ // 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}});
+ }
+ }
+
+ 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];
- uint64_t vlanId;
- bool errorDetected;
+ void doPost(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
+ }
- 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;
- }
+ nlohmann::json postReq;
- // 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 (!json_util::processJsonFromRequest(res, req, postReq))
+ {
+ return;
}
- 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();
+ // 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;
}
- } 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;
+
+ // 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 7a861b4a3d..86fe567f3a 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"}}}};
- }
+ 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();
- }
+ 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);
+ 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, ':');
- }
+ 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;
- }
+ 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 ae29df05f6..bb021f5297 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 {
-
-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
+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 NetworkProtocolListenResponseElements {
- NET_PROTO_LISTEN_TYPE,
- NET_PROTO_LISTEN_STREAM
+enum NetworkProtocolListenResponseElements
+{
+ NET_PROTO_LISTEN_TYPE,
+ NET_PROTO_LISTEN_STREAM
};
/**
@@ -46,9 +49,10 @@ using UnitStruct =
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 @@ const static boost::container::flat_map<const char*, ServiceConfiguration>
{"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";
-
- for (auto& protocol : protocolToDBus) {
- Node::json[protocol.first]["ProtocolEnabled"] = false;
+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;
+ }
+
+ 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);
-
- 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();
+ 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);
}
- return hostName;
- }
-
- void getData(const std::shared_ptr<AsyncResp>& asyncResp) {
- Node::json["HostName"] = getHostName();
- asyncResp->res.jsonValue = Node::json;
-
- 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;
- }
-
- 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;
+ std::string getHostName() const
+ {
+ std::string hostName;
+
+ std::array<char, HOST_NAME_MAX> hostNameCStr;
+ if (gethostname(hostNameCStr.data(), hostNameCStr.size()) == 0)
+ {
+ hostName = hostNameCStr.data();
+ }
+ return hostName;
+ }
+
+ void getData(const std::shared_ptr<AsyncResp>& asyncResp)
+ {
+ Node::json["HostName"] = getHostName();
+ asyncResp->res.jsonValue = Node::json;
+
+ 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;
+ }
+
+ 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");
}
- },
- "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 ca1c3757da..2406250fa3 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";
-
- 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;
+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"}}}};
}
- Node::json["Id"] = session->uniqueId;
- Node::json["UserName"] = session->username;
- Node::json["@odata.id"] =
- "/redfish/v1/SessionService/Sessions/" + session->uniqueId;
-
- res.jsonValue = Node::json;
- res.end();
- }
-
- 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::bad_request);
- messages::addMessageToErrorJson(res.jsonValue, messages::generalError());
-
- res.end();
- return;
+ 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;
+ }
+
+ Node::json["Id"] = session->uniqueId;
+ Node::json["UserName"] = session->username;
+ Node::json["@odata.id"] =
+ "/redfish/v1/SessionService/Sessions/" + session->uniqueId;
+
+ res.jsonValue = Node::json;
+ res.end();
}
- 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;
+ 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::bad_request);
+ messages::addMessageToErrorJson(res.jsonValue,
+ messages::generalError());
+
+ 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();
-
- 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}});
+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, {}}};
}
- res.jsonValue = Node::json;
- res.end();
- }
-
- 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);
-
- if (!userAuthSuccessful) {
- res.end();
- return;
+ 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}});
+ }
+
+ 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);
-
- res.addHeader("Location",
- "/redfish/v1/SessionService/Sessions/" + session->uniqueId);
-
- // Return data for created session
- memberSession.doGet(res, req, {session->uniqueId});
-
- // No need for res.end(), as it is called by doGet()
- }
-
- /**
- * @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;
-
- // 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;
+ 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);
+
+ if (!userAuthSuccessful)
+ {
+ res.end();
+ return;
+ }
+
+ // User is authenticated - create session for him
+ auto session = crow::persistent_data::SessionStore::getInstance()
+ .generateUserSession(username);
+ res.addHeader("X-Auth-Token", session->sessionToken);
+
+ res.addHeader("Location", "/redfish/v1/SessionService/Sessions/" +
+ session->uniqueId);
+
+ // Return data for created session
+ memberSession.doGet(res, req, {session->uniqueId});
+
+ // 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;
-
- 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;
+ /**
+ * @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;
+
+ // 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;
+ }
+
+ // 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;
}
- // 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"));
- }
+ /**
+ * Member session to ensure consistency between collection's doPost and
+ * member's doGet, as they should return 100% matching data
+ */
+ Sessions memberSession;
+};
- return false;
+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"}}}};
}
- // 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;
+ private:
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+ res.jsonValue = Node::json;
+ res.end();
}
-
- // 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;
-};
-
-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"}}}};
- }
-
- 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 72d79486bb..258eed31b2 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 7f9fa684bc..c390cd7908 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 @@ using ManagedObjectsVectorType = std::vector<std::pair<
* 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();
+ }
+
+ void setErrorStatus()
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ }
- crow::Response& res;
- std::string chassisId{};
- const std::vector<const char*> types;
+ crow::Response& res;
+ std::string chassisId{};
+ const std::vector<const char*> types;
};
/**
@@ -78,70 +86,84 @@ class SensorsAsyncResp {
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"};
-
- // 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;
- }
+ 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";
+ 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);
+ // 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;
- }
+ 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);
- }
+ 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;
+ }
}
- }
- 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";
+ 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 @@ void getConnections(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
*/
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;
-
- // 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];
-
- if (chassisName != SensorsAsyncResp->chassisId) {
- split.clear();
- continue;
- }
- BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
- foundChassis = true;
- sensorNames.emplace(sensorName);
- split.clear();
+ 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);
+
+ 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();
+ };
+ 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 @@ void objectInterfacesToJson(
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";
-
- // 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));
- }
+
+ // 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;
}
- // 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));
- }
+ }
+
+ 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;
+ BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
}
/**
@@ -342,106 +404,140 @@ void objectInterfacesToJson(
* 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;
-
- 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;
- }
-
- 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();
- }
-
- 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";
+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;
+ }
+
+ 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];
+
+ // 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";
+ };
+ 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 chassis information related to sensors
- getChassis(SensorsAsyncResp, std::move(getChassisCb));
- BMCWEB_LOG_DEBUG << "getChassisData 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";
};
-} // namespace redfish
+} // namespace redfish
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 6fa9632c9b..d2c5163a8a 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();
- }
+ 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"}}}};
+ }
- const std::string getUuid() {
- // If we are using a version of systemd that can get the app specific uuid,
- // use that
+ 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;
+ 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();
+ // 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 b7f91b9916..cd49883859 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) {}
+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();
+ ~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();
}
- res.end();
- }
- void setErrorStatus() {
- res.result(boost::beast::http::status::internal_server_error);
- }
+ void setErrorStatus()
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ }
- crow::Response &res;
+ crow::Response &res;
};
/**
@@ -59,628 +67,853 @@ class SystemAsyncResp {
* 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",
- };
- 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;
+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));
}
- 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;
- }
+ }
+ // 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",
+ };
+ 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;
}
- 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;
+ }
+ 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["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);
+ 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);
- }
+ 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);
- }
+ /**
+ * @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");
- }
+ },
+ "xyz.openbmc_project.LED.GroupManager",
+ "/xyz/openbmc_project/led/groups",
+ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+ }
- 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;
+ 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;
+ }
+ }
+ }
+ }
}
- }
}
- }
- }
- }
- 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");
- }
+ 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";
- }
+ /**
+ * @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;
}
- }
- }
- }
- },
- "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()
+ << "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> &params) 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> &params) 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";
-
- 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 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";
- private:
- OnDemandSystemsProvider provider;
-
- /**
- * Functions triggers appropriate requests on DBus
- */
- void doGet(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> &params) 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;
+
+ /**
+ * Functions triggers appropriate requests on DBus
+ */
+ void doGet(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
+ }
- res.jsonValue = Node::json;
- res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
+ const std::string &name = params[0];
- auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+ res.jsonValue = Node::json;
+ res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + name;
- 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);
- }
+ auto asyncResp = std::make_shared<SystemAsyncResp>(res);
- void doPatch(crow::Response &res, const crow::Request &req,
- const std::vector<std::string> &params) 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;
- }
+ 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;
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> &params) 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;
+ }
+ }
- provider.getHostState(asyncResp);
- provider.getComputerSystem(asyncResp, name);
+ // Update led status
+ auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+ res.jsonValue = Node::json;
+ res.jsonValue["@odata.id"] = "/redfish/v1/Systems/" + 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));
+ 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 8fb291b9bb..37b0f43f3a 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 677b6d1741..658937d9a5 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"}};
-
- 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> &params) 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> &params) 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;
+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"}}}};
}
- // 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> &params) 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;
-
- 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;
+ }
+ 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> &params) 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;
}
- }
- };
-
- 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!!";
- }
-};
+ // 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;
+ }
-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> &params) 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);
- return;
- }
- asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
- asyncResp->res.jsonValue["Members@odata.count"] = 0;
-
- 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;
- }
+ res.result(boost::beast::http::status::internal_server_error);
+ res.jsonValue = redfish::messages::internalError();
+ res.end();
+ });
- 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;
+ 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;
}
- 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");
+ UpdateService::activateImage(objPath.str); // str_objpath);
+ res.jsonValue = redfish::messages::success();
+ BMCWEB_LOG_DEBUG << "ending response";
+ res.end();
+ fwUpdateMatcher = nullptr;
+ }
}
- }
- },
- "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"});
- }
+ };
+
+ 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"}}}};
- }
-
- 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);
- res.jsonValue = Node::json;
-
- if (params.size() != 1) {
- res.result(boost::beast::http::status::internal_server_error);
- res.jsonValue = messages::internalError();
- res.end();
- return;
+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"}}}};
}
- 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> &params) 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);
+ return;
+ }
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+ asyncResp->res.jsonValue["Members@odata.count"] = 0;
+
+ 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");
+ }
+ }
+ },
+ "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"});
+ }
+};
- res.jsonValue["@odata.id"] =
- "/redfish/v1/UpdateService/FirmwareInventory/" + *sw_id;
+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"}}}};
+ }
- 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);
+ 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);
+ res.jsonValue = Node::json;
+
+ if (params.size() != 1)
+ {
+ res.result(boost::beast::http::status::internal_server_error);
+ res.jsonValue = messages::internalError();
+ res.end();
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) {
+ 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;
- }
- 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;
+ }
+
+ 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;
}
- 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;
+ if (obj.second.size() <= 1)
+ {
+ continue;
}
- 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"});
- }
+
+ 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
+} // namespace redfish