Add ``status`` action
The action gets rbd mirror pool status for mirrored pools. Change-Id: Ie0962dbee9e0ba9298df6b2448d21180c3a9c0d4
This commit is contained in:
parent
516ca0186b
commit
cb66d5acea
|
@ -16,3 +16,16 @@ refresh-pools:
|
||||||
Refresh list of pools from local and remote Ceph endpoint.
|
Refresh list of pools from local and remote Ceph endpoint.
|
||||||
As a side effect, mirroring will be configured for any manually created
|
As a side effect, mirroring will be configured for any manually created
|
||||||
pools that the charm currently does not know about.
|
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
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
@ -45,16 +46,32 @@ def rbd_mirror_action(args):
|
||||||
ceph_local = reactive.endpoint_from_name('ceph-local')
|
ceph_local = reactive.endpoint_from_name('ceph-local')
|
||||||
pools = (pool for pool, attrs in ceph_local.pools.items()
|
pools = (pool for pool, attrs in ceph_local.pools.items()
|
||||||
if 'rbd' in attrs['applications'])
|
if 'rbd' in attrs['applications'])
|
||||||
result = []
|
result = {}
|
||||||
cmd = ['rbd', '--id', charm.ceph_id, 'mirror', 'pool', action_name]
|
cmd = ['rbd', '--id', charm.ceph_id, 'mirror', 'pool', action_name]
|
||||||
if ch_core.hookenv.action_get('force'):
|
if ch_core.hookenv.action_get('force'):
|
||||||
cmd += ['--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:
|
for pool in pools:
|
||||||
output = subprocess.check_output(cmd + [pool],
|
output = subprocess.check_output(cmd + [pool],
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
universal_newlines=True)
|
universal_newlines=True)
|
||||||
result.append('{}: {}'.format(pool, output.rstrip()))
|
if output_format == 'json':
|
||||||
ch_core.hookenv.action_set({'output': '\n'.join(result)})
|
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):
|
def refresh_pools(args):
|
||||||
|
@ -83,6 +100,7 @@ ACTIONS = {
|
||||||
'demote': rbd_mirror_action,
|
'demote': rbd_mirror_action,
|
||||||
'promote': rbd_mirror_action,
|
'promote': rbd_mirror_action,
|
||||||
'refresh-pools': refresh_pools,
|
'refresh-pools': refresh_pools,
|
||||||
|
'status': rbd_mirror_action,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
actions.py
|
|
@ -51,7 +51,11 @@ class TestCephRBDMirrorActions(test_utils.PatchHelper):
|
||||||
self.check_output.return_value = 'Promoted 0 mirrored images\n'
|
self.check_output.return_value = 'Promoted 0 mirrored images\n'
|
||||||
actions.rbd_mirror_action(['promote'])
|
actions.rbd_mirror_action(['promote'])
|
||||||
self.endpoint_from_name.assert_called_once_with('ceph-local')
|
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([
|
self.check_output.assert_has_calls([
|
||||||
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
|
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
|
||||||
'apool'],
|
'apool'],
|
||||||
|
@ -65,22 +69,28 @@ class TestCephRBDMirrorActions(test_utils.PatchHelper):
|
||||||
# the order the pools has in the output string is undefined
|
# the order the pools has in the output string is undefined
|
||||||
self.action_set.assert_called_once_with(
|
self.action_set.assert_called_once_with(
|
||||||
{'output': mock.ANY})
|
{'output': mock.ANY})
|
||||||
for entry in self.action_set.call_args[0][0]['output'].split('\n'):
|
self.assertEquals(
|
||||||
assert (entry == 'apool: Promoted 0 mirrored images' or
|
sorted(self.action_set.call_args[0][0]['output'].split('\n')),
|
||||||
entry == 'bpool: Promoted 0 mirrored images')
|
['apool: Promoted 0 mirrored images',
|
||||||
self.action_get.return_value = True
|
'bpool: Promoted 0 mirrored images'])
|
||||||
|
self.action_get.side_effect = [True, True, False]
|
||||||
self.check_output.reset_mock()
|
self.check_output.reset_mock()
|
||||||
actions.rbd_mirror_action(['promote'])
|
actions.rbd_mirror_action(['promote'])
|
||||||
self.check_output.assert_has_calls([
|
self.check_output.assert_has_calls([
|
||||||
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
|
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
|
||||||
'--force', 'apool'],
|
'--force', '--verbose', 'apool'],
|
||||||
stderr=actions.subprocess.STDOUT,
|
stderr=actions.subprocess.STDOUT,
|
||||||
universal_newlines=True),
|
universal_newlines=True),
|
||||||
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
|
mock.call(['rbd', '--id', 'acephid', 'mirror', 'pool', 'promote',
|
||||||
'--force', 'bpool'],
|
'--force', '--verbose', 'bpool'],
|
||||||
stderr=actions.subprocess.STDOUT,
|
stderr=actions.subprocess.STDOUT,
|
||||||
universal_newlines=True),
|
universal_newlines=True),
|
||||||
], any_order=True)
|
], any_order=True)
|
||||||
|
self.action_get.assert_has_calls([
|
||||||
|
mock.call('force'),
|
||||||
|
mock.call('verbose'),
|
||||||
|
mock.call('format'),
|
||||||
|
])
|
||||||
|
|
||||||
def test_refresh_pools(self):
|
def test_refresh_pools(self):
|
||||||
self.patch_object(actions.reactive, 'is_flag_set')
|
self.patch_object(actions.reactive, 'is_flag_set')
|
||||||
|
|
Loading…
Reference in New Issue