1 #include "config.h"
2 
3 #include "hypervisor_state_manager.hpp"
4 
5 #include <fmt/format.h>
6 
7 #include <phosphor-logging/elog-errors.hpp>
8 #include <phosphor-logging/log.hpp>
9 #include <sdbusplus/exception.hpp>
10 #include <sdbusplus/server.hpp>
11 
12 #include <fstream>
13 #include <iostream>
14 #include <map>
15 #include <string>
16 
17 namespace phosphor
18 {
19 namespace state
20 {
21 namespace manager
22 {
23 
24 // When you see server:: you know we're referencing our base class
25 namespace server = sdbusplus::xyz::openbmc_project::State::server;
26 using namespace phosphor::logging;
27 
28 server::Host::Transition Hypervisor::requestedHostTransition(Transition value)
29 {
30     log<level::INFO>(fmt::format("Hypervisor state transition request of {}",
31                                  convertForMessage(value))
32                          .c_str());
33 
34     // Only support the transition to On
35     if (value != server::Host::Transition::On)
36     {
37         log<level::ERR>("Hypervisor state only supports a transition to On");
38         // TODO raise appropriate error exception
39         return server::Host::Transition::Off;
40     }
41 
42     // This property is monitored by a separate application (for example PLDM)
43     // which is responsible for propagating the On request to the hypervisor
44 
45     return server::Host::requestedHostTransition(value);
46 }
47 
48 server::Host::HostState Hypervisor::currentHostState(HostState value)
49 {
50     log<level::INFO>(
51         fmt::format("Change to Hypervisor State: {}", convertForMessage(value))
52             .c_str());
53     return server::Host::currentHostState(value);
54 }
55 
56 server::Host::HostState Hypervisor::currentHostState()
57 {
58     return server::Host::currentHostState();
59 }
60 
61 void Hypervisor::updateCurrentHostState(std::string& bootProgress)
62 {
63     log<level::DEBUG>(
64         fmt::format("New BootProgress: {}", bootProgress).c_str());
65 
66     if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
67                         "ProgressStages.SystemInitComplete")
68     {
69         currentHostState(server::Host::HostState::Standby);
70     }
71     else if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
72                              "ProgressStages.OSStart")
73     {
74         currentHostState(server::Host::HostState::TransitioningToRunning);
75     }
76     else if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
77                              "ProgressStages.OSRunning")
78     {
79         currentHostState(server::Host::HostState::Running);
80     }
81     else if (bootProgress == "xyz.openbmc_project.State.Boot.Progress."
82                              "ProgressStages.Unspecified")
83     {
84         // Unspecified is set when the system is powered off so
85         // set the state to off and reset the requested host state
86         // back to its default
87         currentHostState(server::Host::HostState::Off);
88         server::Host::requestedHostTransition(server::Host::Transition::Off);
89     }
90     else
91     {
92         // BootProgress changed and it is not one of the above so
93         // set hypervisor state to off
94         currentHostState(server::Host::HostState::Off);
95     }
96 }
97 
98 void Hypervisor::bootProgressChangeEvent(sdbusplus::message::message& msg)
99 {
100     std::string statusInterface;
101     std::map<std::string, std::variant<std::string>> msgData;
102     msg.read(statusInterface, msgData);
103 
104     auto propertyMap = msgData.find("BootProgress");
105     if (propertyMap != msgData.end())
106     {
107         // Extract the BootProgress
108         auto& bootProgress = std::get<std::string>(propertyMap->second);
109         updateCurrentHostState(bootProgress);
110     }
111 }
112 
113 } // namespace manager
114 } // namespace state
115 } // namespace phosphor
116