xref: /openbmc/phosphor-fan-presence/control/json/actions/net_target_increase.cpp (revision fbf4703f3de7fbdbd8388e946bd71c3b760b174c)
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_increase.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/log.hpp>
25 
26 #include <algorithm>
27 #include <format>
28 #include <variant>
29 
30 namespace phosphor::fan::control::json
31 {
32 
33 using json = nlohmann::json;
34 using namespace phosphor::logging;
35 
36 NetTargetIncrease::NetTargetIncrease(const json& jsonObj,
37                                      const std::vector<Group>& groups) :
38     ActionBase(jsonObj, groups)
39 {
40     setState(jsonObj);
41     setDelta(jsonObj);
42 }
43 
44 void NetTargetIncrease::run(Zone& zone)
45 {
46     if (!_stateParameter.empty())
47     {
48         auto s = Manager::getParameter(_stateParameter);
49         if (!s)
50         {
51             return;
52         }
53         _state = *s;
54     }
55 
56     auto netDelta = zone.getIncDelta();
57     for (const auto& group : _groups)
58     {
59         const auto& members = group.getMembers();
60         std::for_each(members.begin(), members.end(),
61                       [this, &zone, &group, &netDelta](const auto& member) {
62             try
63             {
64                 auto value = Manager::getObjValueVariant(
65                     member, group.getInterface(), group.getProperty());
66                 if (std::holds_alternative<int64_t>(value) ||
67                     std::holds_alternative<double>(value))
68                 {
69                     // Where a group of int/doubles are greater than or
70                     // equal to the state(some value) provided, request an
71                     // increase of the configured delta times the difference
72                     // between the group member's value and configured state
73                     // value.
74                     if (value >= _state)
75                     {
76                         uint64_t incDelta = 0;
77                         if (auto dblPtr = std::get_if<double>(&value))
78                         {
79                             incDelta = static_cast<uint64_t>(
80                                 (*dblPtr - std::get<double>(_state)) * _delta);
81                         }
82                         else
83                         {
84                             // Increase by at least a single delta
85                             // to attempt bringing under provided 'state'
86                             auto deltaFactor =
87                                 std::max((std::get<int64_t>(value) -
88                                           std::get<int64_t>(_state)),
89                                          int64_t(1));
90                             incDelta =
91                                 static_cast<uint64_t>(deltaFactor * _delta);
92                         }
93                         netDelta = std::max(netDelta, incDelta);
94                     }
95                 }
96                 else if (std::holds_alternative<bool>(value))
97                 {
98                     // Where a group of booleans equal the state(`true` or
99                     // `false`) provided, request an increase of the
100                     // configured delta
101                     if (_state == value)
102                     {
103                         netDelta = std::max(netDelta, _delta);
104                     }
105                 }
106                 else if (std::holds_alternative<std::string>(value))
107                 {
108                     // Where a group of strings equal the state(some string)
109                     // provided, request an increase of the configured delta
110                     if (_state == value)
111                     {
112                         netDelta = std::max(netDelta, _delta);
113                     }
114                 }
115                 else
116                 {
117                     // Unsupported group member type for this action
118                     log<level::ERR>(
119                         std::format("Action {}: Unsupported group member type "
120                                     "given. [object = {} : {} : {}]",
121                                     ActionBase::getName(), member,
122                                     group.getInterface(), group.getProperty())
123                             .c_str());
124                 }
125             }
126             catch (const std::out_of_range& oore)
127             {
128                 // Property value not found, netDelta unchanged
129             }
130         });
131     }
132     // Request increase to target
133     zone.requestIncrease(netDelta);
134 }
135 
136 void NetTargetIncrease::setState(const json& jsonObj)
137 {
138     if (jsonObj.contains("state"))
139     {
140         _state = getJsonValue(jsonObj["state"]);
141     }
142     else if (jsonObj.contains("state_parameter_name"))
143     {
144         _stateParameter = jsonObj["state_parameter_name"].get<std::string>();
145     }
146     else
147     {
148         throw ActionParseError{
149             ActionBase::getName(),
150             "Missing required state or state_parameter_name value"};
151     }
152 }
153 
154 void NetTargetIncrease::setDelta(const json& jsonObj)
155 {
156     if (!jsonObj.contains("delta"))
157     {
158         throw ActionParseError{ActionBase::getName(),
159                                "Missing required delta value"};
160     }
161     _delta = jsonObj["delta"].get<uint64_t>();
162 }
163 
164 } // namespace phosphor::fan::control::json
165