Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mgr / StandbyPyModules.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2016 John Spray <john.spray@redhat.com>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  */
13
14 #pragma once
15
16 #include "Python.h"
17
18 #include <string>
19 #include <map>
20
21 #include "common/Thread.h"
22 #include "common/Mutex.h"
23
24 #include "mgr/Gil.h"
25 #include "mon/MonClient.h"
26 #include "mon/MgrMap.h"
27 #include "mgr/PyModuleRunner.h"
28
29 typedef std::map<std::string, std::string> PyModuleConfig;
30
31 /**
32  * State that is read by all modules running in standby mode
33  */
34 class StandbyPyModuleState
35 {
36   mutable Mutex lock{"StandbyPyModuleState::lock"};
37
38   MgrMap mgr_map;
39   PyModuleConfig config_cache;
40
41   mutable Cond config_loaded;
42
43 public:
44
45   bool is_config_loaded = false;
46
47   void set_mgr_map(const MgrMap &mgr_map_)
48   {
49     Mutex::Locker l(lock);
50
51     mgr_map = mgr_map_;
52   }
53
54   void loaded_config(const PyModuleConfig &config_)
55   {
56     Mutex::Locker l(lock);
57
58     config_cache = config_;
59     is_config_loaded = true;
60     config_loaded.Signal();
61   }
62
63   template<typename Callback, typename...Args>
64   void with_mgr_map(Callback&& cb, Args&&...args) const
65   {
66     Mutex::Locker l(lock);
67     std::forward<Callback>(cb)(mgr_map, std::forward<Args>(args)...);
68   }
69
70   template<typename Callback, typename...Args>
71   auto with_config(Callback&& cb, Args&&... args) const ->
72     decltype(cb(config_cache, std::forward<Args>(args)...)) {
73     Mutex::Locker l(lock);
74
75     if (!is_config_loaded) {
76       config_loaded.Wait(lock);
77     }
78
79     return std::forward<Callback>(cb)(config_cache, std::forward<Args>(args)...);
80   }
81 };
82
83
84 class StandbyPyModule : public PyModuleRunner
85 {
86   StandbyPyModuleState &state;
87
88   public:
89
90   StandbyPyModule(
91       StandbyPyModuleState &state_,
92       const std::string &module_name_,
93       PyObject *pClass_,
94       const SafeThreadState &pMyThreadState_)
95     :
96       PyModuleRunner(module_name_, pClass_, pMyThreadState_),
97       state(state_)
98   {
99   }
100
101   bool get_config(const std::string &key, std::string *value) const;
102   std::string get_active_uri() const;
103
104   int load();
105 };
106
107 class StandbyPyModules
108 {
109 private:
110   mutable Mutex lock{"StandbyPyModules::lock"};
111   std::map<std::string, std::unique_ptr<StandbyPyModule>> modules;
112
113   MonClient *monc;
114
115   StandbyPyModuleState state;
116
117   void load_config();
118   class LoadConfigThread : public Thread
119   {
120     protected:
121       MonClient *monc;
122       StandbyPyModuleState *state;
123     public:
124     LoadConfigThread(MonClient *monc_, StandbyPyModuleState *state_)
125       : monc(monc_), state(state_)
126     {}
127     void *entry() override;
128   };
129
130   LoadConfigThread load_config_thread;
131
132 public:
133
134   StandbyPyModules(
135       MonClient *monc_,
136       const MgrMap &mgr_map_);
137
138   int start_one(std::string const &module_name,
139                 PyObject *pClass,
140                 const SafeThreadState &pMyThreadState);
141
142   void shutdown();
143
144   void handle_mgr_map(const MgrMap &mgr_map)
145   {
146     state.set_mgr_map(mgr_map);
147   }
148
149 };