from __future__ import absolute_import
+import json
+
from .helper import DashboardTestCase, authenticate, JObj, JAny, JList, JLeaf, JTuple
self._post('/api/osd/0/scrub?deep=True')
self.assertStatus(200)
+
+
+class OsdFlagsTest(DashboardTestCase):
+ def __init__(self, *args, **kwargs):
+ super(OsdFlagsTest, self).__init__(*args, **kwargs)
+ self._initial_flags = sorted( # These flags cannot be unset
+ ['sortbitwise', 'recovery_deletes', 'purged_snapdirs'])
+
+ @classmethod
+ def _get_cluster_osd_flags(cls):
+ return sorted(
+ json.loads(cls._ceph_cmd(['osd', 'dump',
+ '--format=json']))['flags_set'])
+
+ @classmethod
+ def _put_flags(cls, flags):
+ cls._put('/api/osd/flags', data={'flags': flags})
+ return sorted(cls._resp.json())
+
+ @authenticate
+ def test_list_osd_flags(self):
+ flags = self._get('/api/osd/flags')
+ self.assertStatus(200)
+ self.assertEqual(len(flags), 3)
+ self.assertEqual(sorted(flags), self._initial_flags)
+
+ @authenticate
+ def test_add_osd_flag(self):
+ flags = self._put_flags([
+ 'sortbitwise', 'recovery_deletes', 'purged_snapdirs', 'noout',
+ 'pause'
+ ])
+ self.assertEqual(flags, sorted([
+ 'sortbitwise', 'recovery_deletes', 'purged_snapdirs', 'noout',
+ 'pause'
+ ]))
+
+ # Restore flags
+ self._put_flags(self._initial_flags)
from __future__ import absolute_import
from . import ApiController, AuthRequired, RESTController
-from .. import mgr
-
+from .. import mgr, logger
from ..services.ceph_service import CephService
from ..services.exception import handle_send_command_error
from ..tools import str_to_bool
def scrub(self, svc_id, deep=False):
api_scrub = "osd deep-scrub" if str_to_bool(deep) else "osd scrub"
CephService.send_command("mon", api_scrub, who=svc_id)
+
+
+@ApiController('/osd/flags')
+class OsdFlagsController(RESTController):
+ @staticmethod
+ def _osd_flags():
+ enabled_flags = mgr.get('osd_map')['flags_set']
+ if 'pauserd' in enabled_flags and 'pausewr' in enabled_flags:
+ # 'pause' is set by calling `ceph osd set pause` and unset by
+ # calling `set osd unset pause`, but `ceph osd dump | jq '.flags'`
+ # will contain 'pauserd,pausewr' if pause is set.
+ # Let's pretend to the API that 'pause' is in fact a proper flag.
+ enabled_flags = list(
+ set(enabled_flags) - {'pauserd', 'pausewr'} | {'pause'})
+ return sorted(enabled_flags)
+
+ def list(self):
+ return self._osd_flags()
+
+ def bulk_set(self, flags):
+ """
+ The `recovery_deletes` and `sortbitwise` flags cannot be unset.
+ `purged_snapshots` cannot even be set. It is therefore required to at
+ least include those three flags for a successful operation.
+ """
+ assert isinstance(flags, list)
+
+ enabled_flags = set(self._osd_flags())
+ data = set(flags)
+ added = data - enabled_flags
+ removed = enabled_flags - data
+ for flag in added:
+ CephService.send_command('mon', 'osd set', '', key=flag)
+ for flag in removed:
+ CephService.send_command('mon', 'osd unset', '', key=flag)
+ logger.info('Changed OSD flags: added=%s removed=%s', added, removed)
+
+ return sorted(enabled_flags - removed | added)