1 /*
2 // Copyright (c) 2019 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 
17 #include <ipmid/api.hpp>
18 #include <ipmid/utils.hpp>
19 #include <multinodecommands.hpp>
20 #include <oemcommands.hpp>
21 #include <phosphor-logging/log.hpp>
22 #include <sdbusplus/bus.hpp>
23 #include <sdbusplus/message/types.hpp>
24 
25 #include <string>
26 
27 namespace ipmi
28 {
29 void registerMultiNodeFunctions() __attribute__((constructor));
30 
31 std::optional<uint8_t> getMultiNodeInfo(std::string name)
32 {
33     auto pdbus = getSdBus();
34     try
35     {
36         std::string service = getService(*pdbus, multiNodeIntf,
37                                          multiNodeObjPath);
38         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
39                                           multiNodeIntf, name);
40         return std::get<uint8_t>(dbusValue);
41     }
42     catch (const std::exception& e)
43     {
44         phosphor::logging::log<phosphor::logging::level::ERR>(
45             "getMultiNodeInfo: can't get multi node info from dbus!",
46             phosphor::logging::entry("ERR=%s", e.what()));
47         return std::nullopt;
48     }
49 }
50 
51 std::optional<uint8_t> getMultiNodeRole()
52 {
53     auto pdbus = getSdBus();
54     try
55     {
56         std::string service = getService(*pdbus, multiNodeIntf,
57                                          multiNodeObjPath);
58         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
59                                           multiNodeIntf, "NodeRole");
60         std::string valueStr = std::get<std::string>(dbusValue);
61         uint8_t value;
62         if (valueStr == "single")
63             value = static_cast<uint8_t>(NodeRole::single);
64         else if (valueStr == "master")
65             value = static_cast<uint8_t>(NodeRole::controller);
66         else if (valueStr == "slave")
67             value = static_cast<uint8_t>(NodeRole::target);
68         else if (valueStr == "arbitrating")
69             value = static_cast<uint8_t>(NodeRole::arbitrating);
70         else
71         {
72             phosphor::logging::log<phosphor::logging::level::ERR>(
73                 "getMultiNodeRole: Invalid dbus value!",
74                 phosphor::logging::entry("VALUE=%s", valueStr.c_str()));
75             return std::nullopt;
76         }
77         return value;
78     }
79     catch (const std::exception& e)
80     {
81         phosphor::logging::log<phosphor::logging::level::ERR>(
82             "getMultiNodeRole: can't get multi node role from dbus!",
83             phosphor::logging::entry("ERR=%s", e.what()));
84         return std::nullopt;
85     }
86 }
87 
88 ipmi::RspType<uint8_t> ipmiGetMultiNodePresence()
89 
90 {
91     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodePresence");
92     if (!nodeInfo)
93     {
94         return ipmi::responseResponseError();
95     }
96 
97     return ipmi::responseSuccess(*nodeInfo);
98 }
99 
100 ipmi::RspType<uint8_t> ipmiGetMultiNodeId()
101 {
102     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodeId");
103     if (!nodeInfo)
104     {
105         return ipmi::responseResponseError();
106     }
107 
108     return ipmi::responseSuccess(*nodeInfo);
109 }
110 
111 ipmi::RspType<uint8_t> ipmiGetMultiNodeRole()
112 {
113     std::optional<uint8_t> nodeInfo = getMultiNodeRole();
114     if (!nodeInfo)
115     {
116         return ipmi::responseResponseError();
117     }
118 
119     return ipmi::responseSuccess(*nodeInfo);
120 }
121 
122 void registerMultiNodeFunctions(void)
123 {
124     phosphor::logging::log<phosphor::logging::level::INFO>(
125         "Registering MultiNode commands");
126 
127     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
128                           ipmi::intel::general::cmdGetMultiNodePresence,
129                           ipmi::Privilege::User, ipmiGetMultiNodePresence);
130 
131     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
132                           ipmi::intel::general::cmdGetMultiNodeId,
133                           ipmi::Privilege::User, ipmiGetMultiNodeId);
134 
135     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
136                           ipmi::intel::general::cmdGetMultiNodeRole,
137                           ipmi::Privilege::User, ipmiGetMultiNodeRole);
138 }
139 
140 } // namespace ipmi
141