141e76f84SMatt Spinler /**
241e76f84SMatt Spinler * Copyright © 2021 IBM Corporation
341e76f84SMatt Spinler *
441e76f84SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License");
541e76f84SMatt Spinler * you may not use this file except in compliance with the License.
641e76f84SMatt Spinler * You may obtain a copy of the License at
741e76f84SMatt Spinler *
841e76f84SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0
941e76f84SMatt Spinler *
1041e76f84SMatt Spinler * Unless required by applicable law or agreed to in writing, software
1141e76f84SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS,
1241e76f84SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1341e76f84SMatt Spinler * See the License for the specific language governing permissions and
1441e76f84SMatt Spinler * limitations under the License.
1541e76f84SMatt Spinler */
1641e76f84SMatt Spinler #include "get_managed_objects.hpp"
1741e76f84SMatt Spinler
1841e76f84SMatt Spinler #include "../manager.hpp"
1941e76f84SMatt Spinler #include "event.hpp"
2041e76f84SMatt Spinler
2141e76f84SMatt Spinler namespace phosphor::fan::control::json
2241e76f84SMatt Spinler {
2341e76f84SMatt Spinler
2441e76f84SMatt Spinler using json = nlohmann::json;
2541e76f84SMatt Spinler
GetManagedObjects(const json & jsonObj,const std::vector<Group> & groups)2641e76f84SMatt Spinler GetManagedObjects::GetManagedObjects(const json& jsonObj,
2741e76f84SMatt Spinler const std::vector<Group>& groups) :
2841e76f84SMatt Spinler ActionBase(jsonObj, groups)
2941e76f84SMatt Spinler {
3041e76f84SMatt Spinler setActions(jsonObj);
3141e76f84SMatt Spinler }
3241e76f84SMatt Spinler
run(Zone & zone)3341e76f84SMatt Spinler void GetManagedObjects::run(Zone& zone)
3441e76f84SMatt Spinler {
3541e76f84SMatt Spinler std::set<std::string> services;
3641e76f84SMatt Spinler
3741e76f84SMatt Spinler // Call Manager::addObjects to refresh the values of the group members.
3841e76f84SMatt Spinler // If there is an ObjectManager interface that handles them, then
3941e76f84SMatt Spinler // the code can combine all members in the same service down to one call.
4041e76f84SMatt Spinler // If no ObjectManager, then still need addObjects calls for each.
4141e76f84SMatt Spinler for (const auto& group : _groups)
4241e76f84SMatt Spinler {
4341e76f84SMatt Spinler for (const auto& member : group.getMembers())
4441e76f84SMatt Spinler {
45cd34ac50SMatt Spinler try
46cd34ac50SMatt Spinler {
4741e76f84SMatt Spinler std::vector<std::string> objMgrPaths;
4841e76f84SMatt Spinler
4941e76f84SMatt Spinler const auto& service =
5041e76f84SMatt Spinler zone.getManager()->getService(member, group.getInterface());
5141e76f84SMatt Spinler
5241e76f84SMatt Spinler if (!service.empty())
5341e76f84SMatt Spinler {
5441e76f84SMatt Spinler objMgrPaths = zone.getManager()->getPaths(
5541e76f84SMatt Spinler service, "org.freedesktop.DBus.ObjectManager");
5641e76f84SMatt Spinler }
5741e76f84SMatt Spinler else
5841e76f84SMatt Spinler {
5941e76f84SMatt Spinler continue;
6041e76f84SMatt Spinler }
6141e76f84SMatt Spinler
6241e76f84SMatt Spinler // Look for the ObjectManager as an ancestor of the path.
63*dfddd648SPatrick Williams auto hasObjMgr = std::any_of(
64*dfddd648SPatrick Williams objMgrPaths.begin(), objMgrPaths.end(),
6541e76f84SMatt Spinler [member](const auto& path) {
6641e76f84SMatt Spinler return member.find(path) != std::string::npos;
6741e76f84SMatt Spinler });
6841e76f84SMatt Spinler
6941e76f84SMatt Spinler if (!hasObjMgr || services.find(service) == services.end())
7041e76f84SMatt Spinler {
7141e76f84SMatt Spinler if (hasObjMgr)
7241e76f84SMatt Spinler {
7341e76f84SMatt Spinler services.insert(service);
7441e76f84SMatt Spinler }
7541e76f84SMatt Spinler
7641e76f84SMatt Spinler zone.getManager()->addObjects(member, group.getInterface(),
7741e76f84SMatt Spinler group.getProperty());
7841e76f84SMatt Spinler }
7941e76f84SMatt Spinler }
80cd34ac50SMatt Spinler catch (const std::exception& e)
81cd34ac50SMatt Spinler {
82cd34ac50SMatt Spinler // May have been called from a name_owner_changed trigger
83cd34ac50SMatt Spinler // and the service may have been lost.
84cd34ac50SMatt Spinler }
85cd34ac50SMatt Spinler }
8641e76f84SMatt Spinler }
8741e76f84SMatt Spinler
8841e76f84SMatt Spinler // Perform the actions
8941e76f84SMatt Spinler std::for_each(_actions.begin(), _actions.end(),
9041e76f84SMatt Spinler [](auto& action) { action->run(); });
9141e76f84SMatt Spinler }
9241e76f84SMatt Spinler
setZones(std::vector<std::reference_wrapper<Zone>> & zones)9341e76f84SMatt Spinler void GetManagedObjects::setZones(
9441e76f84SMatt Spinler std::vector<std::reference_wrapper<Zone>>& zones)
9541e76f84SMatt Spinler {
9641e76f84SMatt Spinler for (auto& zone : zones)
9741e76f84SMatt Spinler {
9841e76f84SMatt Spinler this->addZone(zone);
9941e76f84SMatt Spinler // Add zone to _actions
10041e76f84SMatt Spinler std::for_each(_actions.begin(), _actions.end(),
10141e76f84SMatt Spinler [&zone](std::unique_ptr<ActionBase>& action) {
10241e76f84SMatt Spinler action->addZone(zone);
10341e76f84SMatt Spinler });
10441e76f84SMatt Spinler }
10541e76f84SMatt Spinler }
10641e76f84SMatt Spinler
setActions(const json & jsonObj)10741e76f84SMatt Spinler void GetManagedObjects::setActions(const json& jsonObj)
10841e76f84SMatt Spinler {
10941e76f84SMatt Spinler if (!jsonObj.contains("actions"))
11041e76f84SMatt Spinler {
11141e76f84SMatt Spinler return;
11241e76f84SMatt Spinler }
11341e76f84SMatt Spinler
11441e76f84SMatt Spinler for (const auto& jsonAct : jsonObj["actions"])
11541e76f84SMatt Spinler {
11641e76f84SMatt Spinler if (!jsonAct.contains("name"))
11741e76f84SMatt Spinler {
11841e76f84SMatt Spinler throw ActionParseError{getName(), "Missing required action name"};
11941e76f84SMatt Spinler }
12041e76f84SMatt Spinler
12141e76f84SMatt Spinler // Get any configured profile restrictions on the action
12241e76f84SMatt Spinler std::vector<std::string> profiles;
12341e76f84SMatt Spinler if (jsonAct.contains("profiles"))
12441e76f84SMatt Spinler {
12541e76f84SMatt Spinler profiles = jsonAct["profiles"].get<std::vector<std::string>>();
12641e76f84SMatt Spinler }
12741e76f84SMatt Spinler
12841e76f84SMatt Spinler // Set the groups configured for each action run when the timer expires
12941e76f84SMatt Spinler std::vector<Group> groups;
13041e76f84SMatt Spinler Event::setGroups(jsonAct, profiles, groups);
13141e76f84SMatt Spinler
13241e76f84SMatt Spinler // If no groups on that action, use our own groups instead
13341e76f84SMatt Spinler const std::vector<Group>* groupPtr = &groups;
13441e76f84SMatt Spinler if (groups.empty())
13541e76f84SMatt Spinler {
13641e76f84SMatt Spinler groupPtr = &_groups;
13741e76f84SMatt Spinler }
13841e76f84SMatt Spinler
13941e76f84SMatt Spinler // List of zones is set on these actions by overriden setZones()
14041e76f84SMatt Spinler auto actObj = ActionFactory::getAction(
14141e76f84SMatt Spinler jsonAct["name"].get<std::string>(), jsonAct, *groupPtr, {});
14241e76f84SMatt Spinler if (actObj)
14341e76f84SMatt Spinler {
14441e76f84SMatt Spinler _actions.emplace_back(std::move(actObj));
14541e76f84SMatt Spinler }
14641e76f84SMatt Spinler }
14741e76f84SMatt Spinler }
14841e76f84SMatt Spinler
14941e76f84SMatt Spinler } // namespace phosphor::fan::control::json
150