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