diff --git a/qa/tasks/mgr/dashboard/test_feedback.py b/qa/tasks/mgr/dashboard/test_feedback.py
index a395adf4865..39d736ea08c 100644
--- a/qa/tasks/mgr/dashboard/test_feedback.py
+++ b/qa/tasks/mgr/dashboard/test_feedback.py
@@ -6,7 +6,7 @@ class FeedbackTest(MgrModuleTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
- cls._ceph_cmd(['mgr', 'module', 'enable', 'feedback'], wait=3)
+ cls._ceph_cmd(['mgr', 'module', 'enable', 'feedback', '--force'], wait=3)
# Point the feedback module at an unreachable host so the test
# does not depend on tracker.ceph.com being available. Any
# create_issue call will fail fast with a ConnectionError
diff --git a/src/pybind/mgr/dashboard/controllers/mgr_modules.py b/src/pybind/mgr/dashboard/controllers/mgr_modules.py
index 57bb9b5ffb8..249c111e00c 100644
--- a/src/pybind/mgr/dashboard/controllers/mgr_modules.py
+++ b/src/pybind/mgr/dashboard/controllers/mgr_modules.py
@@ -1,11 +1,13 @@
# -*- coding: utf-8 -*-
+from typing import Optional
+
from .. import mgr
from ..security import Scope
from ..services.ceph_service import CephService
from ..services.exception import handle_send_command_error
from ..tools import find_object_in_list, str_to_bool
-from . import APIDoc, APIRouter, EndpointDoc, RESTController, allow_empty_body
+from . import APIDoc, APIRouter, EndpointDoc, Param, RESTController, allow_empty_body
MGR_MODULE_SCHEMA = ([{
"name": (str, "Module Name"),
@@ -94,15 +96,27 @@ class MgrModules(RESTController):
@RESTController.Resource('POST')
@handle_send_command_error('mgr_modules')
@allow_empty_body
- def enable(self, module_name):
+ @EndpointDoc("Enable Mgr module",
+ parameters={
+ 'force': Param(
+ bool,
+ 'Force enablement when not all mgr daemons support the module',
+ True,
+ False)
+ })
+ def enable(self, module_name, force: Optional[bool] = False):
"""
Enable the specified Ceph Mgr module.
:param module_name: The name of the Ceph Mgr module.
:type module_name: str
+ :param force: Force enablement when not all mgr daemons support the module.
+ :type force: bool
"""
assert self._is_module_managed(module_name)
- CephService.send_command(
- 'mon', 'mgr module enable', module=module_name)
+ cmd_kwargs = {'module': module_name}
+ if force:
+ cmd_kwargs['force'] = True
+ CephService.send_command('mon', 'mgr module enable', **cmd_kwargs)
@RESTController.Resource('POST')
@handle_send_command_error('mgr_modules')
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts
index 68fad64f689..ffe59f37e37 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.spec.ts
@@ -146,7 +146,7 @@ describe('MgrModuleListComponent', () => {
tick(mgrModuleService.REFRESH_INTERVAL);
tick(mgrModuleService.REFRESH_INTERVAL);
tick(mgrModuleService.REFRESH_INTERVAL);
- expect(mgrModuleService.enable).toHaveBeenCalledWith('foo');
+ expect(mgrModuleService.enable).toHaveBeenCalledWith('foo', false);
expect(mgrModuleService.list).toHaveBeenCalledTimes(2);
expect(component.table.refreshBtn).toHaveBeenCalled();
}));
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/feedback/feedback.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/feedback/feedback.component.html
index 50a1804f35d..270f88c8443 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/feedback/feedback.component.html
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/feedback/feedback.component.html
@@ -17,13 +17,13 @@
class="modal-wrapper"
>
@if (!isFeedbackEnabled) {
-
- In order to report an issue, Feedback module must be enabled.
+ Enable the feedback service to report issues.
}
@@ -31,14 +31,13 @@
+ API key
@if (feedbackForm.showError('api_key', formDir, 'required')) {
Ceph Tracker API key is required.
+ i18n>API key is required.
} @if (feedbackForm.showError('api_key', formDir, 'invalidApiKey')) {
Ceph Tracker API key is invalid.
+ i18n>API key is invalid.
}
- You can obtain your API key from
- https://tracker.ceph.com/my/account
-
+
+ Enter your Ceph Tracker API key. You can find your API key in your
+ Ceph Tracker account.
+