xref: /openbmc/phosphor-fan-presence/control/json/actions/override_fan_target.cpp (revision f2040133fa85ba2381c59496744ce29de1e7019a)
1 /**
2  * Copyright © 2022 IBM 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 #include "override_fan_target.hpp"
17 
18 #include "../manager.hpp"
19 #include "../zone.hpp"
20 #include "action.hpp"
21 #include "group.hpp"
22 
23 #include <fmt/format.h>
24 #include <fmt/ranges.h>
25 
26 #include <nlohmann/json.hpp>
27 
28 namespace phosphor::fan::control::json
29 {
30 
31 using json = nlohmann::json;
32 
33 OverrideFanTarget::OverrideFanTarget(const json& jsonObj,
34                                      const std::vector<Group>& groups) :
35     ActionBase(jsonObj, groups)
36 {
37     setCount(jsonObj);
38     setState(jsonObj);
39     setTarget(jsonObj);
40     setFans(jsonObj);
41 }
42 
43 void OverrideFanTarget::run(Zone& zone)
44 {
45     size_t numAtState = 0;
46 
47     for (const auto& group : _groups)
48     {
49         for (const auto& member : group.getMembers())
50         {
51             try
52             {
53                 if (Manager::getObjValueVariant(member, group.getInterface(),
54                                                 group.getProperty()) == _state)
55                 {
56                     numAtState++;
57 
58                     if (numAtState >= _count)
59                     {
60                         break;
61                     }
62                 }
63             }
64             catch (const std::out_of_range&)
65             {}
66         }
67 
68         // lock the fans
69         if (numAtState >= _count)
70         {
71             lockFans(zone);
72             break;
73         }
74     }
75 
76     if (_locked && numAtState < _count)
77     {
78         unlockFans(zone);
79     }
80 }
81 
82 void OverrideFanTarget::lockFans(Zone& zone)
83 {
84     if (!_locked)
85     {
86         record(fmt::format("Adding fan target lock of {} on fans {} zone {}",
87                            _target, _fans, zone.getName()));
88 
89         for (auto& fan : _fans)
90         {
91             zone.lockFanTarget(fan, _target);
92         }
93 
94         _locked = true;
95     }
96 }
97 
98 void OverrideFanTarget::unlockFans(Zone& zone)
99 {
100     record(fmt::format("Un-locking fan target {} on fans {} zone {}", _target,
101                        _fans, zone.getName()));
102 
103     // unlock all fans in this instance
104     for (auto& fan : _fans)
105     {
106         zone.unlockFanTarget(fan, _target);
107     }
108 
109     _locked = false;
110 }
111 
112 void OverrideFanTarget::setCount(const json& jsonObj)
113 {
114     if (!jsonObj.contains("count"))
115     {
116         throw ActionParseError{ActionBase::getName(),
117                                "Missing required count value"};
118     }
119     _count = jsonObj["count"].get<size_t>();
120 }
121 
122 void OverrideFanTarget::setState(const json& jsonObj)
123 {
124     if (!jsonObj.contains("state"))
125     {
126         throw ActionParseError{ActionBase::getName(),
127                                "Missing required state value"};
128     }
129     _state = getJsonValue(jsonObj["state"]);
130 }
131 
132 void OverrideFanTarget::setTarget(const json& jsonObj)
133 {
134     if (!jsonObj.contains("target"))
135     {
136         throw ActionParseError{ActionBase::getName(),
137                                "Missing required target value"};
138     }
139     _target = jsonObj["target"].get<uint64_t>();
140 }
141 
142 void OverrideFanTarget::setFans(const json& jsonObj)
143 {
144     if (!jsonObj.contains("fans"))
145     {
146         throw ActionParseError{ActionBase::getName(),
147                                "Missing required fans value"};
148     }
149 
150     _fans = jsonObj["fans"].get<std::vector<std::string>>();
151 }
152 
153 } // namespace phosphor::fan::control::json
154