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::resourceInStandby(asyncResp->res);
80 return;
81 }
82 }
83 BMCWEB_LOG_ERROR("D-Bus error setting Redfish Property {} ec={}",
84 redfishPropertyName, ec);
85 messages::internalError(asyncResp->res);
86 return;
87 }
88 // Only set 204 if another error hasn't already happened.
89 if (asyncResp->res.result() == boost::beast::http::status::ok)
90 {
91 asyncResp->res.result(boost::beast::http::status::no_content);
92 }
93 };
94
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 &)95 void afterSetPropertyAction(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
96 const std::string& redfishActionName,
97 const std::string& redfishActionParameterName,
98 const boost::system::error_code& ec,
99 const sdbusplus::message_t& /*msg*/)
100 {
101 if (ec)
102 {
103 if (ec.value() == boost::asio::error::invalid_argument)
104 {
105 BMCWEB_LOG_WARNING(
106 "Resource {} is patched with invalid argument during action {}",
107 redfishActionParameterName, redfishActionName);
108 if (redfishActionParameterName.empty())
109 {
110 messages::operationFailed(asyncResp->res);
111 }
112 else
113 {
114 messages::actionParameterValueError(asyncResp->res,
115 redfishActionParameterName,
116 redfishActionName);
117 }
118 return;
119 }
120 if (ec.value() == boost::asio::error::host_unreachable)
121 {
122 BMCWEB_LOG_WARNING(
123 "Resource {} is not found while performing action {}",
124 redfishActionParameterName, redfishActionName);
125 messages::resourceNotFound(asyncResp->res, "Actions",
126 redfishActionName);
127 return;
128 }
129
130 BMCWEB_LOG_ERROR("D-Bus error setting Redfish Property {} ec={}",
131 redfishActionParameterName, ec);
132 messages::internalError(asyncResp->res);
133 return;
134 }
135 // Only set success if another error hasn't already happened.
136 if (asyncResp->res.result() == boost::beast::http::status::ok)
137 {
138 messages::success(asyncResp->res);
139 }
140 };
141 } // namespace details
142 } // namespace redfish
143