summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFeist, James <james.feist@intel.com>2019-10-08 20:51:55 +0300
committerGerrit Code Review <gerrit@localhost>2019-10-08 20:51:55 +0300
commit124de49a990ba0dd9720c9359cab4e2037e66ac7 (patch)
treebb970dc5a470bc43cb4815f34b9aeb4496fb4e97
parent7998edd927c3370719a9ea9f70f55773c0964604 (diff)
parent05cbe7a49a614b554413f8ebbda4306f603112f6 (diff)
downloadprovingground-124de49a990ba0dd9720c9359cab4e2037e66ac7.tar.xz
Merge changes Ia050316a,I79a73bb0
* changes: Create associations for drives with inventory Add rebuilding to hsbp manager
-rw-r--r--hsbp-manager/CMakeLists.txt1
-rw-r--r--hsbp-manager/include/utils.hpp1
-rw-r--r--hsbp-manager/src/hsbp_manager.cpp274
3 files changed, 270 insertions, 6 deletions
diff --git a/hsbp-manager/CMakeLists.txt b/hsbp-manager/CMakeLists.txt
index 20560c9..eeb6f0a 100644
--- a/hsbp-manager/CMakeLists.txt
+++ b/hsbp-manager/CMakeLists.txt
@@ -87,6 +87,7 @@ target_link_libraries (hsbp-manager -lsystemd)
target_link_libraries (hsbp-manager i2c)
target_link_libraries (hsbp-manager ${Boost_LIBRARIES})
target_link_libraries (hsbp-manager sdbusplus)
+target_link_libraries (hsbp-manager stdc++fs)
if (NOT YOCTO)
add_dependencies (hsbp-manager sdbusplus-project)
diff --git a/hsbp-manager/include/utils.hpp b/hsbp-manager/include/utils.hpp
index eec2cd6..8e63bfe 100644
--- a/hsbp-manager/include/utils.hpp
+++ b/hsbp-manager/include/utils.hpp
@@ -25,6 +25,7 @@ using GetSubTreeType = std::vector<
using BasicVariantType =
std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
+using Association = std::tuple<std::string, std::string, std::string>;
namespace mapper
{
diff --git a/hsbp-manager/src/hsbp_manager.cpp b/hsbp-manager/src/hsbp_manager.cpp
index e02b76a..56469dd 100644
--- a/hsbp-manager/src/hsbp_manager.cpp
+++ b/hsbp-manager/src/hsbp_manager.cpp
@@ -18,6 +18,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/asio/steady_timer.hpp>
+#include <filesystem>
#include <iostream>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
@@ -47,9 +48,18 @@ static std::string zeroPad(const uint8_t val)
return version.str();
}
+struct Mux
+{
+ Mux(size_t busIn, size_t addressIn) : bus(busIn), address(addressIn)
+ {
+ }
+ size_t bus;
+ size_t address;
+};
struct Drive
{
- Drive(size_t driveIndex, bool isPresent, bool isOperational, bool nvme) :
+ Drive(size_t driveIndex, bool isPresent, bool isOperational, bool nvme,
+ bool rebuilding) :
isNvme(nvme)
{
constexpr const char* basePath =
@@ -61,19 +71,42 @@ struct Drive
"Drive " + std::to_string(driveIndex));
itemIface->initialize();
operationalIface = objServer.add_interface(
- basePath + std::to_string(driveIndex),
+ itemIface->get_object_path(),
"xyz.openbmc_project.State.Decorator.OperationalStatus");
operationalIface->register_property("Functional", isOperational);
operationalIface->initialize();
+ rebuildingIface = objServer.add_interface(
+ itemIface->get_object_path(), "xyz.openbmc_project.State.Drive");
+ rebuildingIface->register_property("Rebuilding", rebuilding);
+ rebuildingIface->initialize();
}
~Drive()
{
objServer.remove_interface(itemIface);
objServer.remove_interface(operationalIface);
+ objServer.remove_interface(rebuildingIface);
+ objServer.remove_interface(associationIface);
+ }
+
+ void createAssociation(const std::string& path)
+ {
+ if (associationIface != nullptr)
+ {
+ return;
+ }
+ associationIface = objServer.add_interface(
+ itemIface->get_object_path(),
+ "xyz.openbmc_project.Association.Definitions");
+ std::vector<Association> associations;
+ associations.emplace_back("inventory", "drive", path);
+ associationIface->register_property("Associations", associations);
+ associationIface->initialize();
}
std::shared_ptr<sdbusplus::asio::dbus_interface> itemIface;
std::shared_ptr<sdbusplus::asio::dbus_interface> operationalIface;
+ std::shared_ptr<sdbusplus::asio::dbus_interface> rebuildingIface;
+ std::shared_ptr<sdbusplus::asio::dbus_interface> associationIface;
bool isNvme;
};
@@ -84,7 +117,8 @@ struct Backplane
const std::string& nameIn) :
bus(busIn),
address(addressIn), backplaneIndex(backplaneIndexIn - 1), name(nameIn),
- timer(std::make_shared<boost::asio::steady_timer>(io))
+ timer(std::make_shared<boost::asio::steady_timer>(io)),
+ muxes(std::make_shared<std::vector<Mux>>())
{
}
void run()
@@ -155,17 +189,20 @@ struct Backplane
uint8_t curPresence = 0;
uint8_t curIFDET = 0;
uint8_t curFailed = 0;
+ uint8_t curRebuild = 0;
getPresence(curPresence);
getIFDET(curIFDET);
getFailed(curFailed);
+ getRebuild(curRebuild);
if (curPresence != presence || curIFDET != ifdet ||
- curFailed != failed)
+ curFailed != failed || curRebuild != rebuilding)
{
presence = curPresence;
ifdet = curIFDET;
failed = curFailed;
+ rebuilding = curRebuild;
updateDrives();
}
runTimer();
@@ -180,10 +217,12 @@ struct Backplane
bool isNvme = nvme & (1 << ii);
bool isPresent = isNvme || (presence & (1 << ii));
bool isFailed = !isPresent || failed & (1 << ii);
+ bool isRebuilding = !isPresent && (rebuilding & (1 << ii));
// +1 to convert from 0 based to 1 based
size_t driveIndex = (backplaneIndex * maxDrives) + ii + 1;
- drives.emplace_back(driveIndex, isPresent, !isFailed, isNvme);
+ drives.emplace_back(driveIndex, isPresent, !isFailed, isNvme,
+ isRebuilding);
}
}
@@ -195,12 +234,14 @@ struct Backplane
{
bool isNvme = nvme & (1 << ii);
bool isPresent = isNvme || (presence & (1 << ii));
- bool isFailed = !isPresent || failed & (1 << ii);
+ bool isFailed = !isPresent || (failed & (1 << ii));
+ bool isRebuilding = isPresent && (rebuilding & (1 << ii));
Drive& drive = drives[ii];
drive.isNvme = isNvme;
drive.itemIface->set_property("Present", isPresent);
drive.operationalIface->set_property("Functional", !isFailed);
+ drive.rebuildingIface->set_property("Rebuilding", isRebuilding);
}
}
@@ -351,6 +392,7 @@ struct Backplane
uint8_t presence = 0;
uint8_t ifdet = 0;
uint8_t failed = 0;
+ uint8_t rebuilding = 0;
int file = -1;
@@ -360,10 +402,206 @@ struct Backplane
std::shared_ptr<sdbusplus::asio::dbus_interface> versionIface;
std::vector<Drive> drives;
+ std::shared_ptr<std::vector<Mux>> muxes;
};
std::unordered_map<std::string, Backplane> backplanes;
+void updateAssociations()
+{
+ constexpr const char* driveType =
+ "xyz.openbmc_project.Inventory.Item.Drive";
+
+ conn->async_method_call(
+ [](const boost::system::error_code ec, const GetSubTreeType& subtree) {
+ if (ec)
+ {
+ std::cerr << "Error contacting mapper " << ec.message() << "\n";
+ return;
+ }
+ for (const auto& [path, objDict] : subtree)
+ {
+ if (objDict.empty())
+ {
+ continue;
+ }
+
+ const std::string& owner = objDict.begin()->first;
+ conn->async_method_call(
+ [path](const boost::system::error_code ec2,
+ const boost::container::flat_map<
+ std::string, std::variant<uint64_t>>& values) {
+ if (ec2)
+ {
+ std::cerr << "Error Getting Config "
+ << ec2.message() << " " << __FUNCTION__
+ << "\n";
+ return;
+ }
+ auto findBus = values.find("Bus");
+ auto findIndex = values.find("Index");
+
+ if (findBus == values.end() ||
+ findIndex == values.end())
+ {
+ std::cerr << "Illegal interface at " << path
+ << "\n";
+ return;
+ }
+
+ size_t muxBus = static_cast<size_t>(
+ std::get<uint64_t>(findBus->second));
+ size_t driveIndex = static_cast<size_t>(
+ std::get<uint64_t>(findIndex->second));
+ std::filesystem::path muxPath =
+ "/sys/bus/i2c/devices/i2c-" +
+ std::to_string(muxBus) + "/mux_device";
+ if (!std::filesystem::is_symlink(muxPath))
+ {
+ std::cerr << path << " mux does not exist\n";
+ return;
+ }
+
+ // we should be getting something of the form 7-0052 for
+ // bus 7 addr 52
+ std::string fname =
+ std::filesystem::read_symlink(muxPath).filename();
+ auto findDash = fname.find('-');
+
+ if (findDash == std::string::npos ||
+ findDash + 1 >= fname.size())
+ {
+ std::cerr << path << " mux path invalid\n";
+ return;
+ }
+
+ std::string busStr = fname.substr(0, findDash);
+ std::string muxStr = fname.substr(findDash + 1);
+
+ size_t bus = static_cast<size_t>(std::stoi(busStr));
+ size_t addr =
+ static_cast<size_t>(std::stoi(muxStr, nullptr, 16));
+ Backplane* parent = nullptr;
+ for (auto& [name, backplane] : backplanes)
+ {
+ for (const Mux& mux : *(backplane.muxes))
+ {
+ if (bus == mux.bus && addr == mux.address)
+ {
+ parent = &backplane;
+ break;
+ }
+ }
+ }
+ if (parent == nullptr)
+ {
+ std::cerr << "Failed to find mux at bus " << bus
+ << ", addr " << addr << "\n";
+ return;
+ }
+ if (parent->drives.size() <= driveIndex)
+ {
+
+ std::cerr << "Illegal drive index at " << path
+ << " " << driveIndex << "\n";
+ return;
+ }
+ Drive& drive = parent->drives[driveIndex];
+ drive.createAssociation(path);
+ },
+ owner, path, "org.freedesktop.DBus.Properties", "GetAll",
+ "xyz.openbmc_project.Inventory.Item.Drive");
+ }
+ },
+ mapper::busName, mapper::path, mapper::interface, mapper::subtree, "/",
+ 0, std::array<const char*, 1>{driveType});
+}
+
+void populateMuxes(std::shared_ptr<std::vector<Mux>> muxes,
+ std::string& rootPath)
+{
+ const static std::array<const std::string, 4> muxTypes = {
+ "xyz.openbmc_project.Configuration.PCA9543Mux",
+ "xyz.openbmc_project.Configuration.PCA9544Mux",
+ "xyz.openbmc_project.Configuration.PCA9545Mux",
+ "xyz.openbmc_project.Configuration.PCA9546Mux"};
+ conn->async_method_call(
+ [muxes](const boost::system::error_code ec,
+ const GetSubTreeType& subtree) {
+ if (ec)
+ {
+ std::cerr << "Error contacting mapper " << ec.message() << "\n";
+ return;
+ }
+ std::shared_ptr<std::function<void()>> callback =
+ std::make_shared<std::function<void()>>(
+ []() { updateAssociations(); });
+ for (const auto& [path, objDict] : subtree)
+ {
+ if (objDict.empty() || objDict.begin()->second.empty())
+ {
+ continue;
+ }
+
+ const std::string& owner = objDict.begin()->first;
+ const std::vector<std::string>& interfaces =
+ objDict.begin()->second;
+
+ const std::string* interface = nullptr;
+ for (const std::string& iface : interfaces)
+ {
+ if (std::find(muxTypes.begin(), muxTypes.end(), iface) !=
+ muxTypes.end())
+ {
+ interface = &iface;
+ break;
+ }
+ }
+ if (interface == nullptr)
+ {
+ std::cerr << "Cannot get mux type\n";
+ continue;
+ }
+
+ conn->async_method_call(
+ [path, muxes, callback](
+ const boost::system::error_code ec2,
+ const boost::container::flat_map<
+ std::string, std::variant<uint64_t>>& values) {
+ if (ec2)
+ {
+ std::cerr << "Error Getting Config "
+ << ec2.message() << " " << __FUNCTION__
+ << "\n";
+ return;
+ }
+ auto findBus = values.find("Bus");
+ auto findAddress = values.find("Address");
+ if (findBus == values.end() ||
+ findAddress == values.end())
+ {
+ std::cerr << "Illegal configuration at " << path
+ << "\n";
+ return;
+ }
+ size_t bus = static_cast<size_t>(
+ std::get<uint64_t>(findBus->second));
+ size_t address = static_cast<size_t>(
+ std::get<uint64_t>(findAddress->second));
+ muxes->emplace_back(bus, address);
+ if (callback.use_count() == 1)
+ {
+ (*callback)();
+ }
+ },
+ owner, path, "org.freedesktop.DBus.Properties", "GetAll",
+ *interface);
+ }
+ },
+ mapper::busName, mapper::path, mapper::interface, mapper::subtree,
+ rootPath, 1, muxTypes);
+}
+
void populate()
{
conn->async_method_call(
@@ -421,10 +659,13 @@ void populate()
<< "\n";
return;
}
+ std::string parentPath =
+ std::filesystem::path(path).parent_path();
const auto& [backplane, status] = backplanes.emplace(
*name,
Backplane(*bus, *address, *backplaneIndex, *name));
backplane->second.run();
+ populateMuxes(backplane->second.muxes, parentPath);
},
owner, path, "org.freedesktop.DBus.Properties", "GetAll",
configType);
@@ -461,6 +702,27 @@ int main()
});
});
+ sdbusplus::bus::match::match drive(
+ *conn,
+ "type='signal',member='PropertiesChanged',arg0='xyz.openbmc_project."
+ "Inventory.Item.Drive'",
+ [&callbackTimer](sdbusplus::message::message&) {
+ callbackTimer.expires_after(std::chrono::seconds(2));
+ callbackTimer.async_wait([](const boost::system::error_code ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ // timer was restarted
+ return;
+ }
+ else if (ec)
+ {
+ std::cerr << "Timer error" << ec.message() << "\n";
+ return;
+ }
+ populate();
+ });
+ });
+
io.post([]() { populate(); });
io.run();
}