blob: 21e722fb06aad01fae19a1cb8962e26769a14ac8 [file] [log] [blame]
Nikhil Potadeb669b6b2019-03-13 10:52:21 -07001/*
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
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <NVMeSensor.hpp>
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070018#include <boost/asio/deadline_timer.hpp>
James Feist38fb5982020-05-28 10:09:54 -070019
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070020#include <regex>
21
22static constexpr const char* sensorType =
23 "xyz.openbmc_project.Configuration.NVME1000";
24
25static NVMEMap nvmeDeviceMap;
26
Ed Tanous8a57ec02020-10-09 12:46:52 -070027static constexpr bool debug = false;
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070028
29NVMEMap& getNVMEMap()
30{
31 return nvmeDeviceMap;
32}
33
34void createSensors(boost::asio::io_service& io,
35 sdbusplus::asio::object_server& objectServer,
36 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
37{
38
39 auto getter = std::make_shared<GetSensorConfiguration>(
40 dbusConnection,
41 std::move([&io, &objectServer, &dbusConnection](
42 const ManagedObjectType& sensorConfigurations) {
43 // todo: it'd be better to only update the ones we care about
James Feist375ade22020-07-16 16:32:10 -070044 for (const auto& [_, nvmeContextPtr] : nvmeDeviceMap)
45 {
46 if (nvmeContextPtr)
47 {
48 nvmeContextPtr->close();
49 }
50 }
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070051 nvmeDeviceMap.clear();
52
53 // iterate through all found configurations
54 for (const std::pair<sdbusplus::message::object_path, SensorData>&
55 sensor : sensorConfigurations)
56 {
57 const SensorData& sensorData = sensor.second;
58 const std::string& interfacePath = sensor.first.str;
59 const std::pair<
60 std::string,
61 boost::container::flat_map<std::string, BasicVariantType>>*
62 baseConfiguration = nullptr;
63
64 // find base configuration
65 auto sensorBase = sensor.second.find(sensorType);
66 if (sensorBase != sensor.second.end())
67 {
68 baseConfiguration = &(*sensorBase);
69 }
70
71 if (baseConfiguration == nullptr)
72 {
73 continue;
74 }
75 auto findBus = baseConfiguration->second.find("Bus");
76 if (findBus == baseConfiguration->second.end())
77 {
78 continue;
79 }
80
81 unsigned int busNumber =
82 std::visit(VariantToUnsignedIntVisitor(), findBus->second);
83
84 auto findSensorName = baseConfiguration->second.find("Name");
85 if (findSensorName == baseConfiguration->second.end())
86 {
87 std::cerr << "could not determine configuration name for "
88 << interfacePath << "\n";
89 continue;
90 }
91 std::string sensorName =
92 std::get<std::string>(findSensorName->second);
93
94 std::vector<thresholds::Threshold> sensorThresholds;
95
96 if (!parseThresholdsFromConfig(sensorData, sensorThresholds))
97 {
98 std::cerr << "error populating thresholds for "
99 << sensorName << "\n";
100 }
101
102 int rootBus = busNumber;
103
104 std::string muxPath = "/sys/bus/i2c/devices/i2c-" +
105 std::to_string(busNumber) + "/mux_device";
106
107 if (std::filesystem::is_symlink(muxPath))
108 {
109 std::string rootName =
110 std::filesystem::read_symlink(muxPath).filename();
111 size_t dash = rootName.find("-");
112 if (dash == std::string::npos)
113 {
114 std::cerr << "Error finding root bus for " << rootName
115 << "\n";
116 continue;
117 }
118 rootBus = std::stoi(rootName.substr(0, dash));
119 }
120
121 std::shared_ptr<NVMeContext> context;
122 auto findRoot = nvmeDeviceMap.find(rootBus);
123 if (findRoot != nvmeDeviceMap.end())
124 {
125 context = findRoot->second;
126 }
127 else
128 {
129 context = std::make_shared<NVMeContext>(io, rootBus);
130 nvmeDeviceMap[rootBus] = context;
131 }
132
133 std::shared_ptr<NVMeSensor> sensorPtr =
134 std::make_shared<NVMeSensor>(
135 objectServer, io, dbusConnection, sensorName,
136 std::move(sensorThresholds), interfacePath, busNumber);
137
138 context->sensors.emplace_back(sensorPtr);
139 }
140 for (const auto& [_, context] : nvmeDeviceMap)
141 {
142 context->pollNVMeDevices();
143 }
144 }));
145 getter->getConfiguration(std::vector<std::string>{sensorType});
146}
147
148int main()
149{
150 boost::asio::io_service io;
151 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
152 systemBus->request_name("xyz.openbmc_project.NVMeSensor");
153 sdbusplus::asio::object_server objectServer(systemBus);
154 nvmeMCTP::init();
155
156 io.post([&]() { createSensors(io, objectServer, systemBus); });
157
158 boost::asio::deadline_timer filterTimer(io);
159 std::function<void(sdbusplus::message::message&)> eventHandler =
160 [&filterTimer, &io, &objectServer,
James Feist7d7579f2020-09-02 14:13:08 -0700161 &systemBus](sdbusplus::message::message&) {
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700162 // this implicitly cancels the timer
163 filterTimer.expires_from_now(boost::posix_time::seconds(1));
164
165 filterTimer.async_wait([&](const boost::system::error_code& ec) {
166 if (ec == boost::asio::error::operation_aborted)
167 {
168 return; // we're being canceled
169 }
170 else if (ec)
171 {
172 std::cerr << "Error: " << ec.message() << "\n";
173 return;
174 }
175
176 createSensors(io, objectServer, systemBus);
177 });
178 };
179
180 sdbusplus::bus::match::match configMatch(
181 static_cast<sdbusplus::bus::bus&>(*systemBus),
182 "type='signal',member='PropertiesChanged',path_namespace='" +
183 std::string(inventoryPath) + "',arg0namespace='" +
184 std::string(sensorType) + "'",
185 eventHandler);
186
187 io.run();
188}