Add ``status`` action

The action gets rbd mirror pool status for mirrored pools.

Change-Id: Ie0962dbee9e0ba9298df6b2448d21180c3a9c0d4
This commit is contained in:
Frode Nordahl 2019-03-18 15:55:28 +01:00
parent 516ca0186b
commit cb66d5acea
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
4 changed files with 52 additions and 10 deletions

View File

@ -16,3 +16,16 @@ refresh-pools:
Refresh list of pools from local and remote Ceph endpoint.
As a side effect, mirroring will be configured for any manually created
pools that the charm currently does not know about.
status:
description: |
Get mirror pool status
params:
verbose:
type: boolean
format:
type: string
default: plain
enum:
- plain
- json
- xml

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import subprocess
import sys
@ -45,16 +46,32 @@ def rbd_mirror_action(args):
ceph_local = reactive.endpoint_from_name('ceph-local')
pools = (pool for pool, attrs in ceph_local.pools.items()
if 'rbd' in attrs['applications'])
result = []
result = {}
cmd = ['rbd', '--id', charm.ceph_id, 'mirror', 'pool', action_name]
if ch_core.hookenv.action_get('force'):
cmd += ['--force']
if ch_core.hookenv.action_get('verbose'):
cmd += ['--verbose']
output_format = ch_core.hookenv.action_get('format')
if output_format:
cmd += ['--format', output_format]
for pool in pools:
output = subprocess.check_output(cmd + [pool],
stderr=subprocess.STDOUT,
universal_newlines=True)
result.append('{}: {}'.format(pool, output.rstrip()))
ch_core.hookenv.action_set({'output': '\n'.join(result)})
if output_format == 'json':
result[pool] = json.loads(output)
else:
result[pool] = output.rstrip()
if output_format == 'json':
ch_core.hookenv.action_set({'output': json.dumps(result)})
else:
output_str = ''
for pool, output in result.items():
if output_str:
output_str += '\n'
output_str += '{}: {}'.format(pool, output)
ch_core.hookenv.action_set({'output': output_str})
def refresh_pools(args):
@ -83,6 +100,7 @@ ACTIONS = {
'demote': rbd_mirror_action,
'promote': rbd_mirror_action,
'refresh-pools': refresh_pools,
'status': rbd_mirror_action,
}

1
src/actions/status Symbolic link
View File

@ -0,0 +1 @@
actions.py

View File

@ -51,7 +51,11 @@ class TestCephRBDMirrorActions(test_utils.PatchHelper):
self.check_output.return_value = 'Promoted 0 mirrored images\n'
actions.rbd_mirror_action(['promote'])
self.endpoint_from_name.assert_called_once_with('ceph-local')
self.action_get.assert_called_once_with('force')
self.action_get.assert_has_calls([
mock.call('force'),
mock.call('verbose'),
mock.call('format'),
])
self.check_output.assert_has_calls([
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
'apool'],
@ -65,22 +69,28 @@ class TestCephRBDMirrorActions(test_utils.PatchHelper):
# the order the pools has in the output string is undefined
self.action_set.assert_called_once_with(
{'output': mock.ANY})
for entry in self.action_set.call_args[0][0]['output'].split('\n'):
assert (entry == 'apool: Promoted 0 mirrored images' or
entry == 'bpool: Promoted 0 mirrored images')
self.action_get.return_value = True
self.assertEquals(
sorted(self.action_set.call_args[0][0]['output'].split('\n')),
['apool: Promoted 0 mirrored images',
'bpool: Promoted 0 mirrored images'])
self.action_get.side_effect = [True, True, False]
self.check_output.reset_mock()
actions.rbd_mirror_action(['promote'])
self.check_output.assert_has_calls([
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
'--force', 'apool'],
'--force', '--verbose', 'apool'],
stderr=actions.subprocess.STDOUT,
universal_newlines=True),
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
'--force', 'bpool'],
'--force', '--verbose', 'bpool'],
stderr=actions.subprocess.STDOUT,
universal_newlines=True),
], any_order=True)
self.action_get.assert_has_calls([
mock.call('force'),
mock.call('verbose'),
mock.call('format'),
])
def test_refresh_pools(self):
self.patch_object(actions.reactive, 'is_flag_set')