JaiaBot  1.19.0
JaiaBot micro-AUV software
liaison_upgrade.h
Go to the documentation of this file.
1 #ifndef LIAISON_UPGRADE_H
2 #define LIAISON_UPGRADE_H
3 
4 #include <Wt/Http/Response>
5 #include <Wt/WFileResource>
6 
7 #include <chrono>
8 #include <future>
9 
10 #include <boost/asio/io_service.hpp>
11 #include <boost/process.hpp>
12 #include <boost/process/pipe.hpp>
13 
14 #include <goby/util/thirdparty/nlohmann/json.hpp>
15 #include <goby/zeromq/liaison/liaison_container.h>
16 
17 #include "config.pb.h"
18 
19 namespace jaiabot
20 {
21 class LiaisonUpgrade : public goby::zeromq::LiaisonContainer
22 {
23  public:
24  LiaisonUpgrade(const goby::apps::zeromq::protobuf::LiaisonConfig& cfg,
25  Wt::WContainerWidget* parent = 0);
26 
27  private:
28  class LogFileResource : public Wt::WResource
29  {
30  public:
31  LogFileResource() {}
32 
33  void set_last_log(const std::string& log) { last_log_ = log; }
34 
35  void handleRequest(const Wt::Http::Request& request, Wt::Http::Response& response) override
36  {
37  suggestFileName("jaiabot_upgrade_ansible_log_" + goby::time::file_str() + ".json");
38  response.addHeader("Content-Type", "application/json");
39  response.out() << last_log_;
40  }
41 
42  private:
43  std::string last_log_;
44  };
45 
46  class AutoScrollWidget : public Wt::WContainerWidget
47  {
48  public:
49  AutoScrollWidget(Wt::WContainerWidget* parent = nullptr) : Wt::WContainerWidget(parent)
50  {
51  this->setOverflow(Wt::WContainerWidget::OverflowAuto, Wt::Horizontal | Wt::Vertical);
52  this->setHeight(300);
53  }
54 
55  void addText(Wt::WString line)
56  {
57  new Wt::WText(line + "<br/>", this);
58 
59  // JavaScript to scroll to the bottom
60  std::string jsCode = "var obj = document.getElementById('" + this->id() +
61  "'); obj.scrollTop = obj.scrollHeight;";
62  Wt::WApplication::instance()->doJavaScript(jsCode);
63  }
64  };
65 
67  {
68  AnsiblePlaybookConfig(const jaiabot::protobuf::UpgradeConfig::AnsiblePlaybook& playbook,
69  Wt::WContainerWidget* parent, LiaisonUpgrade* upgrade,
70  std::size_t playbook_index);
71  AnsiblePlaybookConfig() = delete;
74 
75  std::string file;
76  std::string stdout_file;
77  std::string json_file;
78 
79  Wt::WGroupBox* group_box;
80  Wt::WContainerWidget* group_div;
81  Wt::WContainerWidget* iv_group_div;
82  Wt::WContainerWidget* run_button_div;
83  Wt::WPushButton* run_button;
84  Wt::WContainerWidget* log_button_div;
85  Wt::WPushButton* log_button;
86  Wt::WContainerWidget* stdout_button_div;
87  Wt::WPushButton* stdout_button;
88  Wt::WContainerWidget* result_div;
89  Wt::WText* result_text;
90  Wt::WTable* result_table;
91 
92  Wt::WGroupBox* stdout_group;
93  AutoScrollWidget* stdout_div;
94 
95  std::vector<std::string>::const_iterator run_text_it;
96  // name -> value
97  std::map<std::string, std::string> input_var;
98  // name -> display name
99  std::map<std::string, std::string> output_var;
100  std::vector<std::string> output_var_order;
101 
102  struct ProcessData
103  {
104  ProcessData(const protobuf::UpgradeConfig& cfg, const std::string& playbook_file,
105  const jaiabot::protobuf::UpgradeConfig::AnsiblePlaybook& pb_playbook,
106  const std::string& input_vars, const std::string& ansible_stdout_file,
107  const std::string& ansible_json_file);
108  ~ProcessData();
109 
110  boost::asio::io_service io;
111  std::future<std::string> stderr;
112  boost::process::child process;
113  std::thread io_thread;
114  std::ifstream stdout;
115  };
116  std::unique_ptr<ProcessData> pdata;
117  std::string last_log;
118  std::shared_ptr<LogFileResource> log_resource;
119  const jaiabot::protobuf::UpgradeConfig::AnsiblePlaybook& pb_playbook;
120 
121  void show_stdout();
122  void hide_stdout();
123  };
124  friend struct AnsiblePlaybookConfig;
125 
126  struct Result
127  {
128  enum ResultType
129  {
130  FAILURE,
131  UNREACHABLE,
132  SUCCESS // not FAILURE or UNREACHABLE
133  };
134  ResultType result{SUCCESS};
135  std::map<std::string, std::string> output_vars;
136  };
137 
138  void run_ansible_playbook(std::size_t playbook_index);
139  void set_input_var(int selection_index, Wt::WComboBox* selection, std::string name,
140  std::size_t playbook_index);
141 
142  void process_ansible_json_result(nlohmann::json j, AnsiblePlaybookConfig& playbook);
143  void toggle_stdout(std::size_t playbook_index);
144 
145  void loop();
146  void focus() override { timer_.start(); }
147  void unfocus() override { timer_.stop(); }
148 
149  private:
150  struct SectionWidgets
151  {
152  Wt::WPanel* panel;
153  Wt::WContainerWidget* div;
154  };
155 
156  std::map<std::string, SectionWidgets> sections;
157 
158  const protobuf::UpgradeConfig& cfg_;
159  std::vector<AnsiblePlaybookConfig> playbooks_;
160  Wt::WTimer timer_;
161  static const std::vector<std::string> running_;
162  static const Wt::WColor color_success_;
163  static const Wt::WColor color_failure_;
164 };
165 
166 } // namespace jaiabot
167 
168 #endif
jaiabot::LiaisonUpgrade
Definition: liaison_upgrade.h:21
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::ProcessData
ProcessData(const protobuf::UpgradeConfig &cfg, const std::string &playbook_file, const jaiabot::protobuf::UpgradeConfig::AnsiblePlaybook &pb_playbook, const std::string &input_vars, const std::string &ansible_stdout_file, const std::string &ansible_json_file)
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig
friend struct AnsiblePlaybookConfig
Definition: liaison_upgrade.h:124
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::process
boost::process::child process
Definition: liaison_upgrade.h:112
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::io_thread
std::thread io_thread
Definition: liaison_upgrade.h:113
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::stdout
std::ifstream stdout
Definition: liaison_upgrade.h:114
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::io
boost::asio::io_service io
Definition: liaison_upgrade.h:110
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData
Definition: liaison_upgrade.h:102
jaiabot::LiaisonUpgrade::LiaisonUpgrade
LiaisonUpgrade(const goby::apps::zeromq::protobuf::LiaisonConfig &cfg, Wt::WContainerWidget *parent=0)
jaiabot
Definition: config.pb.h:56
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::~ProcessData
~ProcessData()
jaiabot::LiaisonUpgrade::AnsiblePlaybookConfig::ProcessData::stderr
std::future< std::string > stderr
Definition: liaison_upgrade.h:111