xref: /openbmc/phosphor-fan-presence/control/json/actions/net_target_decrease.cpp (revision 64b5ac203518568ec8b7569d0e785352278f2472)
1 /**
2  * Copyright © 2021 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 "net_target_decrease.hpp"
17 
18 #include "../manager.hpp"
19 #include "../zone.hpp"
20 #include "action.hpp"
21 #include "group.hpp"
22 
23 #include <nlohmann/json.hpp>
24 #include <phosphor-logging/lg2.hpp>
25 
26 #include <algorithm>
27 #include <variant>
28 
29 namespace phosphor::fan::control::json
30 {
31 
32 using json = nlohmann::json;
33 
NetTargetDecrease(const json & jsonObj,const std::vector<Group> & groups)34 NetTargetDecrease::NetTargetDecrease(const json& jsonObj,
35                                      const std::vector<Group>& groups) :
36     ActionBase(jsonObj, groups)
37 {
38     setState(jsonObj);
39     setDelta(jsonObj);
40 }
41 
run(Zone & zone)42 void NetTargetDecrease::run(Zone& zone)
43 {
44     if (!_stateParameter.empty())
45     {
46         auto s = Manager::getParameter(_stateParameter);
47         if (!s)
48         {
49             return;
50         }
51         _state = *s;
52     }
53 
54     auto netDelta = zone.getDecDelta();
55     for (const auto& group : _groups)
56     {
57         for (const auto& member : group.getMembers())
58         {
59             try
60             {
61                 auto value = Manager::getObjValueVariant(
62                     member, group.getInterface(), group.getProperty());
63                 if (std::holds_alternative<int64_t>(value) ||
64                     std::holds_alternative<double>(value))
65                 {
66                     if (value >= _state)
67                     {
68                         // No decrease allowed for this group
69                         netDelta = 0;
70                         break;
71                     }
72                     else
73                     {
74                         // Decrease factor is the difference in configured state
75                         // to the current value's state
76                         uint64_t deltaFactor = 0;
77                         if (auto dblPtr = std::get_if<double>(&value))
78                         {
79                             deltaFactor = static_cast<uint64_t>(
80                                 std::get<double>(_state) - *dblPtr);
81                         }
82                         else
83                         {
84                             deltaFactor = static_cast<uint64_t>(
85                                 std::get<int64_t>(_state) -
86                                 std::get<int64_t>(value));
87                         }
88 
89                         // Multiply the decrease factor by the configured delta
90                         // to get the net decrease delta for the given group
91                         // member. The lowest net decrease delta of the entire
92                         // group is the decrease requested.
93                         if (netDelta == 0)
94                         {
95                             netDelta = deltaFactor * _delta;
96                         }
97                         else
98                         {
99                             netDelta = std::min(netDelta, deltaFactor * _delta);
100                         }
101                     }
102                 }
103                 else if (std::holds_alternative<bool>(value) ||
104                          std::holds_alternative<std::string>(value))
105                 {
106                     // Where a group of booleans or strings equal the state
107                     // provided, request a decrease of the configured delta
108                     if (_state == value)
109                     {
110                         if (netDelta == 0)
111                         {
112                             netDelta = _delta;
113                         }
114                         else
115                         {
116                             netDelta = std::min(netDelta, _delta);
117                         }
118                     }
119                 }
120                 else
121                 {
122                     // Unsupported group member type for this action
123                     lg2::error(
124                         "Action {ACTION_NAME}: Unsupported group member type "
125                         "given. [object = {MEMBER} : {GROUP_INTERFACE} : {GROUP_PROPERTY}]",
126                         "ACTION_NAME", ActionBase::getName(), "MEMBER", member,
127                         "GROUP_INTERFACE", group.getInterface(),
128                         "GROUP_PROPERTY", group.getProperty());
129                 }
130             }
131             catch (const std::out_of_range& oore)
132             {
133                 // Property value not found, netDelta unchanged
134             }
135         }
136         // Update group's decrease allowed state
137         zone.setDecreaseAllow(group.getName(), !(netDelta == 0));
138     }
139     // Request target decrease to occur on decrease interval
140     zone.requestDecrease(netDelta);
141 }
142 
setState(const json & jsonObj)143 void NetTargetDecrease::setState(const json& jsonObj)
144 {
145     if (jsonObj.contains("state"))
146     {
147         _state = getJsonValue(jsonObj["state"]);
148     }
149     else if (jsonObj.contains("state_parameter_name"))
150     {
151         _stateParameter = jsonObj["state_parameter_name"].get<std::string>();
152     }
153     else
154     {
155         throw ActionParseError{
156             ActionBase::getName(),
157             "Missing required state or state_parameter_name value"};
158     }
159 }
160 
setDelta(const json & jsonObj)161 void NetTargetDecrease::setDelta(const json& jsonObj)
162 {
163     if (!jsonObj.contains("delta"))
164     {
165         throw ActionParseError{ActionBase::getName(),
166                                "Missing required delta value"};
167     }
168     _delta = jsonObj["delta"].get<uint64_t>();
169 }
170 
171 } // namespace phosphor::fan::control::json
172