]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | ceph-mgr plugin author guide | |
3 | ============================ | |
4 | ||
5 | Creating a plugin | |
6 | ----------------- | |
7 | ||
8 | In pybind/mgr/, create a python module. Within your module, create a class | |
9 | named ``Module`` that inherits from ``MgrModule``. | |
10 | ||
11 | The most important methods to override are: | |
12 | ||
13 | * a ``serve`` member function for server-type modules. This | |
14 | function should block forever. | |
15 | * a ``notify`` member function if your module needs to | |
16 | take action when new cluster data is available. | |
17 | * a ``handle_command`` member function if your module | |
18 | exposes CLI commands. | |
19 | ||
20 | Installing a plugin | |
21 | ------------------- | |
22 | ||
23 | Once your module is present in the location set by the | |
224ce89b WB |
24 | ``mgr module path`` configuration setting, you can enable it |
25 | via the ``ceph mgr module enable`` command:: | |
7c673cae | 26 | |
224ce89b | 27 | ceph mgr module enable mymodule |
7c673cae FG |
28 | |
29 | Note that the MgrModule interface is not stable, so any modules maintained | |
30 | outside of the Ceph tree are liable to break when run against any newer | |
31 | or older versions of Ceph. | |
32 | ||
33 | Logging | |
34 | ------- | |
35 | ||
36 | MgrModule instances have a ``log`` property which is a logger instance that | |
37 | sends log messages into the Ceph logging layer where they will be recorded | |
38 | in the mgr daemon's log file. | |
39 | ||
40 | Use it the same way you would any other python logger. The python | |
41 | log levels debug, info, warn, err are mapped into the Ceph | |
42 | severities 20, 4, 1 and 0 respectively. | |
43 | ||
44 | Exposing commands | |
45 | ----------------- | |
46 | ||
47 | Set the ``COMMANDS`` class attribute of your plugin to a list of dicts | |
48 | like this:: | |
49 | ||
50 | COMMANDS = [ | |
51 | { | |
52 | "cmd": "foobar name=myarg,type=CephString", | |
53 | "desc": "Do something awesome", | |
54 | "perm": "rw" | |
55 | } | |
56 | ] | |
57 | ||
58 | The ``cmd`` part of each entry is parsed in the same way as internal | |
59 | Ceph mon and admin socket commands (see mon/MonCommands.h in | |
60 | the Ceph source for examples) | |
61 | ||
62 | Config settings | |
63 | --------------- | |
64 | ||
65 | Modules have access to a simple key/value store (keys and values are | |
66 | byte strings) for storing configuration. Don't use this for | |
67 | storing large amounts of data. | |
68 | ||
69 | Config values are stored using the mon's config-key commands. | |
70 | ||
71 | Hints for using these: | |
72 | ||
73 | * Reads are fast: ceph-mgr keeps a local in-memory copy | |
74 | * Don't set things by hand with "ceph config-key", the mgr doesn't update | |
75 | at runtime (only set things from within modules). | |
76 | * Writes block until the value is persisted, but reads from another | |
77 | thread will see the new value immediately. | |
78 | ||
79 | Any config settings you want to expose to users from your module will | |
80 | need corresponding hooks in ``COMMANDS`` to expose a setter. | |
81 | ||
82 | Accessing cluster data | |
83 | ---------------------- | |
84 | ||
85 | Modules have access to the in-memory copies of the Ceph cluster's | |
86 | state that the mgr maintains. Accessor functions as exposed | |
87 | as members of MgrModule. | |
88 | ||
89 | Calls that access the cluster or daemon state are generally going | |
90 | from Python into native C++ routines. There is some overhead to this, | |
91 | but much less than for example calling into a REST API or calling into | |
92 | an SQL database. | |
93 | ||
94 | There are no consistency rules about access to cluster structures or | |
95 | daemon metadata. For example, an OSD might exist in OSDMap but | |
96 | have no metadata, or vice versa. On a healthy cluster these | |
97 | will be very rare transient states, but plugins should be written | |
98 | to cope with the possibility. | |
99 | ||
100 | ``get(self, data_name)`` | |
101 | ||
102 | Fetch named cluster-wide objects such as the OSDMap. Valid things | |
103 | to fetch are osd_crush_map_text, osd_map, osd_map_tree, | |
104 | osd_map_crush, config, mon_map, fs_map, osd_metadata, pg_summary, | |
105 | df, osd_stats, health, mon_status. | |
106 | ||
107 | All these structures have their own JSON representations: experiment | |
108 | or look at the C++ dump() methods to learn about them. | |
109 | ||
110 | ``get_server(self, hostname)`` | |
111 | ||
112 | Fetch metadata about a particular hostname. This is information | |
113 | that ceph-mgr has gleaned from the daemon metadata reported | |
114 | by daemons running on a particular server. | |
115 | ||
116 | ``list_servers(self)`` | |
117 | ||
118 | Like ``get_server``, but gives information about all servers (i.e. all | |
119 | unique hostnames that have been mentioned in daemon metadata) | |
120 | ||
121 | ``get_metadata(self, svc_type, svc_id)`` | |
122 | ||
123 | Fetch the daemon metadata for a particular service. svc_type is one | |
124 | of osd or mds, and svc_id is a string (convert OSD integer IDs to strings | |
125 | when calling this). | |
126 | ||
127 | ``get_counter(self, svc_type, svc_name, path)`` | |
128 | ||
129 | Fetch the latest performance counter data for a particular counter. The | |
130 | path is a period-separated concatenation of the subsystem and the counter | |
131 | name, for example "mds.inodes". | |
132 | ||
133 | A list of two-tuples of (timestamp, value) is returned. This may be | |
134 | empty if no data is available. | |
135 | ||
136 | Sending commands | |
137 | ---------------- | |
138 | ||
139 | A non-blocking facility is provided for sending monitor commands | |
140 | to the cluster. | |
141 | ||
142 | ``send_command(self, result, command_str, tag)`` | |
143 | ||
144 | The ``result`` parameter should be an instance of the CommandResult | |
145 | class, defined in the same module as MgrModule. This acts as a | |
146 | completion and stores the output of the command. Use CommandResult.wait() | |
147 | if you want to block on completion. | |
148 | ||
149 | The ``command_str`` parameter is a JSON-serialized command. This | |
150 | uses the same format as the ceph command line, which is a dictionary | |
151 | of command arguments, with the extra ``prefix`` key containing the | |
152 | command name itself. Consult MonCommands.h for available commands | |
153 | and their expected arguments. | |
154 | ||
155 | The ``tag`` parameter is used for nonblocking operation: when | |
156 | a command completes, the ``notify()`` callback on the MgrModule | |
157 | instance is triggered, with notify_type set to "command", and | |
158 | notify_id set to the tag of the command. | |
159 | ||
160 | ||
161 | Logging | |
162 | ------- | |
163 | ||
164 | Use your module's ``log`` attribute as your logger. This is a logger | |
165 | configured to output via the ceph logging framework, to the local ceph-mgr | |
166 | log files. | |
167 | ||
168 | Python log severities are mapped to ceph severities as follows: | |
169 | ||
170 | * DEBUG is 20 | |
171 | * INFO is 4 | |
172 | * WARN is 1 | |
173 | * ERR is 0 | |
174 | ||
175 | Shutting down cleanly | |
176 | --------------------- | |
177 | ||
178 | If a module implements the ``serve()`` method, it should also implement | |
179 | the ``shutdown()`` method to shutdown cleanly: misbehaving modules | |
180 | may otherwise prevent clean shutdown of ceph-mgr. | |
181 | ||
182 | Is something missing? | |
183 | --------------------- | |
184 | ||
185 | The ceph-mgr python interface is not set in stone. If you have a need | |
186 | that is not satisfied by the current interface, please bring it up | |
187 | on the ceph-devel mailing list. While it is desired to avoid bloating | |
188 | the interface, it is not generally very hard to expose existing data | |
189 | to the Python code when there is a good reason. | |
190 |