Set the Hypervisor IPv4 Static IP address
This commit implements the PATCH command for setting the
Power hypervisor Virtual Management Interface's IPv4 static network.
Tested by:
1. Configure the Static IPv4 address:
PATCH -d '{"IPv4StaticAddresses": [{"Address": "<>","SubnetMask": "<>","Gateway":"<>"}]}'
https://${bmc}/redfish/v1/Systems/hypervisor/EthernetInterfaces/<id>
2. Delete the Static IPv4 address:
PATCH -d '{"IPv4StaticAddresses": [null]}'
https://${bmc}/redfish/v1/Systems/hypervisor/EthernetInterfaces/<id>
3. GET https://${bmc}/redfish/v1/Systems/hypervisor/EthernetInterfaces/<id>
Signed-off-by: Sunitha Harish <sunithaharish04@gmail.com>
Change-Id: Idacbf2dc6859314185b3521dc714925b7f14d965
diff --git a/redfish-core/lib/hypervisor_ethernet.hpp b/redfish-core/lib/hypervisor_ethernet.hpp
index 70fb423..58896d4 100644
--- a/redfish-core/lib/hypervisor_ethernet.hpp
+++ b/redfish-core/lib/hypervisor_ethernet.hpp
@@ -295,6 +295,149 @@
}
/**
+ * @brief Sets the Hypervisor Interface IPAddress DBUS
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ * @param[in] ipv4Aaddress Address from the incoming request
+ * @param[in] ethifaceId Hypervisor Interface Id
+ *
+ * @return None.
+ */
+inline void setHypervisorIPv4Address(std::shared_ptr<AsyncResp> aResp,
+ const std::string ðifaceId,
+ const std::string &ipv4Aaddress)
+{
+ BMCWEB_LOG_DEBUG << "Setting the Hypervisor IPaddress : " << ipv4Aaddress
+ << " on Iface: " << ethifaceId;
+ std::string path =
+ "/xyz/openbmc_project/network/vmi/" + ethifaceId + "/ipv4/addr0";
+ const char *vmiObj = path.c_str();
+
+ crow::connections::systemBus->async_method_call(
+ [aResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ // not an error, don't have to have the interface
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Hypervisor IPaddress is Set";
+ },
+ "xyz.openbmc_project.Settings", vmiObj,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.IP", "Address",
+ std::variant<std::string>(ipv4Aaddress));
+}
+
+/**
+ * @brief Sets the Hypervisor Interface SubnetMask DBUS
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ * @param[in] subnet SubnetMask from the incoming request
+ * @param[in] ethifaceId Hypervisor Interface Id
+ *
+ * @return None.
+ */
+inline void setHypervisorIPv4Subnet(std::shared_ptr<AsyncResp> aResp,
+ const std::string ðifaceId,
+ const uint8_t subnet)
+{
+ BMCWEB_LOG_DEBUG << "Setting the Hypervisor subnet : " << subnet
+ << " on Iface: " << ethifaceId;
+ std::string path =
+ "/xyz/openbmc_project/network/vmi/" + ethifaceId + "/ipv4/addr0";
+ const char *vmiObj = path.c_str();
+
+ crow::connections::systemBus->async_method_call(
+ [aResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ // not an error, don't have to have the interface
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "SubnetMask is Set";
+ },
+ "xyz.openbmc_project.Settings", vmiObj,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.IP", "PrefixLength",
+ std::variant<uint8_t>(subnet));
+}
+
+/**
+ * @brief Sets the Hypervisor Interface Gateway DBUS
+ *
+ * @param[in] aResp Shared pointer for generating response message.
+ * @param[in] gateway Gateway from the incoming request
+ * @param[in] ethifaceId Hypervisor Interface Id
+ *
+ * @return None.
+ */
+inline void setHypervisorIPv4Gateway(std::shared_ptr<AsyncResp> aResp,
+ const std::string ðifaceId,
+ const std::string &gateway)
+{
+ BMCWEB_LOG_DEBUG
+ << "Setting the DefaultGateway to the last configured gateway";
+
+ crow::connections::systemBus->async_method_call(
+ [aResp](const boost::system::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
+ // not an error, don't have to have the interface
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Default Gateway is Set";
+ },
+ "xyz.openbmc_project.Settings", "/xyz/openbmc_project/network/vmi",
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Network.SystemConfiguration", "DefaultGateway",
+ std::variant<std::string>(gateway));
+}
+
+/**
+ * @brief Creates a static IPv4 entry
+ *
+ * @param[in] ifaceId Id of interface upon which to create the IPv4 entry
+ * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
+ * @param[in] gateway IPv4 address of this interfaces gateway
+ * @param[in] address IPv4 address to assign to this interface
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return None
+ */
+inline void createHypervisorIPv4(const std::string &ifaceId,
+ uint8_t prefixLength,
+ const std::string &gateway,
+ const std::string &address,
+ std::shared_ptr<AsyncResp> asyncResp)
+{
+ setHypervisorIPv4Address(asyncResp, ifaceId, address);
+ setHypervisorIPv4Gateway(asyncResp, ifaceId, gateway);
+ setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength);
+}
+
+/**
+ * @brief Deletes given IPv4 interface
+ *
+ * @param[in] ifaceId Id of interface whose IP should be deleted
+ * @param[io] asyncResp Response object that will be returned to client
+ *
+ * @return None
+ */
+inline void deleteHypervisorIPv4(const std::string &ifaceId,
+ const std::shared_ptr<AsyncResp> asyncResp)
+{
+ std::string address = "0.0.0.0";
+ std::string gateway = "0.0.0.0";
+ const uint8_t prefixLength = 0;
+ setHypervisorIPv4Address(asyncResp, ifaceId, address);
+ setHypervisorIPv4Gateway(asyncResp, ifaceId, gateway);
+ setHypervisorIPv4Subnet(asyncResp, ifaceId, prefixLength);
+}
+
+/**
* HypervisorInterface derived class for delivering Ethernet Schema
*/
class HypervisorInterface : public Node
@@ -352,6 +495,110 @@
}
}
+ void handleHypervisorIPv4StaticPatch(
+ const std::string &ifaceId, nlohmann::json &&input,
+ const std::shared_ptr<AsyncResp> asyncResp)
+ {
+ if ((!input.is_array()) || input.empty())
+ {
+ messages::propertyValueTypeError(asyncResp->res, input.dump(),
+ "IPv4StaticAddresses");
+ return;
+ }
+
+ // Hypervisor considers the first IP address in the array list
+ // as the Hypervisor's virtual management interface supports single IPv4
+ // address
+ nlohmann::json &thisJson = input[0];
+
+ // For the error string
+ std::string pathString = "IPv4StaticAddresses/1";
+
+ if (!thisJson.is_null() && !thisJson.empty())
+ {
+ std::optional<std::string> address;
+ std::optional<std::string> subnetMask;
+ std::optional<std::string> gateway;
+
+ if (!json_util::readJson(thisJson, asyncResp->res, "Address",
+ address, "SubnetMask", subnetMask,
+ "Gateway", gateway))
+ {
+ messages::propertyValueFormatError(asyncResp->res,
+ thisJson.dump(), pathString);
+ return;
+ }
+
+ uint8_t prefixLength = 0;
+ bool errorInEntry = false;
+ if (address)
+ {
+ if (!ipv4VerifyIpAndGetBitcount(*address))
+ {
+ messages::propertyValueFormatError(asyncResp->res, *address,
+ pathString + "/Address");
+ errorInEntry = true;
+ }
+ }
+ else
+ {
+ messages::propertyMissing(asyncResp->res,
+ pathString + "/Address");
+ errorInEntry = true;
+ }
+
+ if (subnetMask)
+ {
+ if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength))
+ {
+ messages::propertyValueFormatError(
+ asyncResp->res, *subnetMask,
+ pathString + "/SubnetMask");
+ errorInEntry = true;
+ }
+ }
+ else
+ {
+ messages::propertyMissing(asyncResp->res,
+ pathString + "/SubnetMask");
+ errorInEntry = true;
+ }
+
+ if (gateway)
+ {
+ if (!ipv4VerifyIpAndGetBitcount(*gateway))
+ {
+ messages::propertyValueFormatError(asyncResp->res, *gateway,
+ pathString + "/Gateway");
+ errorInEntry = true;
+ }
+ }
+ else
+ {
+ messages::propertyMissing(asyncResp->res,
+ pathString + "/Gateway");
+ errorInEntry = true;
+ }
+
+ if (errorInEntry)
+ {
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "Calling createHypervisorIPv4 on : " << ifaceId
+ << "," << *address;
+ createHypervisorIPv4(ifaceId, prefixLength, *gateway, *address,
+ asyncResp);
+ }
+ else
+ {
+ if (thisJson.is_null())
+ {
+ deleteHypervisorIPv4(ifaceId, asyncResp);
+ }
+ }
+ }
+
/**
* Functions triggers appropriate requests on DBus
*/
@@ -386,5 +633,37 @@
ipv4Data);
});
}
+
+ void doPatch(crow::Response &res, const crow::Request &req,
+ const std::vector<std::string> ¶ms) override
+ {
+ std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
+ if (params.size() != 1)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const std::string &ifaceId = params[0];
+ std::optional<nlohmann::json> ipv4StaticAddresses;
+
+ if (!json_util::readJson(req, res, "IPv4StaticAddresses",
+ ipv4StaticAddresses))
+ {
+ return;
+ }
+
+ if (ipv4StaticAddresses)
+ {
+ nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses);
+ handleHypervisorIPv4StaticPatch(ifaceId, std::move(ipv4Static),
+ asyncResp);
+ }
+
+ // TODO : Task will be created for monitoring the hypervisor interface
+ // Hypervisor will notify once the IP is applied to the hypervisor.
+ // The status will be sent over to the client.
+ res.result(boost::beast::http::status::accepted);
+ }
};
} // namespace redfish