1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #include "utils/dbus_utils.hpp"
4
5 #include "async_resp.hpp"
6 #include "boost_formatters.hpp"
7 #include "error_messages.hpp"
8 #include "logging.hpp"
9
10 #include <systemd/sd-bus.h>
11
12 #include <boost/asio/error.hpp>
13 #include <boost/beast/http/status.hpp>
14 #include <boost/system/error_code.hpp>
15 #include <nlohmann/json.hpp>
16 #include <sdbusplus/message.hpp>
17
18 #include <memory>
19 #include <string>
20 #include <string_view>
21
22 namespace redfish
23 {
24 namespace details
25 {
26
afterSetProperty(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & redfishPropertyName,const nlohmann::json & propertyValue,const boost::system::error_code & ec,const sdbusplus::message_t & msg)27 void afterSetProperty(
28 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
29 const std::string& redfishPropertyName, const nlohmann::json& propertyValue,
30 const boost::system::error_code& ec, const sdbusplus::message_t& msg)
31 {
32 if (ec)
33 {
34 if (ec.value() == boost::system::errc::permission_denied)
35 {
36 messages::insufficientPrivilege(asyncResp->res);
37 }
38 if (ec.value() == boost::asio::error::host_unreachable)
39 {
40 messages::resourceNotFound(asyncResp->res, "Set",
41 redfishPropertyName);
42 return;
43 }
44 const sd_bus_error* dbusError = msg.get_error();
45 if (dbusError != nullptr)
46 {
47 std::string_view errorName(dbusError->name);
48
49 if (errorName == "xyz.openbmc_project.Common.Error.InvalidArgument")
50 {
51 BMCWEB_LOG_WARNING("DBUS response error: {}", ec);
52 messages::propertyValueIncorrect(
53 asyncResp->res, redfishPropertyName, propertyValue);
54 return;
55 }
56 if (errorName ==
57 "xyz.openbmc_project.State.Chassis.Error.BMCNotReady")
58 {
59 BMCWEB_LOG_WARNING(
60 "BMC not ready, operation not allowed right now");
61 messages::serviceTemporarilyUnavailable(asyncResp->res, "10");
62 return;
63 }
64 if (errorName == "xyz.openbmc_project.State.Host.Error.BMCNotReady")
65 {
66 BMCWEB_LOG_WARNING(
67 "BMC not ready, operation not allowed right now");
68 messages::serviceTemporarilyUnavailable(asyncResp->res, "10");
69 return;
70 }
71 if (errorName == "xyz.openbmc_project.Common.Error.NotAllowed")
72 {
73 messages::propertyNotWritable(asyncResp->res,
74 redfishPropertyName);
75 return;
76 }
77 if (errorName == "xyz.openbmc_project.Common.Error.Unavailable")
78 {
79 messages::propertyValueExternalConflict(
80 asyncResp->res, redfishPropertyName, propertyValue);
81 return;
82 }
83 }
84 BMCWEB_LOG_ERROR("D-Bus error setting Redfish Property {} ec={}",
85 redfishPropertyName, ec);
86 messages::internalError(asyncResp->res);
87 return;
88 }
89 // Only set 204 if another error hasn't already happened.
90 if (asyncResp->res.result() == boost::beast::http::status::ok)
91 {
92 asyncResp->res.result(boost::beast::http::status::no_content);
93 }
94 };
95
afterSetPropertyAction(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & redfishActionName,const std::string & redfishActionParameterName,const boost::system::error_code & ec,const sdbusplus::message_t &)96 void afterSetPropertyAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
97 const std::string& redfishActionName,
98 const std::string& redfishActionParameterName,
99 const boost::system::error_code& ec,
100 const sdbusplus::message_t& /*msg*/)
101 {
102 if (ec)
103 {
104 if (ec.value() == boost::asio::error::invalid_argument)
105 {
106 BMCWEB_LOG_WARNING(
107 "Resource {} is patched with invalid argument during action {}",
108 redfishActionParameterName, redfishActionName);
109 if (redfishActionParameterName.empty())
110 {
111 messages::operationFailed(asyncResp->res);
112 }
113 else
114 {
115 messages::actionParameterValueError(asyncResp->res,
116 redfishActionParameterName,
117 redfishActionName);
118 }
119 return;
120 }
121 if (ec.value() == boost::asio::error::host_unreachable)
122 {
123 BMCWEB_LOG_WARNING(
124 "Resource {} is not found while performing action {}",
125 redfishActionParameterName, redfishActionName);
126 messages::resourceNotFound(asyncResp->res, "Actions",
127 redfishActionName);
128 return;
129 }
130
131 BMCWEB_LOG_ERROR("D-Bus error setting Redfish Property {} ec={}",
132 redfishActionParameterName, ec);
133 messages::internalError(asyncResp->res);
134 return;
135 }
136 // Only set success if another error hasn't already happened.
137 if (asyncResp->res.result() == boost::beast::http::status::ok)
138 {
139 messages::success(asyncResp->res);
140 }
141 };
142 } // namespace details
143 } // namespace redfish
144