How to access the manager module instance from a controller?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-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.
+We provide the manager module instance as a global variable that can be
+imported in any module. We also provide a logger instance in the same way.
Example::
import cherrypy
+ from .. import logger, mgr
from ..tools import ApiController, RESTController
@ApiController('servers')
class Servers(RESTController):
def list(self):
- self.logger.debug('Listing available servers')
- return {'servers': self.mgr.list_servers()}
+ logger.debug('Listing available servers')
+ return {'servers': mgr.list_servers()}
How to write a unit test for a controller?
list of RBD images of the ``rbd`` pool::
import rbd
+ from .. import mgr
from ..tools import ApiController, RESTController
@ApiController('rbdimages')
class RbdImages(RESTController):
def __init__(self):
- self.ioctx = self.mgr.rados.open_ioctx('rbd')
+ self.ioctx = mgr.rados.open_ioctx('rbd')
self.rbd = rbd.RBD()
def list(self):
# -*- coding: utf-8 -*-
+# pylint: disable=wrong-import-position,global-statement,protected-access
"""
openATTIC module
"""
if 'UNITTEST' not in os.environ:
class _LoggerProxy(object):
def __init__(self):
- self.logger = None
+ self._logger = None
def __getattr__(self, item):
- if self.logger is None:
- raise AttributeError("Logging not initialized")
- return getattr(self.logger, item)
+ if self._logger is None:
+ raise AttributeError("logger not initialized")
+ return getattr(self._logger, item)
+ class _ModuleProxy(object):
+ def __init__(self):
+ self._mgr = None
+
+ def init(self, module_inst):
+ global logger
+ self._mgr = module_inst
+ logger._logger = self._mgr._logger
+
+ def __getattr__(self, item):
+ if self._mgr is None:
+ raise AttributeError("global manager module instance not initialized")
+ return getattr(self._mgr, item)
+
+ mgr = _ModuleProxy()
logger = _LoggerProxy()
- # pylint: disable=wildcard-import, wrong-import-position
- from .module import * # NOQA
+
+ from .module import Module, StandbyModule
else:
import logging
logging.basicConfig(level=logging.DEBUG)
import sys
import mock
sys.modules['ceph_module'] = mock.Mock()
+
+ mgr = mock.Mock()
import cherrypy
from ..tools import ApiController, RESTController, Session
-from .. import logger
+from .. import logger, mgr
@ApiController('auth')
@RESTController.args_from_json
def create(self, username, password, stay_signed_in=False):
now = time.time()
- config_username = self.mgr.get_config('username', None)
- config_password = self.mgr.get_config('password', None)
+ config_username = mgr.get_config('username', None)
+ config_password = mgr.get_config('password', None)
hash_password = Auth.password_hash(password,
config_password)
if username == config_username and hash_password == config_password:
raise cherrypy.HTTPError(401, 'You are not authorized to access '
'that resource')
now = time.time()
- expires = float(Auth.mgr.get_config(
+ expires = float(mgr.get_config(
'session-expire', Session.DEFAULT_EXPIRE))
if expires > 0:
username_ts = cherrypy.session.get(Session.TS, None)
@staticmethod
def set_login_credentials(username, password):
- Auth.mgr.set_config('username', username)
+ mgr.set_config('username', username)
hashed_passwd = Auth.password_hash(password)
- Auth.mgr.set_config('password', hashed_passwd)
+ mgr.set_config('password', hashed_passwd)
import cherrypy
from mgr_module import CommandResult
+from .. import mgr
from ..tools import ApiController, AuthRequired, BaseController, ViewCache
for mds_name in mds_names:
result[mds_name] = {}
for counter in counters:
- data = self.mgr.get_counter("mds", mds_name, counter)
+ data = mgr.get_counter("mds", mds_name, counter)
if data is not None:
result[mds_name][counter] = data[counter]
else:
def _get_mds_names(self, filesystem_id=None):
names = []
- fsmap = self.mgr.get("fs_map")
+ fsmap = mgr.get("fs_map")
for fs in fsmap['filesystems']:
if filesystem_id is not None and fs['id'] != filesystem_id:
continue
return names
def get_rate(self, daemon_type, daemon_name, stat):
- data = self.mgr.get_counter(daemon_type, daemon_name, stat)[stat]
+ data = mgr.get_counter(daemon_type, daemon_name, stat)[stat]
if data and len(data) > 1:
return (data[-1][1] - data[-2][1]) / float(data[-1][0] - data[-2][0])
def fs_status(self, fs_id):
mds_versions = defaultdict(list)
- fsmap = self.mgr.get("fs_map")
+ fsmap = mgr.get("fs_map")
filesystem = None
for fs in fsmap['filesystems']:
if fs['id'] == fs_id:
info['name'],
"mds_server.handle_client_request")
- metadata = self.mgr.get_metadata('mds', info['name'])
+ metadata = mgr.get_metadata('mds', info['name'])
mds_versions[metadata.get('ceph_version', 'unknown')].append(
info['name'])
rank_table.append(
}
)
- df = self.mgr.get("df")
+ df = mgr.get("df")
pool_stats = dict([(p['id'], p['stats']) for p in df['pools']])
- osdmap = self.mgr.get("osd_map")
+ osdmap = mgr.get("osd_map")
pools = dict([(p['pool'], p) for p in osdmap['pools']])
metadata_pool_id = mdsmap['metadata_pool']
data_pool_ids = mdsmap['data_pools']
standby_table = []
for standby in fsmap['standbys']:
- metadata = self.mgr.get_metadata('mds', standby['name'])
+ metadata = mgr.get_metadata('mds', standby['name'])
mds_versions[metadata.get('ceph_version', 'unknown')].append(
standby['name'])
def _clients(self, fs_id):
cephfs_clients = self.cephfs_clients.get(fs_id, None)
if cephfs_clients is None:
- cephfs_clients = CephFSClients(self.mgr, fs_id)
+ cephfs_clients = CephFSClients(mgr, fs_id)
self.cephfs_clients[fs_id] = cephfs_clients
try:
}
def get_latest(self, daemon_type, daemon_name, stat):
- data = self.mgr.get_counter(daemon_type, daemon_name, stat)[stat]
+ data = mgr.get_counter(daemon_type, daemon_name, stat)[stat]
if data:
return data[-1][1]
return 0
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
import cherrypy
+
+from .. import mgr
from ..tools import ApiController, RESTController, AuthRequired
if level is not None:
assert level in levels
- options = self.mgr.get("config_options")['options']
+ options = mgr.get("config_options")['options']
if service is not None:
options = [o for o in options if service in o['services']]
return options
def get(self, name):
- for option in self.mgr.get('config_options')['options']:
+ for option in mgr.get('config_options')['options']:
if option['name'] == name:
return option
import cherrypy
from mgr_module import CommandResult
+from .. import mgr
from ..tools import ApiController, AuthRequired, BaseController, NotificationQueue
def load_buffer(self, buf, channel_name):
result = CommandResult("")
- self.mgr.send_command(result, "mon", "", json.dumps({
+ mgr.send_command(result, "mon", "", json.dumps({
"prefix": "log last",
"format": "json",
"channel": channel_name,
osd_map = self.osd_map()
- pg_summary = self.mgr.get("pg_summary")
+ pg_summary = mgr.get("pg_summary")
pools = []
pool_stats = defaultdict(lambda: defaultdict(
lambda: collections.deque(maxlen=10)))
- df = self.mgr.get("df")
+ df = mgr.get("df")
pool_stats_dict = dict([(p['id'], p['stats']) for p in df['pools']])
now = time.time()
for pool_id, stats in pool_stats_dict.items():
return {
"health": self.health_data(),
"mon_status": self.mon_status(),
- "fs_map": self.mgr.get('fs_map'),
+ "fs_map": mgr.get('fs_map'),
"osd_map": osd_map,
"clog": list(self.log_buffer),
"audit_log": list(self.audit_buffer),
"pools": pools,
- "mgr_map": self.mgr.get("mgr_map"),
+ "mgr_map": mgr.get("mgr_map"),
"df": df
}
def mon_status(self):
- mon_status_data = self.mgr.get("mon_status")
+ mon_status_data = mgr.get("mon_status")
return json.loads(mon_status_data['json'])
def osd_map(self):
- osd_map = self.mgr.get("osd_map")
+ osd_map = mgr.get("osd_map")
assert osd_map is not None
- osd_map['tree'] = self.mgr.get("osd_map_tree")
- osd_map['crush'] = self.mgr.get("osd_map_crush")
- osd_map['crush_map_text'] = self.mgr.get("osd_map_crush_map_text")
- osd_map['osd_metadata'] = self.mgr.get("osd_metadata")
+ osd_map['tree'] = mgr.get("osd_map_tree")
+ osd_map['crush'] = mgr.get("osd_map_crush")
+ osd_map['crush_map_text'] = mgr.get("osd_map_crush_map_text")
+ osd_map['osd_metadata'] = mgr.get("osd_metadata")
return osd_map
def health_data(self):
- health_data = self.mgr.get("health")
+ health_data = mgr.get("health")
health = json.loads(health_data['json'])
# Transform the `checks` dict into a list for the convenience
# -*- coding: utf-8 -*-
from __future__ import absolute_import
+from .. import mgr
from ..tools import ApiController, AuthRequired, RESTController
@AuthRequired()
class Host(RESTController):
def list(self):
- return self.mgr.list_servers()
+ return mgr.list_servers()
import cherrypy
+from .. import mgr
from ..tools import ApiController, AuthRequired, BaseController
counters = ['mon.num_sessions']
- mon_status_json = self.mgr.get("mon_status")
+ mon_status_json = mgr.get("mon_status")
mon_status = json.loads(mon_status_json['json'])
for mon in mon_status["monmap"]["mons"]:
mon["stats"] = {}
for counter in counters:
- data = self.mgr.get_counter("mon", mon["name"], counter)
+ data = mgr.get_counter("mon", mon["name"], counter)
if data is not None:
mon["stats"][counter.split(".")[1]] = data[counter]
else:
import json
from mgr_module import CommandResult
+
+from .. import logger, mgr
from ..tools import ApiController, AuthRequired, RESTController
-from .. import logger
@ApiController('osd')
@AuthRequired()
class Osd(RESTController):
def get_counter(self, daemon_name, stat):
- return self.mgr.get_counter('osd', daemon_name, stat)[stat]
+ return mgr.get_counter('osd', daemon_name, stat)[stat]
def get_rate(self, daemon_name, stat):
data = self.get_counter(daemon_name, stat)
def list(self):
osds = self.get_osd_map()
# Extending by osd stats information
- for s in self.mgr.get('osd_stats')['osd_stats']:
+ for s in mgr.get('osd_stats')['osd_stats']:
osds[str(s['osd'])].update({'osd_stats': s})
# Extending by osd node information
- nodes = self.mgr.get('osd_map_tree')['nodes']
+ nodes = mgr.get('osd_map_tree')['nodes']
osd_tree = [(str(o['id']), o) for o in nodes if o['id'] >= 0]
for o in osd_tree:
osds[o[0]].update({'tree': o[1]})
def get_osd_map(self):
osds = {}
- for osd in self.mgr.get('osd_map')['osds']:
+ for osd in mgr.get('osd_map')['osds']:
osd['id'] = osd['osd']
osds[str(osd['id'])] = osd
return osds
def get(self, svc_id):
result = CommandResult('')
- self.mgr.send_command(result, 'osd', svc_id,
- json.dumps({
- 'prefix': 'perf histogram dump',
- }),
- '')
+ mgr.send_command(result, 'osd', svc_id,
+ json.dumps({
+ 'prefix': 'perf histogram dump',
+ }),
+ '')
r, outb, outs = result.wait()
if r != 0:
histogram = None
histogram = json.loads(outb)
return {
'osd_map': self.get_osd_map()[svc_id],
- 'osd_metadata': self.mgr.get_metadata('osd', svc_id),
+ 'osd_metadata': mgr.get_metadata('osd', svc_id),
'histogram': histogram,
}
# -*- coding: utf-8 -*-
from __future__ import absolute_import
+
+from .. import mgr
from ..tools import ApiController, AuthRequired, RESTController
class PerfCounter(RESTController):
- def __init__(self, service_type, mgr):
- PerfCounter.mgr = mgr
+ def __init__(self, service_type):
self._service_type = service_type
def _get_rate(self, daemon_type, daemon_name, stat):
- data = self.mgr.get_counter(daemon_type, daemon_name, stat)[stat]
+ data = mgr.get_counter(daemon_type, daemon_name, stat)[stat]
if data and len(data) > 1:
return (data[-1][1] - data[-2][1]) / float(data[-1][0] - data[-2][0])
return 0
def _get_latest(self, daemon_type, daemon_name, stat):
- data = self.mgr.get_counter(daemon_type, daemon_name, stat)[stat]
+ data = mgr.get_counter(daemon_type, daemon_name, stat)[stat]
if data:
return data[-1][1]
return 0
def get(self, service_id):
- schema = self.mgr.get_perf_schema(
+ schema = mgr.get_perf_schema(
self._service_type, str(service_id)).values()[0]
counters = []
counter['name'] = str(key)
counter['description'] = value['description']
# pylint: disable=W0212
- if self.mgr._stattype_to_str(value['type']) == 'counter':
+ if mgr._stattype_to_str(value['type']) == 'counter':
counter['value'] = self._get_rate(
self._service_type, service_id, key)
counter['unit'] = '/s'
@AuthRequired()
class PerfCounters(RESTController):
def __init__(self):
- self.mds = PerfCounter('mds', self.mgr)
- self.mon = PerfCounter('mon', self.mgr)
- self.osd = PerfCounter('osd', self.mgr)
- self.rgw = PerfCounter('rgw', self.mgr)
- self.rbd_mirror = PerfCounter('rbd-mirror', self.mgr)
+ self.mds = PerfCounter('mds')
+ self.mon = PerfCounter('mon')
+ self.osd = PerfCounter('osd')
+ self.rgw = PerfCounter('rgw')
+ self.rbd_mirror = PerfCounter('rbd-mirror')
def list(self):
- counters = self.mgr.get_all_perf_counters()
+ counters = mgr.get_all_perf_counters()
return counters
import rbd
+from .. import mgr
from ..tools import ApiController, AuthRequired, RESTController, ViewCache
@ViewCache()
def _rbd_list(self, pool_name):
- ioctx = self.mgr.rados.open_ioctx(pool_name)
+ ioctx = mgr.rados.open_ioctx(pool_name)
self.rbd = rbd.RBD()
names = self.rbd.list(ioctx)
result = []
import cherrypy
import rbd
+from .. import logger, mgr
from ..services.ceph_service import CephService
from ..tools import ApiController, AuthRequired, BaseController, ViewCache
-from .. import logger
@ViewCache()
-def get_daemons_and_pools(mgr): # pylint: disable=R0915
+def get_daemons_and_pools(): # pylint: disable=R0915
def get_daemons():
daemons = []
for hostname, server in CephService.get_service_map('rbd-mirror').items():
data = {}
logger.debug("Constructing IOCtx %s", pool_name)
try:
- ioctx = self.mgr.rados.open_ioctx(pool_name)
+ ioctx = mgr.rados.open_ioctx(pool_name)
except TypeError:
logger.exception("Failed to open pool %s", pool_name)
return None
return value
pool_names = [pool['pool_name'] for pool in CephService.get_pool_list('rbd')]
- _, data = get_daemons_and_pools(self.mgr)
+ _, data = get_daemons_and_pools()
if isinstance(data, Exception):
logger.exception("Failed to get rbd-mirror daemons list")
raise type(data)(str(data))
import cherrypy
+from .. import logger, mgr
from ..controllers.rbd_mirroring import get_daemons_and_pools
from ..tools import AuthRequired, ApiController, BaseController
from ..services.ceph_service import CephService
-from .. import logger
@ApiController('summary')
return sorted(pool_names)
def _health_status(self):
- health_data = self.mgr.get("health")
+ health_data = mgr.get("health")
return json.loads(health_data["json"])['status']
def _filesystems(self):
- fsmap = self.mgr.get("fs_map")
+ fsmap = mgr.get("fs_map")
return [
{
"id": f['id'],
]
def _rbd_mirroring(self):
- _, data = get_daemons_and_pools(self.mgr)
+ _, data = get_daemons_and_pools()
if isinstance(data, Exception):
logger.exception("Failed to get rbd-mirror daemons and pools")
'health_status': self._health_status(),
'filesystems': self._filesystems(),
'rbd_mirroring': self._rbd_mirroring(),
- 'mgr_id': self.mgr.get_mgr_id(),
- 'have_mon_connection': self.mgr.have_mon_connection()
+ 'mgr_id': mgr.get_mgr_id(),
+ 'have_mon_connection': mgr.have_mon_connection()
}
# -*- coding: utf-8 -*-
from __future__ import absolute_import
+from .. import mgr
from ..services.ceph_service import CephService
from ..tools import ApiController, AuthRequired, RESTController
pool=metadata['pool_name'],
name=metadata['image_name'])
perf_key = "{}lock_acquired_time".format(perf_key_prefix)
- lock_acquired_time = (self.mgr.get_counter(
+ lock_acquired_time = (mgr.get_counter(
'tcmu-runner', service_id, perf_key)[perf_key] or
[[0, 0]])[-1][1] / 1000000000
if lock_acquired_time > image.get('optimized_since', 0):
image['stats_history'] = {}
for s in ['rd', 'wr', 'rd_bytes', 'wr_bytes']:
perf_key = "{}{}".format(perf_key_prefix, s)
- image['stats'][s] = self.mgr.get_rate(
+ image['stats'][s] = mgr.get_rate(
'tcmu-runner', service_id, perf_key)
- image['stats_history'][s] = self.mgr.get_counter(
+ image['stats_history'][s] = mgr.get_counter(
'tcmu-runner', service_id, perf_key)[perf_key]
else:
daemon['non_optimized_paths'] += 1
_cov.start()
# pylint: disable=wrong-import-position
+from . import logger, mgr
from .controllers.auth import Auth
from .tools import load_controllers, json_error_page, SessionExpireAtBrowserCloseTool, \
NotificationQueue
-from .services import Service
-from . import logger
# cherrypy likes to sys.exit on error. don't let it take us down too!
def __init__(self, *args, **kwargs):
super(Module, self).__init__(*args, **kwargs)
- logger.logger = self._logger
+ mgr.init(self)
self._url_prefix = ''
def configure_cherrypy(self):
- Service.mgr = self # injects module instance into Service class
-
server_addr = self.get_localized_config('server_addr', '::')
server_port = self.get_localized_config('server_port', '8080')
if server_addr is None:
}
def __init__(self, mgrmod):
- self.ctrls = load_controllers(mgrmod)
+ self.ctrls = load_controllers()
logger.debug('Loaded controllers: %s', self.ctrls)
first_level_ctrls = [ctrl for ctrl in self.ctrls
from __future__ import absolute_import
from . import Service
+from .. import mgr
class CephService(Service):
@classmethod
def get_service_map(cls, service_name):
service_map = {}
- for server in cls.mgr.list_servers():
+ for server in mgr.list_servers():
for service in server['services']:
if service['type'] == service_name:
if server['hostname'] not in service_map:
'services': []
}
inst_id = service['id']
- metadata = cls.mgr.get_metadata(service_name, inst_id)
- status = cls.mgr.get_daemon_status(service_name, inst_id)
+ metadata = mgr.get_metadata(service_name, inst_id)
+ status = mgr.get_daemon_status(service_name, inst_id)
service_map[server['hostname']]['services'].append({
'id': inst_id,
'type': service_name,
@classmethod
def get_service(cls, service_name, service_id):
- for server in cls.mgr.list_servers():
+ for server in mgr.list_servers():
for service in server['services']:
if service['type'] == service_name:
inst_id = service['id']
if inst_id == service_id:
- metadata = cls.mgr.get_metadata(service_name, inst_id)
- status = cls.mgr.get_daemon_status(service_name, inst_id)
+ metadata = mgr.get_metadata(service_name, inst_id)
+ status = mgr.get_daemon_status(service_name, inst_id)
return {
'id': inst_id,
'type': service_name,
@classmethod
def get_pool_list(cls, application=None):
- osd_map = cls.mgr.get('osd_map')
+ osd_map = mgr.get('osd_map')
if not application:
return osd_map['pools']
return [pool for pool in osd_map['pools']
import cherrypy
from cherrypy.test.helper import CPWebCase
+from .. import mgr
from ..controllers.auth import Auth
from ..controllers.summary import Summary
from ..controllers.rbd_mirroring import RbdMirror
@classmethod
def setup_test(cls):
- mgr_mock = mock.Mock()
- mgr_mock.list_servers.return_value = mock_list_servers
- mgr_mock.get_metadata.return_value = mock_get_metadata
- mgr_mock.get_daemon_status.return_value = mock_get_daemon_status
- mgr_mock.get.side_effect = lambda key: {
+ mgr.list_servers.return_value = mock_list_servers
+ mgr.get_metadata.return_value = mock_get_metadata
+ mgr.get_daemon_status.return_value = mock_get_daemon_status
+ mgr.get.side_effect = lambda key: {
'osd_map': mock_osd_map,
'health': {'json': '{"status": 1}'},
'fs_map': {'filesystems': []},
}[key]
- mgr_mock.url_prefix = ''
- mgr_mock.get_mgr_id.return_value = 0
- mgr_mock.have_mon_connection.return_value = True
+ mgr.url_prefix = ''
+ mgr.get_mgr_id.return_value = 0
+ mgr.have_mon_connection.return_value = True
- Service.mgr = mgr_mock
-
- RbdMirror.mgr = mgr_mock
RbdMirror._cp_config['tools.authenticate.on'] = False # pylint: disable=protected-access
- Summary.mgr = mgr_mock
Summary._cp_config['tools.authenticate.on'] = False # pylint: disable=protected-access
cherrypy.tree.mount(RbdMirror(), '/api/test/rbdmirror')
import cherrypy
import mock
+from .. import mgr
from ..controllers.auth import Auth
from ..services import Service
from ..tools import SessionExpireAtBrowserCloseTool
@classmethod
def setup_test(cls):
- mgr_mock = mock.Mock()
- mgr_mock.list_servers.return_value = mocked_servers
- mgr_mock.get_metadata.return_value = mocked_metadata
- mgr_mock.get_daemon_status.return_value = mocked_get_daemon_status
- mgr_mock.get_counter.return_value = mocked_get_counter
- mgr_mock.get_rate.return_value = mocked_get_rate
- mgr_mock.url_prefix = ''
- Service.mgr = mgr_mock
- TcmuIscsi.mgr = mgr_mock
+ mgr.list_servers.return_value = mocked_servers
+ mgr.get_metadata.return_value = mocked_metadata
+ mgr.get_daemon_status.return_value = mocked_get_daemon_status
+ mgr.get_counter.return_value = mocked_get_counter
+ mgr.get_rate.return_value = mocked_get_rate
+ mgr.url_prefix = ''
TcmuIscsi._cp_config['tools.authenticate.on'] = False # pylint: disable=protected-access
cherrypy.tree.mount(TcmuIscsi(), "/api/test/tcmu")
return decorate
-def load_controllers(mgrmodule):
+def load_controllers():
# setting sys.path properly when not running under the mgr
dashboard_dir = os.path.dirname(os.path.realpath(__file__))
mgr_dir = os.path.dirname(dashboard_dir)
# Controllers MUST be derived from the class BaseController.
if isinstance(cls, BaseControllerMeta) and \
hasattr(cls, '_cp_controller_'):
- cls.mgr = mgrmodule
controllers.append(cls)
return controllers