Skip to content

Commit 70f36d8

Browse files
potinlaiAndrew Geissler
authored and
Andrew Geissler
committed
chassis-state-manager: Add multi-chassis support
Add multi-chassis management support, each chassis bus separates by giving a unique chassis id. Current code only support single chassis, and alway assume bus name is "xyz.openbmc_project.State.Chassis". This patch allow user to launch chassis-state-manager with a chassis id, and chassis id is added into service bus name for identification. Because there are many places hardcode with bus name "xyz.openbmc_project.State.Chassis", if chassis id is 0, chassis-state-manager will request both "xyz.openbmc_project.State.Chassis" and "xyz.openbmc_project.State.Chassis0" bus name to meet backwards compatibility. Tested on Bletchley: root@bletchley:~# busctl tree xyz.openbmc_project.State.Chassis `-/xyz `-/xyz/openbmc_project `-/xyz/openbmc_project/state `-/xyz/openbmc_project/state/chassis0 root@bletchley:~# busctl tree xyz.openbmc_project.State.Chassis0 `-/xyz `-/xyz/openbmc_project `-/xyz/openbmc_project/state `-/xyz/openbmc_project/state/chassis0 root@bletchley:~# busctl tree xyz.openbmc_project.State.Chassis1 `-/xyz `-/xyz/openbmc_project `-/xyz/openbmc_project/state `-/xyz/openbmc_project/state/chassis1 ...... patch dependencies: https://gerrit.openbmc-project.xyz/c/openbmc/phosphor-state-manager/+/51465 Signed-off-by: Potin Lai <[email protected]> Change-Id: I2ce3e9ab2c95a2688143f4e3775da164a5c33c19
1 parent 79b4500 commit 70f36d8

10 files changed

+111
-58
lines changed

chassis_state_manager.cpp

+24-20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "xyz/openbmc_project/Common/error.hpp"
77
#include "xyz/openbmc_project/State/Shutdown/Power/error.hpp"
88

9+
#include <fmt/format.h>
10+
911
#include <cereal/archives/json.hpp>
1012
#include <phosphor-logging/elog-errors.hpp>
1113
#include <phosphor-logging/lg2.hpp>
@@ -33,13 +35,13 @@ using namespace phosphor::logging;
3335
using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
3436
using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Blackout;
3537
using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Regulator;
36-
constexpr auto CHASSIS_STATE_POWEROFF_TGT = "[email protected]";
37-
constexpr auto CHASSIS_STATE_HARD_POWEROFF_TGT =
38-
39-
constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-chassis-poweron@0.target";
40-
constexpr auto RESET_HOST_SENSORS_SVC =
41-
42-
38+
constexpr auto CHASSIS_STATE_POWEROFF_TGT_FMT =
39+
"obmc-chassis-poweroff@{}.target";
40+
constexpr auto CHASSIS_STATE_HARD_POWEROFF_TGT_FMT =
41+
"obmc-chassis-hard-poweroff@{}.target";
42+
constexpr auto CHASSIS_STATE_POWERON_TGT_FMT = "obmc-chassis-poweron@{}.target";
43+
constexpr auto RESET_HOST_SENSORS_SVC_FMT =
44+
"phosphor-reset-sensor-states@{}.service";
4345
constexpr auto ACTIVE_STATE = "active";
4446
constexpr auto ACTIVATING_STATE = "activating";
4547

@@ -48,13 +50,6 @@ constexpr uint TYPE_UPS = 3;
4850
constexpr uint STATE_FULLY_CHARGED = 4;
4951
constexpr uint BATTERY_LVL_FULL = 8;
5052

51-
/* Map a transition to it's systemd target */
52-
const std::map<server::Chassis::Transition, std::string> SYSTEMD_TARGET_TABLE =
53-
{
54-
// Use the hard off target to ensure we shutdown immediately
55-
{server::Chassis::Transition::Off, CHASSIS_STATE_HARD_POWEROFF_TGT},
56-
{server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}};
57-
5853
constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
5954
constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
6055
constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
@@ -85,6 +80,14 @@ void Chassis::subscribeToSystemdSignals()
8580
return;
8681
}
8782

