.. _mgr-module-dev: ceph-mgr module developer's guide ================================= .. warning:: This is developer documentation, describing Ceph internals that are only relevant to people writing ceph-mgr modules. Creating a module ----------------- In pybind/mgr/, create a python module. Within your module, create a class that inherits from ``MgrModule``. For ceph-mgr to detect your module, your directory must contain a file called `module.py`. The most important methods to override are: * a ``serve`` member function for server-type modules. This function should block forever. * a ``notify`` member function if your module needs to take action when new cluster data is available. * a ``handle_command`` member function if your module exposes CLI commands. Some modules interface with external orchestrators to deploy Ceph services. These also inherit from ``Orchestrator``, which adds additional methods to the base ``MgrModule`` class. See :ref:`Orchestrator modules ` for more on creating these modules. Installing a module ------------------- Once your module is present in the location set by the ``mgr module path`` configuration setting, you can enable it via the ``ceph mgr module enable`` command:: ceph mgr module enable mymodule Note that the MgrModule interface is not stable, so any modules maintained outside of the Ceph tree are liable to break when run against any newer or older versions of Ceph. Logging ------- Logging in Ceph manager modules is done as in any other Python program. Just import the ``logging`` package and get a logger instance with the ``logging.getLogger`` function. Each module has a ``log_level`` option that specifies the current Python logging level of the module. To change or query the logging level of the module use the following Ceph commands:: ceph config get mgr mgr//log_level ceph config set mgr mgr//log_level The logging level used upon the module's start is determined by the current logging level of the mgr daemon, unless if the ``log_level`` option was previously set with the ``config set ...`` command. The mgr daemon logging level is mapped to the module python logging level as follows: * <= 0 is CRITICAL * <= 1 is WARNING * <= 4 is INFO * <= +inf is DEBUG We can unset the module log level and fallback to the mgr daemon logging level by running the following command:: ceph config set mgr mgr//log_level '' By default, modules' logging messages are processed by the Ceph logging layer where they will be recorded in the mgr daemon's log file. But it's also possible to send a module's logging message to it's own file. The module's log file will be located in the same directory as the mgr daemon's log file with the following name pattern:: ..log To enable the file logging on a module use the following command:: ceph config set mgr mgr//log_to_file true When the module's file logging is enabled, module's logging messages stop being written to the mgr daemon's log file and are only written to the module's log file. It's also possible to check the status and disable the file logging with the following commands:: ceph config get mgr mgr//log_to_file ceph config set mgr mgr//log_to_file false Exposing commands ----------------- Set the ``COMMANDS`` class attribute of your module to a list of dicts like this:: COMMANDS = [ { "cmd": "foobar name=myarg,type=CephString", "desc": "Do something awesome", "perm": "rw", # optional: "poll": "true" } ] The ``cmd`` part of each entry is parsed in the same way as internal Ceph mon and admin socket commands (see mon/MonCommands.h in the Ceph source for examples). Note that the "poll" field is optional, and is set to False by default; this indicates to the ``ceph`` CLI that it should call this command repeatedly and output results (see ``ceph -h`` and its ``--period`` option). Each command is expected to return a tuple ``(retval, stdout, stderr)``. ``retval`` is an integer representing a libc error code (e.g. EINVAL, EPERM, or 0 for no error), ``stdout`` is a string containing any non-error output, and ``stderr`` is a string containing any progress or error explanation output. Either or both of the two strings may be empty. Implement the ``handle_command`` function to respond to the commands when they are sent: .. py:currentmodule:: mgr_module .. automethod:: MgrModule.handle_command Configuration options --------------------- Modules can load and store configuration options using the ``set_module_option`` and ``get_module_option`` methods. .. note:: Use ``set_module_option`` and ``get_module_option`` to manage user-visible configuration options that are not blobs (like certificates). If you want to persist module-internal data or binary configuration data consider using the `KV store`_. You must declare your available configuration options in the ``MODULE_OPTIONS`` class attribute, like this: :: MODULE_OPTIONS = [ { "name": "my_option" } ] If you try to use set_module_option or get_module_option on options not declared in ``MODULE_OPTIONS``, an exception will be raised. You may choose to provide setter commands in your module to perform high level validation. Users can also modify configuration using the normal `ceph config set` command, where the configuration options for a mgr module are named like `mgr//