diff options
author | Sunitha Harish <sunithaharish04@gmail.com> | 2019-03-21 19:01:24 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2019-03-29 01:27:12 +0300 |
commit | fda13ad2223f3af2a7c4bedd7117ddbd38426126 (patch) | |
tree | c8916c769483cec553c1f44a1c8b821e13bce013 | |
parent | 343ff2e152b30bcc82a1bb9120ff873e8ff40e93 (diff) | |
download | bmcweb-fda13ad2223f3af2a7c4bedd7117ddbd38426126.tar.xz |
Redfish(Network): Fixes VLAN specific issues
This commit fixes the following issues. Before this fix the VLAN functionality was inconsiststant.
1)Add VLANs property to the EthernetInterface resource
2)Removed VLAN property under EthernetInterface resource
3)Made the property - VLANEnable mandatory for creating vlans (POST command)
4)Fetch the VLANId when GET on the VLAN Interface resource
5)Updated Ethernet schema to EthernetInterface.v1_4_1
6)Changed the propert name "DHCPv4Configuration" to "DHCPv4" as per the schema
Tested by:
GET https://${bmc}/redfish/v1/Managers/bmc/EthernetInterfaces/eth0
GET https://${bmc}/redfish/v1/Managers/bmc/EthernetInterfaces/eth0/VLANs
POST -D headers.txt https://${bmc}/redfish/v1/Managers/bmc/EthernetInterfaces/eth0/VLANs -d '{ "VLANId" : 30, "VLANEnable": true}'
GET https://${bmc}/redfish/v1/Managers/bmc/EthernetInterfaces/eth0/VLANs/eth0_30
Signed-off-by: Sunitha Harish <sunithaharish04@gmail.com>
Change-Id: I2339f6711cdd56fe42fee030701125492911dc26
-rw-r--r-- | redfish-core/lib/ethernet.hpp | 157 |
1 files changed, 60 insertions, 97 deletions
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp index 476e03aff2..25dff50ffb 100644 --- a/redfish-core/lib/ethernet.hpp +++ b/redfish-core/lib/ethernet.hpp @@ -82,7 +82,7 @@ struct EthernetInterfaceData std::string hostname; std::string default_gateway; std::string mac_address; - std::optional<uint32_t> vlan_id; + std::vector<std::uint32_t> vlan_id; std::vector<std::string> nameservers; }; @@ -192,7 +192,7 @@ inline void extractEthernetInterfaceData(const std::string ðiface_id, std::get_if<uint32_t>(&propertyPair.second); if (id != nullptr) { - ethData.vlan_id = *id; + ethData.vlan_id.push_back(*id); } } } @@ -669,8 +669,7 @@ inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) messages::internalError(asyncResp->res); return; } - nlohmann::json &DHCPConfigTypeJson = - asyncResp->res.jsonValue["DHCPv4Configuration"]; + nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; for (const auto &property : dbus_data) { auto value = @@ -851,12 +850,17 @@ class EthernetCollection : public Node nlohmann::json &iface_array = res.jsonValue["Members"]; iface_array = nlohmann::json::array(); + std::string tag = "_"; for (const std::string &iface_item : iface_list) { - iface_array.push_back( - {{"@odata.id", - "/redfish/v1/Managers/bmc/EthernetInterfaces/" + - iface_item}}); + std::size_t found = iface_item.find(tag); + if (found == std::string::npos) + { + iface_array.push_back( + {{"@odata.id", + "/redfish/v1/Managers/bmc/EthernetInterfaces/" + + iface_item}}); + } } res.jsonValue["Members@odata.count"] = iface_array.size(); @@ -896,15 +900,6 @@ class EthernetInterface : public Node const EthernetInterfaceData ðData, const std::shared_ptr<AsyncResp> asyncResp) { - if (!ethData.vlan_id) - { - // This interface is not a VLAN. Cannot do anything with it - // TODO(kkowalsk) Change this message - messages::propertyNotWritable(asyncResp->res, "VLANEnable"); - - return; - } - // VLAN is configured on the interface if (vlanEnable == true) { @@ -1238,25 +1233,17 @@ class EthernetInterface : public Node } json_response["SpeedMbps"] = ethData.speed; json_response["MACAddress"] = ethData.mac_address; - json_response["DHCPv4Configuration"]["DHCPEnabled"] = - ethData.DHCPEnabled; + json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; if (!ethData.hostname.empty()) { json_response["HostName"] = ethData.hostname; } - nlohmann::json &vlanObj = json_response["VLAN"]; - if (ethData.vlan_id) - { - vlanObj["VLANEnable"] = true; - vlanObj["VLANId"] = *ethData.vlan_id; - } - else - { - vlanObj["VLANEnable"] = false; - vlanObj["VLANId"] = 0; - } + json_response["VLANs"] = { + {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + + iface_id + "/VLANs"}}; + json_response["NameServers"] = ethData.nameservers; if (ipv4Data.size() > 0) @@ -1300,7 +1287,7 @@ class EthernetInterface : public Node return; } asyncResp->res.jsonValue["@odata.type"] = - "#EthernetInterface.v1_2_0.EthernetInterface"; + "#EthernetInterface.v1_4_1.EthernetInterface"; asyncResp->res.jsonValue["@odata.context"] = "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; @@ -1325,52 +1312,24 @@ class EthernetInterface : public Node const std::string &iface_id = params[0]; - std::optional<nlohmann::json> vlan; std::optional<std::string> hostname; std::optional<std::string> macAddress; std::optional<nlohmann::json> ipv4Addresses; std::optional<nlohmann::json> ipv6Addresses; - if (!json_util::readJson(req, res, "VLAN", vlan, "HostName", hostname, - "IPv4Addresses", ipv4Addresses, - "IPv6Addresses", ipv6Addresses, "MACAddress", - macAddress)) + if (!json_util::readJson( + req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, + "IPv6Addresses", ipv6Addresses, "MACAddress", macAddress)) { return; } - std::optional<uint64_t> vlanId; - std::optional<bool> vlanEnable; - - if (vlan) - { - if (!json_util::readJson(*vlan, res, "VLANEnable", vlanEnable, - "VLANId", vlanId)) - { - return; - } - // Need both vlanId and vlanEnable to service this request - if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) - { - if (vlanId) - { - messages::propertyMissing(asyncResp->res, "VLANEnable"); - } - else - { - messages::propertyMissing(asyncResp->res, "VLANId"); - } - - return; - } - } - // Get single eth interface data, and call the below callback for JSON // preparation getEthernetIfaceData( iface_id, - [this, asyncResp, iface_id, vlanId, vlanEnable, - hostname = std::move(hostname), macAddress = std::move(macAddress), + [this, asyncResp, iface_id, hostname = std::move(hostname), + macAddress = std::move(macAddress), ipv4Addresses = std::move(ipv4Addresses), ipv6Addresses = std::move(ipv6Addresses)]( const bool &success, const EthernetInterfaceData ðData, @@ -1380,20 +1339,14 @@ class EthernetInterface : public Node // ... otherwise return error // TODO(Pawel)consider distinguish between non existing // object, and other errors - messages::resourceNotFound( - asyncResp->res, "VLAN Network Interface", iface_id); + messages::resourceNotFound(asyncResp->res, + "Ethernet Interface", iface_id); return; } parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, ipv4Data); - if (vlanId && vlanEnable) - { - handleVlanPatch(iface_id, *vlanId, *vlanEnable, ethData, - asyncResp); - } - if (hostname) { handleHostnamePatch(*hostname, asyncResp); @@ -1464,20 +1417,16 @@ class VlanNetworkInterface : public Node "/VLANs/" + iface_id; json_response["VLANEnable"] = true; - if (ethData.vlan_id) + if (!ethData.vlan_id.empty()) { - json_response["VLANId"] = *ethData.vlan_id; + json_response["VLANId"] = ethData.vlan_id.back(); } } - bool verifyNames(crow::Response &res, const std::string &parent, - const std::string &iface) + bool verifyNames(const std::string &parent, const std::string &iface) { - std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); if (!boost::starts_with(iface, parent + "_")) { - messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", - iface); return false; } else @@ -1512,7 +1461,7 @@ class VlanNetworkInterface : public Node "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; res.jsonValue["Name"] = "VLAN Network Interface"; - if (!verifyNames(res, parent_iface_id, iface_id)) + if (!verifyNames(parent_iface_id, iface_id)) { return; } @@ -1520,11 +1469,12 @@ class VlanNetworkInterface : public Node // Get single eth interface data, and call the below callback for JSON // preparation getEthernetIfaceData( - iface_id, - [this, asyncResp, parent_iface_id, iface_id]( + params[1], + [this, asyncResp, parent_iface_id{std::string(params[0])}, + iface_id{std::string(params[1])}]( const bool &success, const EthernetInterfaceData ðData, const boost::container::flat_set<IPv4AddressData> &ipv4Data) { - if (success && ethData.vlan_id) + if (success && ethData.vlan_id.size() != 0) { parseInterfaceData(asyncResp->res.jsonValue, parent_iface_id, iface_id, ethData, @@ -1554,8 +1504,10 @@ class VlanNetworkInterface : public Node const std::string &parentIfaceId = params[0]; const std::string &ifaceId = params[1]; - if (!verifyNames(res, parentIfaceId, ifaceId)) + if (!verifyNames(parentIfaceId, ifaceId)) { + messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", + ifaceId); return; } @@ -1606,20 +1558,22 @@ class VlanNetworkInterface : public Node const std::string &parentIfaceId = params[0]; const std::string &ifaceId = params[1]; - if (!verifyNames(asyncResp->res, parentIfaceId, ifaceId)) + if (!verifyNames(parentIfaceId, ifaceId)) { + messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", + ifaceId); return; } // Get single eth interface data, and call the below callback for JSON // preparation getEthernetIfaceData( - ifaceId, - [this, asyncResp, parentIfaceId{std::string(parentIfaceId)}, - ifaceId{std::string(ifaceId)}]( + params[1], + [this, asyncResp, parentIfaceId{std::string(params[0])}, + ifaceId{std::string(params[1])}]( const bool &success, const EthernetInterfaceData ðData, const boost::container::flat_set<IPv4AddressData> &ipv4Data) { - if (success && ethData.vlan_id) + if (success && !ethData.vlan_id.empty()) { parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, ifaceId, ethData, ipv4Data); @@ -1720,12 +1674,6 @@ class VlanNetworkInterfaceCollection : public Node } } - if (iface_array.empty()) - { - messages::resourceNotFound( - asyncResp->res, "EthernetInterface", rootInterfaceName); - return; - } asyncResp->res.jsonValue["Members@odata.count"] = iface_array.size(); asyncResp->res.jsonValue["Members"] = std::move(iface_array); @@ -1744,12 +1692,27 @@ class VlanNetworkInterfaceCollection : public Node messages::internalError(asyncResp->res); return; } - + bool vlanEnable = false; uint32_t vlanId = 0; - if (!json_util::readJson(req, res, "VLANId", vlanId)) + if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", + vlanEnable)) + { + return; + } + // Need both vlanId and vlanEnable to service this request + if (!vlanId) + { + messages::propertyMissing(asyncResp->res, "VLANId"); + } + if (!vlanEnable) + { + messages::propertyMissing(asyncResp->res, "VLANEnable"); + } + if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) { return; } + const std::string &rootInterfaceName = params[0]; auto callback = [asyncResp](const boost::system::error_code ec) { if (ec) |