83+
void Chassis::createSystemdTargetTable()
84+
{
85+
systemdTargetTable = {
86+
// Use the hard off target to ensure we shutdown immediately
87+
{Transition::Off, fmt::format(CHASSIS_STATE_HARD_POWEROFF_TGT_FMT, id)},
88+
{Transition::On, fmt::format(CHASSIS_STATE_POWERON_TGT_FMT, id)}};
89+
}
90+
8891
// TODO - Will be rewritten once sdbusplus client bindings are in place
8992
// and persistent storage design is in place and sdbusplus
9093
// has read property function
@@ -136,7 +139,7 @@ void Chassis::determineInitialState()
136139
"Chassis power was on before the BMC reboot and it is off now");
137140

138141
// Reset host sensors since system is off now
139-
startUnit(RESET_HOST_SENSORS_SVC);
142+
startUnit(fmt::format(RESET_HOST_SENSORS_SVC_FMT, id));
140143

141144
setStateChangeTime();
142145

@@ -410,16 +413,17 @@ int Chassis::sysStateChange(sdbusplus::message::message& msg)
410413
return 0;
411414
}
412415

413-
if ((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
414-
(newStateResult == "done") && (!stateActive(CHASSIS_STATE_POWERON_TGT)))
416+
if ((newStateUnit == systemdTargetTable[Transition::Off]) &&
417+
(newStateResult == "done") &&
418+
(!stateActive(systemdTargetTable[Transition::On])))
415419
{
416420
info("Received signal that power OFF is complete");
417421
this->currentPowerState(server::Chassis::PowerState::Off);
418422
this->setStateChangeTime();
419423
}
420-
else if ((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
424+
else if ((newStateUnit == systemdTargetTable[Transition::On]) &&
421425
(newStateResult == "done") &&
422-
(stateActive(CHASSIS_STATE_POWERON_TGT)))
426+
(stateActive(systemdTargetTable[Transition::On])))
423427
{
424428
info("Received signal that power ON is complete");
425429
this->currentPowerState(server::Chassis::PowerState::On);
@@ -448,7 +452,7 @@ Chassis::Transition Chassis::requestedPowerTransition(Transition value)
448452

449453
info("Change to Chassis Requested Power State: {REQ_POWER_TRAN}",
450454
"REQ_POWER_TRAN", value);
451-
startUnit(SYSTEMD_TARGET_TABLE.find(value)->second);
455+
startUnit(systemdTargetTable.find(value)->second);
452456
return server::Chassis::requestedPowerTransition(value);
453457
}
454458

chassis_state_manager.hpp

+16-4
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ class Chassis : public ChassisInherit
4444
*
4545
* @param[in] bus - The Dbus bus object
4646
* @param[in] objPath - The Dbus object path
47+
* @param[in] id - Chassis id
4748
*/
48-
Chassis(sdbusplus::bus::bus& bus, const char* objPath) :
49+
Chassis(sdbusplus::bus::bus& bus, const char* objPath, size_t id) :
4950
ChassisInherit(bus, objPath, true), bus(bus),
5051
systemdSignals(
5152
bus,
@@ -54,12 +55,14 @@ class Chassis : public ChassisInherit
5455
sdbusRule::interface("org.freedesktop.systemd1.Manager"),
5556
std::bind(std::mem_fn(&Chassis::sysStateChange), this,
5657
std::placeholders::_1)),
57-
pohTimer(sdeventplus::Event::get_default(),
58-
std::bind(&Chassis::pohCallback, this), std::chrono::hours{1},
59-
std::chrono::minutes{1})
58+
id(id), pohTimer(sdeventplus::Event::get_default(),
59+
std::bind(&Chassis::pohCallback, this),
60+
std::chrono::hours{1}, std::chrono::minutes{1})
6061
{
6162
subscribeToSystemdSignals();
6263

64+
createSystemdTargetTable();
65+
6366
restoreChassisStateChangeTime();
6467

6568
determineInitialState();
@@ -83,6 +86,9 @@ class Chassis : public ChassisInherit
8386
void startPOHCounter();
8487

8588
private:
89+
/** @brief Create systemd target instance names and mapping table */
90+
void createSystemdTargetTable();
91+
8692
/** @brief Determine initial chassis state and set internally */
8793
void determineInitialState();
8894

@@ -137,6 +143,12 @@ class Chassis : public ChassisInherit
137143
/** @brief Watch for any changes to UPS properties **/
138144
std::unique_ptr<sdbusplus::bus::match_t> uPowerPropChangeSignal;
139145

146+
/** @brief Chassis id. **/
147+
const size_t id = 0;
148+
149+
/** @brief Transition state to systemd target mapping table. **/
150+
std::map<Transition, std::string> systemdTargetTable;
151+
140152
/** @brief Used to Set value of POHCounter */
141153
uint32_t pohCounter(uint32_t value) override;
142154

chassis_state_manager_main.cpp

+33-6
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,53 @@
22

33
#include "chassis_state_manager.hpp"
44

5+
#include <getopt.h>
6+
57
#include <sdbusplus/bus.hpp>
68

79
#include <cstdlib>
810
#include <exception>
911
#include <iostream>
1012

11-
int main()
13+
int main(int argc, char** argv)
1214
{
15+
size_t chassisId = 0;
16+
int arg;
17+
int optIndex = 0;
18+
static struct option longOpts[] = {{"chassis", required_argument, 0, 'c'},
19+
{0, 0, 0, 0}};
20+
21+
while ((arg = getopt_long(argc, argv, "c:", longOpts, &optIndex)) != -1)
22+
{
23+
switch (arg)
24+
{
25+
case 'c':
26+
chassisId = std::stoul(optarg);
27+
break;
28+
default:
29+
break;
30+
}
31+
}
32+
1333
auto bus = sdbusplus::bus::new_default();
1434

15-
// For now, we only have one instance of the chassis
16-
auto objPathInst = std::string{CHASSIS_OBJPATH} + '0';
35+
auto chassisBusName =
36+
std::string{CHASSIS_BUSNAME} + std::to_string(chassisId);
37+
auto objPathInst = std::string{CHASSIS_OBJPATH} + std::to_string(chassisId);
1738

1839
// Add sdbusplus ObjectManager.
1940
sdbusplus::server::manager::manager objManager(bus, objPathInst.c_str());
41+
phosphor::state::manager::Chassis manager(bus, objPathInst.c_str(),
42+
chassisId);
2043

21-
phosphor::state::manager::Chassis manager(bus, objPathInst.c_str());
44+
// For backwards compatibility, request a busname without chassis id if
45+
// input id is 0.
46+
if (chassisId == 0)
47+
{
48+
bus.request_name(CHASSIS_BUSNAME);
49+
}
2250

23-
bus.request_name(CHASSIS_BUSNAME);
51+
bus.request_name(chassisBusName.c_str());
2452
manager.startPOHCounter();
25-
2653
return 0;
2754
}

host_check.cpp

+15-7
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ constexpr auto CONDITION_HOST_PROPERTY = "CurrentFirmwareCondition";
3939
constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
4040

4141
constexpr auto CHASSIS_STATE_SVC = "xyz.openbmc_project.State.Chassis";
42-
constexpr auto CHASSIS_STATE_PATH = "/xyz/openbmc_project/state/chassis0";
42+
constexpr auto CHASSIS_STATE_PATH = "/xyz/openbmc_project/state/chassis";
4343
constexpr auto CHASSIS_STATE_INTF = "xyz.openbmc_project.State.Chassis";
4444
constexpr auto CHASSIS_STATE_POWER_PROP = "CurrentPowerState";
4545

@@ -124,11 +124,20 @@ bool checkFirmwareConditionRunning(sdbusplus::bus::bus& bus)
124124
}
125125

126126
// Helper function to check if chassis power is on
127-
bool isChassiPowerOn(sdbusplus::bus::bus& bus)
127+
bool isChassiPowerOn(sdbusplus::bus::bus& bus, size_t id)
128128
{
129+
auto svcname = std::string{CHASSIS_STATE_SVC};
130+
auto objpath = std::string{CHASSIS_STATE_PATH};
131+
132+
if (id != 0)
133+
{
134+
svcname += std::to_string(id);
135+
objpath += std::to_string(id);
136+
}
137+
129138
try
130139
{
131-
auto method = bus.new_method_call(CHASSIS_STATE_SVC, CHASSIS_STATE_PATH,
140+
auto method = bus.new_method_call(svcname.c_str(), objpath.c_str(),
132141
PROPERTY_INTERFACE, "Get");
133142
method.append(CHASSIS_STATE_INTF, CHASSIS_STATE_POWER_PROP);
134143

@@ -147,21 +156,20 @@ bool isChassiPowerOn(sdbusplus::bus::bus& bus)
147156
{
148157
error("Error reading Chassis Power State, error: {ERROR}, "
149158
"service: {SERVICE} path: {PATH}",
150-
"ERROR", e, "SERVICE", CHASSIS_STATE_SVC, "PATH",
151-
CHASSIS_STATE_PATH);
159+
"ERROR", e, "SERVICE", svcname.c_str(), "PATH", objpath.c_str());
152160
throw;
153161
}
154162
return false;
155163
}
156164

157-
bool isHostRunning()
165+
bool isHostRunning(size_t id)
158166
{
159167
info("Check if host is running");
160168

161169
auto bus = sdbusplus::bus::new_default();
162170

163171
// No need to check if chassis power is not on
164-
if (!isChassiPowerOn(bus))
172+
if (!isChassiPowerOn(bus, id))
165173
{
166174
info("Chassis power not on, exit");
167175
return false;

host_check.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <cstddef>
4+
35
namespace phosphor
46
{
57
namespace state
@@ -11,7 +13,7 @@ namespace manager
1113
*
1214
* @return True if host running, False otherwise
1315
*/
14-
bool isHostRunning();
16+
bool isHostRunning(size_t hostId = 0);
1517

1618
} // namespace manager
1719
} // namespace state

host_state_manager.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void Host::determineInitialState()
7979
{
8080

8181
if (stateActive(getTarget(server::Host::HostState::Running)) ||
82-
isHostRunning())
82+
isHostRunning(id))
8383
{
8484
info("Initial Host State will be Running");
8585
server::Host::currentHostState(HostState::Running);

meson.build

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ executable('phosphor-chassis-state-manager',
105105
'utils.cpp',
106106
dependencies: [
107107
sdbusplus, sdeventplus, phosphorlogging,
108-
phosphordbusinterfaces, cppfs, libgpiod
108+
phosphordbusinterfaces, cppfs, libgpiod, fmt
109109
],
110110
implicit_include_directories: true,
111111
install: true

service_files/meson.build

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ unit_files = [
77
88
99
'xyz.openbmc_project.State.BMC.service',
10-
'xyz.openbmc_project.State.Chassis.service',
10+
'xyz.openbmc_project.State.Chassis@.service',
1111
1212
'xyz.openbmc_project.State.Hypervisor.service',
1313
'xyz.openbmc_project.State.ScheduledHostTransition.service',

service_files/xyz.openbmc_project.State.Chassis.service

-17
This file was deleted.

service_files/[email protected]

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[Unit]
2+
Description=Phosphor Chassis%i State Manager
3+
Before=mapper-wait@-xyz-openbmc_project-state-chassis%i.service
4+
Wants=obmc-mapper.target
5+
After=obmc-mapper.target
6+
After=org.openbmc.control.Power@%i.service
7+
Wants=xyz.openbmc_project.Logging.service
8+
After=xyz.openbmc_project.Logging.service
9+
10+
[Service]
11+
ExecStart=/usr/bin/phosphor-chassis-state-manager --chassis %i
12+
Restart=always
13+
Type=dbus
14+
BusName=xyz.openbmc_project.State.Chassis%i
15+
16+
[Install]
17+
WantedBy=multi-user.target

0 commit comments

Comments
 (0)