]> git.proxmox.com Git - ceph.git/blame - ceph/src/mgr/PyModule.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / mgr / PyModule.h
CommitLineData
11fdf7f2
TL
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) 2017 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 <map>
17#include <memory>
18#include <string>
19#include <vector>
20#include <boost/optional.hpp>
9f95a23c 21#include "common/ceph_mutex.h"
11fdf7f2
TL
22#include "Python.h"
23#include "Gil.h"
24#include "mon/MgrMap.h"
25
26
27class MonClient;
28
20effc67
TL
29std::string handle_pyerror(bool generate_crash_dump = false,
30 std::string module = {},
31 std::string caller = {});
11fdf7f2
TL
32
33std::string peek_pyerror();
34
35/**
36 * A Ceph CLI command description provided from a Python module
37 */
38class ModuleCommand {
39public:
40 std::string cmdstring;
41 std::string helpstring;
42 std::string perm;
43 bool polling;
44
45 // Call the ActivePyModule of this name to handle the command
46 std::string module_name;
47};
48
49class PyModule
50{
9f95a23c 51 mutable ceph::mutex lock = ceph::make_mutex("PyModule::lock");
11fdf7f2
TL
52private:
53 const std::string module_name;
54 std::string get_site_packages();
55 int load_subclass_of(const char* class_name, PyObject** py_class);
56
57 // Did the MgrMap identify this module as one that should run?
58 bool enabled = false;
59
60 // Did the MgrMap flag this module as always on?
61 bool always_on = false;
62
63 // Did we successfully import this python module and look up symbols?
64 // (i.e. is it possible to instantiate a MgrModule subclass instance?)
65 bool loaded = false;
66
67 // Did the module identify itself as being able to run?
68 // (i.e. should we expect instantiating and calling serve() to work?)
69 bool can_run = false;
70
71 // Did the module encounter an unexpected error while running?
72 // (e.g. throwing an exception from serve())
73 bool failed = false;
74
75 // Populated if loaded, can_run or failed indicates a problem
76 std::string error_string;
77
78 // Helper for loading MODULE_OPTIONS and COMMANDS members
79 int walk_dict_list(
80 const std::string &attr_name,
81 std::function<int(PyObject*)> fn);
82
83 int load_commands();
84 std::vector<ModuleCommand> commands;
85
9f95a23c 86 int register_options(PyObject *cls);
11fdf7f2
TL
87 int load_options();
88 std::map<std::string, MgrMap::ModuleOption> options;
89
20effc67
TL
90 int load_notify_types();
91 std::set<std::string> notify_types;
92
11fdf7f2 93public:
f67539c2 94 static std::string mgr_store_prefix;
11fdf7f2
TL
95
96 SafeThreadState pMyThreadState;
97 PyObject *pClass = nullptr;
98 PyObject *pStandbyClass = nullptr;
99
100 explicit PyModule(const std::string &module_name_)
101 : module_name(module_name_)
102 {
103 }
104
105 ~PyModule();
106
107 bool is_option(const std::string &option_name);
108 const std::map<std::string,MgrMap::ModuleOption>& get_options() const {
109 return options;
110 }
111
112 PyObject *get_typed_option_value(
113 const std::string& option,
114 const std::string& value);
115
116 int load(PyThreadState *pMainThreadState);
11fdf7f2
TL
117 static PyObject* init_ceph_logger();
118 static PyObject* init_ceph_module();
11fdf7f2
TL
119
120 void set_enabled(const bool enabled_)
121 {
122 enabled = enabled_;
123 }
124
125 void set_always_on(const bool always_on_) {
126 always_on = always_on_;
127 }
128
129 /**
130 * Extend `out` with the contents of `this->commands`
131 */
132 void get_commands(std::vector<ModuleCommand> *out) const
133 {
134 std::lock_guard l(lock);
135 ceph_assert(out != nullptr);
136 out->insert(out->end(), commands.begin(), commands.end());
137 }
138
139
140 /**
141 * Mark the module as failed, recording the reason in the error
142 * string.
143 */
144 void fail(const std::string &reason)
145 {
146 std::lock_guard l(lock);
147 failed = true;
148 error_string = reason;
149 }
150
151 bool is_enabled() const {
152 std::lock_guard l(lock);
153 return enabled || always_on;
154 }
155
156 bool is_failed() const { std::lock_guard l(lock) ; return failed; }
157 bool is_loaded() const { std::lock_guard l(lock) ; return loaded; }
158 bool is_always_on() const { std::lock_guard l(lock) ; return always_on; }
159
20effc67
TL
160 bool should_notify(const std::string& notify_type) const {
161 return notify_types.count(notify_type);
162 }
163
11fdf7f2
TL
164 const std::string &get_name() const {
165 std::lock_guard l(lock) ; return module_name;
166 }
167 const std::string &get_error_string() const {
168 std::lock_guard l(lock) ; return error_string;
169 }
170 bool get_can_run() const {
171 std::lock_guard l(lock) ; return can_run;
172 }
173};
174
175typedef std::shared_ptr<PyModule> PyModuleRef;
176
177class PyModuleConfig {
178public:
9f95a23c 179 mutable ceph::mutex lock = ceph::make_mutex("PyModuleConfig::lock");
11fdf7f2
TL
180 std::map<std::string, std::string> config;
181
182 PyModuleConfig();
183
184 PyModuleConfig(PyModuleConfig &mconfig);
185
186 ~PyModuleConfig();
187
20effc67 188 std::pair<int, std::string> set_config(
11fdf7f2
TL
189 MonClient *monc,
190 const std::string &module_name,
20effc67 191 const std::string &key, const std::optional<std::string>& val);
11fdf7f2
TL
192
193};