How to add a new controller?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If you want to add a new endpoint to the backend, you just need to add
-a class decorated with ``ApiController`` in a python file located under the
-``controllers`` directory. The dashboard plugin will automatically load your
-new controller upon start.
+If you want to add a new endpoint to the backend, you just need to add a
+class derived from ``BaseController`` decorated with ``ApiController`` in a
+Python file located under the ``controllers`` directory. The Dashboard module
+will automatically load your new controller upon start.
For example create a file ``ping2.py`` under ``controllers`` directory with the
following code::
import cherrypy
- from ..tools import ApiController
+ from ..tools import ApiController, BaseController
@ApiController('ping2')
- class Ping2(object):
+ class Ping2(BaseController):
@cherrypy.expose
def default(self, *args):
return "Hello"
-Reload the dashboard plugin, and then you can access the above controller
-from the web browser using the URL http://mgr_hostname:8080/api/ping2
+Reload the Dashboard module and then you can access the above controller from
+the web browser using the URL http://mgr_hostname:8080/api/ping2.
We also provide a simple mechanism to create REST based controllers using the
``RESTController`` class.
How to access the manager module instance from a controller?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Each controller class annoted with the ``ApiController`` decorator is injected
-with a class property that points to the manager module global instance. The
-property is named ``mgr``.
+Each controller class derived from ``BaseController``has a class property that
+points to the manager module global instance. The property is named ``mgr``.
+There is another class property called ``logger`` to easily add log messages.
Example::
self.logger.debug('Listing available servers')
return {'servers': self.mgr.list_servers()}
-We also inject a class property ``logger`` that is provided by the module class
-to easily add log messages.
-
How to write a unit test for a controller?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import pkgutil
import sys
+import six
import cherrypy
mod = importlib.import_module('.controllers.{}'.format(mod_name),
package='dashboard_v2')
for _, cls in mod.__dict__.items():
- if isinstance(cls, type) and hasattr(cls, '_cp_controller_'):
- # found controller
+ # Controllers MUST be derived from the class BaseController.
+ if isinstance(cls, BaseControllerMeta) and \
+ hasattr(cls, '_cp_controller_'):
cls.mgr = mgrmodule
- cls.logger = mgrmodule.log
controllers.append(cls)
return controllers
version=version))
-class RESTController(object):
+class BaseControllerMeta(type):
+ @property
+ def mgr(cls):
+ """
+ :return: Returns the MgrModule instance of this Ceph dashboard module.
+ """
+ return cls._mgr_module
+
+ @mgr.setter
+ def mgr(cls, value):
+ """
+ :param value: The MgrModule instance of the Ceph dashboard module.
+ """
+ cls._mgr_module = value
+
+ @property
+ def logger(cls):
+ """
+ :return: Returns the logger belonging to the Ceph dashboard module.
+ """
+ return cls.mgr.log
+
+
+class BaseController(six.with_metaclass(BaseControllerMeta, object)):
+ """
+ Base class for all controllers providing API endpoints.
+ """
+ _mgr_module = None
+
+ @property
+ def mgr(self):
+ """
+ :return: Returns the MgrModule instance of this Ceph module.
+ """
+ return self._mgr_module
+
+ @property
+ def logger(self):
+ """
+ :return: Returns the logger belonging to the Ceph dashboard module.
+ """
+ return self.mgr.log
+
+
+class RESTController(BaseController):
"""
Base class for providing a RESTful interface to a resource.