]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/plugins/feature_toggles.py
1 # -*- coding: utf-8 -*-
2 from __future__
import absolute_import
6 from mgr_module
import CLICommand
, Option
8 from . import PLUGIN_MANAGER
as PM
9 from . import interfaces
as I
10 from .ttl_cache
import ttl_cache
12 from ..controllers
.rbd
import Rbd
, RbdSnapshot
, RbdTrash
13 from ..controllers
.rbd_mirroring
import (
14 RbdMirroringSummary
, RbdMirroringPoolMode
, RbdMirroringPoolPeer
)
15 from ..controllers
.iscsi
import Iscsi
, IscsiTarget
16 from ..controllers
.cephfs
import CephFS
17 from ..controllers
.rgw
import Rgw
, RgwDaemon
, RgwBucket
, RgwUser
22 MIRRORING
= 'mirroring'
28 PREDISABLED_FEATURES
= set()
31 Feature2Controller
= {
32 Features
.RBD
: [Rbd
, RbdSnapshot
, RbdTrash
],
34 RbdMirroringSummary
, RbdMirroringPoolMode
, RbdMirroringPoolPeer
],
35 Features
.ISCSI
: [Iscsi
, IscsiTarget
],
36 Features
.CEPHFS
: [CephFS
],
37 Features
.RGW
: [Rgw
, RgwDaemon
, RgwBucket
, RgwUser
],
48 class FeatureToggles(I
.CanMgr
, I
.CanLog
, I
.Setupable
, I
.HasOptions
,
49 I
.HasCommands
, I
.FilterRequest
.BeforeHandler
,
51 OPTION_FMT
= 'FEATURE_TOGGLE_{}'
52 CACHE_MAX_SIZE
= 128 # Optimum performance with 2^N sizes
53 CACHE_TTL
= 10 # seconds
57 self
.Controller2Feature
= {
59 for feature
, controllers
in Feature2Controller
.items()
60 for controller
in controllers
}
63 def get_options(self
):
65 name
=self
.OPTION_FMT
.format(feature
.value
),
66 default
=(feature
not in PREDISABLED_FEATURES
),
67 type='bool',) for feature
in Features
]
70 def register_commands(self
):
73 "name=action,type=CephChoices,strings={} ".format(
74 "|".join(a
.value
for a
in Actions
))
75 + "name=features,type=CephChoices,strings={},req=false,n=N".format(
76 "|".join(f
.value
for f
in Features
)),
77 "Enable or disable features in Ceph-Mgr Dashboard")
78 def cmd(mgr
, action
, features
=None):
81 if action
in [Actions
.ENABLE
.value
, Actions
.DISABLE
.value
]:
84 msg
= ["At least one feature must be specified"]
86 for feature
in features
:
87 mgr
.set_module_option(
88 self
.OPTION_FMT
.format(feature
),
89 action
== Actions
.ENABLE
.value
)
90 msg
+= ["Feature '{}': {}".format(
92 'enabled' if action
== Actions
.ENABLE
.value
else
95 for feature
in features
or [f
.value
for f
in Features
]:
96 enabled
= mgr
.get_module_option(self
.OPTION_FMT
.format(feature
))
97 msg
+= ["Feature '{}': '{}'".format(
99 'enabled' if enabled
else 'disabled')]
100 return ret
, '\n'.join(msg
), ''
101 return {'handle_command': cmd
}
103 def _get_feature_from_request(self
, request
):
105 return self
.Controller2Feature
[
106 request
.handler
.callable.__self
__]
107 except (AttributeError, KeyError):
110 @ttl_cache(ttl
=CACHE_TTL
, maxsize
=CACHE_MAX_SIZE
)
111 def _is_feature_enabled(self
, feature
):
112 return self
.mgr
.get_module_option(self
.OPTION_FMT
.format(feature
.value
))
115 def filter_request_before_handler(self
, request
):
116 feature
= self
._get
_feature
_from
_request
(request
)
120 if not self
._is
_feature
_enabled
(feature
):
121 raise cherrypy
.HTTPError(
122 404, "Feature='{}' disabled by option '{}'".format(
124 self
.OPTION_FMT
.format(feature
.value
),
129 def get_controllers(self
):
130 from ..controllers
import ApiController
, RESTController
132 @ApiController('/feature_toggles')
133 class FeatureTogglesEndpoint(RESTController
):
137 feature
.value
: self
._is
_feature
_enabled
(feature
)
138 for feature
in Features
140 return [FeatureTogglesEndpoint
]