xref: /openbmc/phosphor-fan-presence/control/json/dbus_zone.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 "config.h"
17 
18 #include "dbus_zone.hpp"
19 
20 #include "dbus_paths.hpp"
21 #include "sdbusplus.hpp"
22 #include "zone.hpp"
23 
24 #include <cereal/archives/json.hpp>
25 #include <cereal/cereal.hpp>
26 #include <phosphor-logging/lg2.hpp>
27 
28 #include <algorithm>
29 #include <filesystem>
30 #include <fstream>
31 
32 namespace phosphor::fan::control::json
33 {
34 
35 namespace fs = std::filesystem;
36 
DBusZone(const Zone & zone)37 DBusZone::DBusZone(const Zone& zone) :
38     ThermalModeIntf(util::SDBusPlus::getBus(),
39                     (fs::path{CONTROL_OBJPATH} /= zone.getName()).c_str(),
40                     ThermalModeIntf::action::defer_emit),
41     _zone(zone)
42 {}
43 
current(std::string value)44 std::string DBusZone::current(std::string value)
45 {
46     auto current = ThermalModeIntf::current();
47     std::transform(value.begin(), value.end(), value.begin(), toupper);
48 
49     auto supported = ThermalModeIntf::supported();
50     auto isSupported =
51         std::any_of(supported.begin(), supported.end(), [&value](auto& s) {
52             std::transform(s.begin(), s.end(), s.begin(), toupper);
53             return value == s;
54         });
55 
56     if (isSupported && value != current)
57     {
58         current = ThermalModeIntf::current(value);
59         if (_zone.isPersisted(thermalModeIntf, currentProp))
60         {
61             saveCurrentMode();
62         }
63     }
64 
65     return current;
66 }
67 
restoreCurrentMode()68 void DBusZone::restoreCurrentMode()
69 {
70     auto current = ThermalModeIntf::current();
71     fs::path path{CONTROL_PERSIST_ROOT_PATH};
72     // Append this object's name and property description
73     path /= _zone.getName();
74     path /= "CurrentMode";
75     fs::create_directories(path.parent_path());
76 
77     try
78     {
79         if (fs::exists(path))
80         {
81             std::ifstream ifs(path.c_str(), std::ios::in | std::ios::binary);
82             cereal::JSONInputArchive iArch(ifs);
83             iArch(current);
84         }
85     }
86     catch (const std::exception& e)
87     {
88         // Include possible exception when removing file, otherwise ec = 0
89         std::error_code ec;
90         fs::remove(path, ec);
91         lg2::error("Unable to restore persisted `Current` thermal mode "
92                    "property ({ERROR}, ec: {ERROR_CODE})",
93                    "ERROR", e, "ERROR_CODE", ec.value());
94         current = ThermalModeIntf::current();
95     }
96 
97     this->current(current);
98 }
99 
saveCurrentMode()100 void DBusZone::saveCurrentMode()
101 {
102     fs::path path{CONTROL_PERSIST_ROOT_PATH};
103     // Append this object's name and property description
104     path /= _zone.getName();
105     path /= "CurrentMode";
106     std::ofstream ofs(path.c_str(), std::ios::binary);
107     cereal::JSONOutputArchive oArch(ofs);
108     oArch(ThermalModeIntf::current());
109 }
110 
111 } // namespace phosphor::fan::control::json
112