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 #include <string>
25 
26 namespace ipmi
27 {
28 void registerMultiNodeFunctions() __attribute__((constructor));
29 
30 std::optional<uint8_t> getMultiNodeInfo(std::string name)
31 {
32     auto pdbus = getSdBus();
33     try
34     {
35         std::string service =
36             getService(*pdbus, multiNodeIntf, multiNodeObjPath);
37         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
38                                           multiNodeIntf, name);
39         return std::get<uint8_t>(dbusValue);
40     }
41     catch (const std::exception& e)
42     {
43         phosphor::logging::log<phosphor::logging::level::ERR>(
44             "getMultiNodeInfo: can't get multi node info from dbus!",
45             phosphor::logging::entry("ERR=%s", e.what()));
46         return std::nullopt;
47     }
48 }
49 
50 std::optional<uint8_t> getMultiNodeRole()
51 {
52     auto pdbus = getSdBus();
53     try
54     {
55         std::string service =
56             getService(*pdbus, multiNodeIntf, multiNodeObjPath);
57         Value dbusValue = getDbusProperty(*pdbus, service, multiNodeObjPath,
58                                           multiNodeIntf, "NodeRole");
59         std::string valueStr = std::get<std::string>(dbusValue);
60         uint8_t value;
61         if (valueStr == "single")
62             value = static_cast<uint8_t>(NodeRole::single);
63         else if (valueStr == "master")
64             value = static_cast<uint8_t>(NodeRole::master);
65         else if (valueStr == "slave")
66             value = static_cast<uint8_t>(NodeRole::slave);
67         else if (valueStr == "arbitrating")
68             value = static_cast<uint8_t>(NodeRole::arbitrating);
69         return value;
70     }
71     catch (const std::exception& e)
72     {
73         phosphor::logging::log<phosphor::logging::level::ERR>(
74             "getMultiNodeRole: can't get multi node role from dbus!",
75             phosphor::logging::entry("ERR=%s", e.what()));
76         return std::nullopt;
77     }
78 }
79 
80 ipmi::RspType<uint8_t> ipmiGetMultiNodePresence()
81 
82 {
83     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodePresence");
84     if (!nodeInfo)
85     {
86         return ipmi::responseResponseError();
87     }
88 
89     return ipmi::responseSuccess(*nodeInfo);
90 }
91 
92 ipmi::RspType<uint8_t> ipmiGetMultiNodeId()
93 {
94     std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodeId");
95     if (!nodeInfo)
96     {
97         return ipmi::responseResponseError();
98     }
99 
100     return ipmi::responseSuccess(*nodeInfo);
101 }
102 
103 ipmi::RspType<uint8_t> ipmiGetMultiNodeRole()
104 {
105     std::optional<uint8_t> nodeInfo = getMultiNodeRole();
106     if (!nodeInfo)
107     {
108         return ipmi::responseResponseError();
109     }
110 
111     return ipmi::responseSuccess(*nodeInfo);
112 }
113 
114 void registerMultiNodeFunctions(void)
115 {
116     phosphor::logging::log<phosphor::logging::level::INFO>(
117         "Registering MultiNode commands");
118 
119     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
120                           ipmi::intel::general::cmdGetMultiNodePresence,
121                           ipmi::Privilege::User, ipmiGetMultiNodePresence);
122 
123     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
124                           ipmi::intel::general::cmdGetMultiNodeId,
125                           ipmi::Privilege::User, ipmiGetMultiNodeId);
126 
127     ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral,
128                           ipmi::intel::general::cmdGetMultiNodeRole,
129                           ipmi::Privilege::User, ipmiGetMultiNodeRole);
130 }
131 
132 } // namespace ipmi
133