virthttp  0.0
libvirt http interface
domain_actions_table.hpp
Go to the documentation of this file.
1 //
2 // Created by hugo on 5/13/20.
3 //
4 
5 #pragma once
6 
7 #include "virt_wrap/Domain.hpp"
8 #include "actions_table.hpp"
9 
10 using DomainActionsHdl = DependsOutcome (*)(const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom);
11 class DomainActionsTable : public NamedCallTable<DomainActionsTable, DomainActionsHdl> {
12  private:
14 
15  using Hdl = DomainActionsHdl;
16 
17  constexpr static std::array<std::string_view, 7> keys = {"power_mgt", "name", "memory", "max_memory", "autostart", "send_signal", "send_keys"};
18  constexpr static std::array<Hdl, 7> fcns = {
19  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
20  auto error = [&](auto... args) { return json_res.error(args...), DependsOutcome::FAILURE; };
21  auto pm_message = [&](gsl::czstring<> name, gsl::czstring<> value) {
22  rapidjson::Value msg_val{};
23  msg_val.SetObject();
24  msg_val.AddMember(rapidjson::StringRef(name), rapidjson::StringRef(value), json_res.GetAllocator());
25  json_res.message(msg_val);
27  };
28 
29  constexpr auto getShutdownFlag = getFlag<virt::enums::domain::ShutdownFlag>;
30 
31  const rapidjson::Value* json_flag = nullptr;
32  gsl::czstring<> pm_req{};
33 
34  if (val.IsString()) {
35  pm_req = val.GetString();
36  } else if (val.IsObject()) {
37  auto it_req = val.FindMember("request");
38  auto it_flags = val.FindMember("type");
39  if (it_req == val.MemberEnd())
40  return error(300);
41  if (it_flags != val.MemberEnd())
42  json_flag = &it_flags->value;
43  pm_req = it_req->value.GetString();
44  } else {
45  return error(300);
46  }
47 
48  const auto dom_state = virt::enums::domain::State{EHTag{}, dom.getInfo().state}; // Verified use of EHTag
49 
50  const auto pm_hdl = [&](gsl::czstring<> req_tag, auto flag_ti, auto mem_fcn, int errc, gsl::czstring<> pm_msg, auto prereqs) {
51  using Flag = typename decltype(flag_ti)::type;
52  return [=, &json_flag, &json_res]() {
53  const auto mem_fcn_passthru = [=](auto... args) constexpr { return mem_fcn(args...); }; // WA GCC
54  const auto local_error = [&] {
56  return error(errc);
57  };
58 
59  if (pm_req == std::string_view{req_tag}) {
60  if (prereqs() == DependsOutcome::FAILURE)
62  if (json_flag) {
63  if constexpr (test_sfinae([](auto f) -> std::enable_if_t<!std::is_same_v<decltype(f), Empty>> {}, Flag{})) {
64  constexpr const auto getFlags = getCombinedFlags<Flag>;
65  const auto o_flagset = getFlags(*json_flag, json_res);
66  if (!o_flagset)
68  if (const auto flagset = *o_flagset; !mem_fcn(flagset))
69  return local_error();
70  } else
71  return error(301);
72  } else {
73  if constexpr (test_sfinae([](auto f) { f(); }, mem_fcn_passthru)) {
74  if (!mem_fcn())
75  return local_error();
76  } else
77  return error(301);
78  }
79  return pm_message(req_tag, pm_msg);
80  }
82  };
83  };
84  constexpr auto no_flags = ti<Empty>;
85  return action_scope(
86  pm_hdl("shutdown", ti<virt::enums::domain::ShutdownFlag>, PM_LIFT(dom.shutdown), 200, "Domain is being shutdown",
87  PM_PREREQ(if (dom_state != virt::enums::domain::State::RUNNING) return error(201);)),
88  pm_hdl("destroy", ti<virt::enums::domain::DestroyFlag>, PM_LIFT(dom.destroy), 209, "Domain destroyed",
89  PM_PREREQ(if (!dom.isActive()) return error(210);)),
90  pm_hdl("start", ti<virt::enums::domain::CreateFlag>, PM_LIFT(dom.create), 202, "Domain started",
91  PM_PREREQ(if (dom.isActive()) return error(203);)),
92  pm_hdl("reboot", ti<virt::enums::domain::ShutdownFlag>, PM_LIFT(dom.reboot), 213, "Domain is being rebooted",
93  PM_PREREQ(if (dom_state != virt::enums::domain::State::RUNNING) return error(201);)),
94  pm_hdl("reset", no_flags, PM_LIFT(dom.reset), 214, "Domain was reset", PM_PREREQ(if (!dom.isActive()) return error(210);)),
95  pm_hdl("suspend", no_flags, PM_LIFT(dom.suspend), 215, "Domain suspended",
96  PM_PREREQ(if (dom_state != virt::enums::domain::State::RUNNING) return error(201);)),
97  pm_hdl("resume", no_flags, PM_LIFT(dom.resume), 212, "Domain resumed",
98  PM_PREREQ(if (dom_state != virt::enums::domain::State::PAUSED) return error(211);)),
99  [&]() { return error(300); });
100  },
101  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
102  auto error = [&](auto... args) { return json_res.error(args...), DependsOutcome::FAILURE; };
103  if (!val.IsString())
104  return error(0);
105  if (!dom.rename(val.GetString()))
106  return error(205);
108  },
109  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
110  auto error = [&](auto... args) { return json_res.error(args...), DependsOutcome::FAILURE; };
111  if (!val.IsInt())
112  return error(0);
113  if (!dom.setMemory(val.GetInt()))
114  return error(206);
116  },
117  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
118  auto error = [&](auto... args) { return json_res.error(args...), DependsOutcome::FAILURE; };
119  if (!val.IsInt())
120  return error(0);
121  if (!dom.setMaxMemory(val.GetInt()))
122  return error(207);
124  },
125  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
126  auto error = [&](auto... args) { return json_res.error(args...), DependsOutcome::FAILURE; };
127  if (!val.IsBool())
128  return error(0);
129  if (!dom.setAutoStart(val.GetBool()))
130  return error(208);
132  },
133  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
134  const auto res = wrap_fcn(
135  val, json_res, [&](auto... args) { return dom.sendProcessSignal(args...); }, WArg<JTag::Int64>{"pid"},
138  },
139  +[](const rapidjson::Value& val, JsonRes& json_res, virt::Domain& dom) -> DependsOutcome {
140  auto error = [&](auto... args) { return json_res.error(args...), DependsOutcome::FAILURE; };
141  if (!val.IsObject())
142  return error(0);
143 
144  const auto keycodeset_opt = extract_param<JTag::Enum, JTag::None, virt::enums::domain::KeycodeSet>(val, "keycode_set", json_res);
145  if (!keycodeset_opt)
146  return error(0);
147  const auto keycodeset = *keycodeset_opt;
148 
149  const auto holdtime_opt = extract_param<JTag::Uint32>(val, "hold_time", json_res);
150  if (!holdtime_opt)
151  return error(0);
152  const auto holdtime = *holdtime_opt;
153 
154  const auto keys_opt = extract_param<JTag::Array, JTag::Uint32>(val, "keys", json_res);
155  if (!keys_opt)
156  return error(0);
157  const auto keys = *keys_opt;
158 
159  return dom.sendKey(keycodeset, holdtime, gsl::span(keys.data(), keys.size())) ? DependsOutcome::SUCCESS : DependsOutcome::FAILURE;
160  }};
161  static_assert(keys.size() == fcns.size());
162 } constexpr static const domain_actions_table{};
DependsOutcome
Definition: depends.hpp:11
#define PM_PREREQ(...)
Definition: actions_table.hpp:14
Definition: domain_actions_table.hpp:11
auto wrap_fcn(const rapidjson::Value &val, JsonRes &json_res, Fcn fcn, Args...args) noexcept
Definition: json2virt.hpp:186
Definition: utility.hpp:55
static constexpr auto RUNNING
Definition: State.hpp:31
Definition: State.hpp:7
Definition: json2virt.hpp:134
Logger logger
Definition: logger.hpp:58
void error(Ts...msg)
Definition: logger.hpp:25
#define PM_LIFT(mem_fn)
Definition: actions_table.hpp:13
class ErrorMessages error_messages
Definition: json_utils.hpp:21
constexpr auto action_scope
Definition: actions_table.hpp:51
constexpr auto test_sfinae(Lambda lambda, Ts &&...) -> decltype(lambda(std::declval< Ts >()...), bool
Definition: utility.hpp:37
static constexpr auto PAUSED
Definition: State.hpp:33
Definition: Domain.hpp:96
Definition: utility.hpp:27
Definition: actions_table.hpp:60
DomainActionsTable domain_actions_table
DependsOutcome(*)(const rapidjson::Value &val, JsonRes &json_res, virt::Domain &dom) DomainActionsHdl
Definition: domain_actions_table.hpp:10