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