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 = 37 getService(*pdbus, multiNodeIntf, 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 = 57 getService(*pdbus, multiNodeIntf, 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::master); 66 else if (valueStr == "slave") 67 value = static_cast<uint8_t>(NodeRole::slave); 68 else if (valueStr == "arbitrating") 69 value = static_cast<uint8_t>(NodeRole::arbitrating); 70 return value; 71 } 72 catch (const std::exception& e) 73 { 74 phosphor::logging::log<phosphor::logging::level::ERR>( 75 "getMultiNodeRole: can't get multi node role from dbus!", 76 phosphor::logging::entry("ERR=%s", e.what())); 77 return std::nullopt; 78 } 79 } 80 81 ipmi::RspType<uint8_t> ipmiGetMultiNodePresence() 82 83 { 84 std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodePresence"); 85 if (!nodeInfo) 86 { 87 return ipmi::responseResponseError(); 88 } 89 90 return ipmi::responseSuccess(*nodeInfo); 91 } 92 93 ipmi::RspType<uint8_t> ipmiGetMultiNodeId() 94 { 95 std::optional<uint8_t> nodeInfo = getMultiNodeInfo("NodeId"); 96 if (!nodeInfo) 97 { 98 return ipmi::responseResponseError(); 99 } 100 101 return ipmi::responseSuccess(*nodeInfo); 102 } 103 104 ipmi::RspType<uint8_t> ipmiGetMultiNodeRole() 105 { 106 std::optional<uint8_t> nodeInfo = getMultiNodeRole(); 107 if (!nodeInfo) 108 { 109 return ipmi::responseResponseError(); 110 } 111 112 return ipmi::responseSuccess(*nodeInfo); 113 } 114 115 void registerMultiNodeFunctions(void) 116 { 117 phosphor::logging::log<phosphor::logging::level::INFO>( 118 "Registering MultiNode commands"); 119 120 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 121 ipmi::intel::general::cmdGetMultiNodePresence, 122 ipmi::Privilege::User, ipmiGetMultiNodePresence); 123 124 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 125 ipmi::intel::general::cmdGetMultiNodeId, 126 ipmi::Privilege::User, ipmiGetMultiNodeId); 127 128 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 129 ipmi::intel::general::cmdGetMultiNodeRole, 130 ipmi::Privilege::User, ipmiGetMultiNodeRole); 131 } 132 133 } // namespace ipmi 134