blob: 0c02c3594fbe6a7eaa004481b5003f596b972eeb [file] [log] [blame]
Deepak Kodihalli5f031f32017-07-26 08:25:59 -05001#include <algorithm>
2#include <iterator>
3#include <experimental/filesystem>
4#include <sdbusplus/server.hpp>
5#include <phosphor-logging/elog-errors.hpp>
6#include <phosphor-logging/log.hpp>
7#include <xyz/openbmc_project/Common/error.hpp>
8#include "occ_finder.hpp"
9#include "config.h"
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050010namespace open_power
11{
12namespace occ
13{
14namespace finder
15{
16
17using namespace phosphor::logging;
18
19constexpr auto toChar(size_t c)
20{
21 constexpr auto map = "0123456789abcdef";
22 return map[c];
23}
24
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053025template <typename T>
26T getDbusProperty(sdbusplus::bus::bus& bus,
27 const std::string& service,
28 const std::string& objPath,
29 const std::string& interface,
30 const std::string& property)
31{
32 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
33
34 constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
35
36 auto method = bus.new_method_call(
37 service.c_str(),
38 objPath.c_str(),
39 PROPERTY_INTF,
40 "Get");
41 method.append(interface, property);
42
43 auto reply = bus.call(method);
44 if (reply.is_method_error())
45 {
46 log<level::ERR>("Failed to get property",
47 entry("PROPERTY=%s", property.c_str()),
48 entry("PATH=%s", objPath.c_str()),
49 entry("INTERFACE=%s", interface.c_str()));
50 elog<InternalFailure>();
51 }
52
53 sdbusplus::message::variant<T> value;
54 reply.read(value);
55
56 return sdbusplus::message::variant_ns::get<T>(value);
57}
58
Vishwanatha Subbanna1ec291f2017-08-21 17:07:29 +053059std::vector<std::string> get(sdbusplus::bus::bus& bus)
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050060{
61 namespace fs = std::experimental::filesystem;
62 using Path = std::string;
63 using Service = std::string;
64 using Interface = std::string;
65 using Interfaces = std::vector<Interface>;
66
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050067 auto mapper =
68 bus.new_method_call(
69 "xyz.openbmc_project.ObjectMapper",
70 "/xyz/openbmc_project/object_mapper",
71 "xyz.openbmc_project.ObjectMapper",
72 "GetSubTree");
73
74 auto depth = 0;
75 Path path = CPU_SUBPATH;
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +053076 Interfaces interfaces
77 {
78 "xyz.openbmc_project.Inventory.Item",
79 "xyz.openbmc_project.State.Decorator.OperationalStatus"
80 };
81
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050082 mapper.append(path);
83 mapper.append(depth);
84 mapper.append(interfaces);
85
86 auto result = bus.call(mapper);
87 if (result.is_method_error())
88 {
89 // It's okay to not have inventory, for example at BMC standby
90 return {};
91 }
92
93 using MapperResponse = std::map<Path, std::map<Service, Interfaces>>;
94 MapperResponse response;
95 result.read(response);
96 if (response.empty())
97 {
98 // It's okay to not have inventory, for example at BMC standby
99 return {};
100 }
101
102 std::vector<std::string> occs;
103 for (auto count = 0; count < MAX_CPUS; ++count)
104 {
105 fs::path p(path);
106 p /= std::string(CPU_NAME) + toChar(count);
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530107
108 auto entry = response.find(p.string());
109 if (response.end() != entry)
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500110 {
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530111 Criteria match{};
112 match.emplace_back(std::make_tuple(
113 "xyz.openbmc_project.Inventory.Item",
114 "Present",
115 true));
116
Deepak Kodihalli3f3fa562017-10-25 04:18:49 -0500117 // Select only if the CPU is marked 'Present'.
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530118 // Local variable to make it readable
119 auto path = entry->first;
120 auto service = entry->second.begin()->first;
121 if (matchCriteria(bus, path, service, match))
122 {
123 occs.emplace_back(std::string(OCC_NAME) +
124 toChar(count));
125 }
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500126 }
127 }
128
129 return occs;
130}
131
Vishwanatha Subbanna3ace7572017-08-22 16:06:11 +0530132bool matchCriteria(sdbusplus::bus::bus& bus,
133 const std::string& path,
134 const std::string& service,
135 const Criteria& match)
136{
137 for (const auto& iter: match)
138 {
139 auto result = getDbusProperty<bool>(bus, service, path,
140 std::get<0>(iter),
141 std::get<1>(iter));
142 if (result != std::get<2>(iter))
143 {
144 return false;
145 }
146 }
147 return true;
148}
149
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500150} // namespace finder
151} // namespace occ
152} // namespace open_power