Add get-health action to the Ceph mon charm
* get-health - outputs `ceph health` output Including unit and functional tests for the above actions. Change-Id: Id4c0a89f2068a6f30025d4a165f84ad112b62cf7 Closes-Bug: #1720099
This commit is contained in:
parent
91d6885e50
commit
001ac4786f
|
@ -2,6 +2,8 @@ pause-health:
|
||||||
description: Pause ceph health operations across the entire ceph cluster
|
description: Pause ceph health operations across the entire ceph cluster
|
||||||
resume-health:
|
resume-health:
|
||||||
description: Resume ceph health operations across the entire ceph cluster
|
description: Resume ceph health operations across the entire ceph cluster
|
||||||
|
get-health:
|
||||||
|
description: Output the current cluster health reported by `ceph health`
|
||||||
create-cache-tier:
|
create-cache-tier:
|
||||||
description: Create a new cache tier
|
description: Create a new cache tier
|
||||||
params:
|
params:
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from subprocess import CalledProcessError, check_output
|
from subprocess import CalledProcessError, check_output
|
||||||
|
import rados
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.append('hooks')
|
sys.path.append('hooks')
|
||||||
|
|
||||||
import rados
|
|
||||||
from charmhelpers.core.hookenv import log, action_get, action_fail
|
from charmhelpers.core.hookenv import log, action_get, action_fail
|
||||||
from charmhelpers.contrib.storage.linux.ceph import pool_set, \
|
from charmhelpers.contrib.storage.linux.ceph import pool_set, \
|
||||||
set_pool_quota, snapshot_pool, remove_pool_snapshot
|
set_pool_quota, snapshot_pool, remove_pool_snapshot
|
||||||
|
@ -25,6 +25,7 @@ from charmhelpers.contrib.storage.linux.ceph import pool_set, \
|
||||||
|
|
||||||
# Connect to Ceph via Librados and return a connection
|
# Connect to Ceph via Librados and return a connection
|
||||||
def connect():
|
def connect():
|
||||||
|
"""Creates a connection to Ceph using librados."""
|
||||||
try:
|
try:
|
||||||
cluster = rados.Rados(conffile='/etc/ceph/ceph.conf')
|
cluster = rados.Rados(conffile='/etc/ceph/ceph.conf')
|
||||||
cluster.connect()
|
cluster.connect()
|
||||||
|
@ -38,11 +39,13 @@ def connect():
|
||||||
|
|
||||||
|
|
||||||
def create_crush_rule():
|
def create_crush_rule():
|
||||||
|
"""Stub function."""
|
||||||
# Shell out
|
# Shell out
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def list_pools():
|
def list_pools():
|
||||||
|
"""Return a list of all Ceph pools."""
|
||||||
try:
|
try:
|
||||||
cluster = connect()
|
cluster = connect()
|
||||||
pool_list = cluster.list_pools()
|
pool_list = cluster.list_pools()
|
||||||
|
@ -56,7 +59,31 @@ def list_pools():
|
||||||
action_fail(str(e))
|
action_fail(str(e))
|
||||||
|
|
||||||
|
|
||||||
|
def get_health():
|
||||||
|
"""
|
||||||
|
Returns the output of 'ceph health'.
|
||||||
|
|
||||||
|
On error, 'unknown' is returned.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
value = check_output(['ceph', 'health'])
|
||||||
|
return value
|
||||||
|
except CalledProcessError as e:
|
||||||
|
action_fail(e.message)
|
||||||
|
return 'Getting health failed, health unknown'
|
||||||
|
|
||||||
|
|
||||||
def pool_get():
|
def pool_get():
|
||||||
|
"""
|
||||||
|
Returns a key from a pool using 'ceph osd pool get'.
|
||||||
|
|
||||||
|
The key is provided via the 'key' action parameter and the
|
||||||
|
pool provided by the 'pool_name' parameter. These are used when
|
||||||
|
running 'ceph osd pool get <pool_name> <key>', the result of
|
||||||
|
which is returned.
|
||||||
|
|
||||||
|
On failure, 'unknown' will be returned.
|
||||||
|
"""
|
||||||
key = action_get("key")
|
key = action_get("key")
|
||||||
pool_name = action_get("pool_name")
|
pool_name = action_get("pool_name")
|
||||||
try:
|
try:
|
||||||
|
@ -65,9 +92,18 @@ def pool_get():
|
||||||
return value
|
return value
|
||||||
except CalledProcessError as e:
|
except CalledProcessError as e:
|
||||||
action_fail(str(e))
|
action_fail(str(e))
|
||||||
|
return 'unknown'
|
||||||
|
|
||||||
|
|
||||||
def set_pool():
|
def set_pool():
|
||||||
|
"""
|
||||||
|
Sets an arbitrary key key in a Ceph pool.
|
||||||
|
|
||||||
|
Sets the key specified by the action parameter 'key' to the value
|
||||||
|
specified in the action parameter 'value' for the pool specified
|
||||||
|
by the action parameter 'pool_name' using the charmhelpers
|
||||||
|
'pool_set' function.
|
||||||
|
"""
|
||||||
key = action_get("key")
|
key = action_get("key")
|
||||||
value = action_get("value")
|
value = action_get("value")
|
||||||
pool_name = action_get("pool_name")
|
pool_name = action_get("pool_name")
|
||||||
|
@ -75,6 +111,11 @@ def set_pool():
|
||||||
|
|
||||||
|
|
||||||
def pool_stats():
|
def pool_stats():
|
||||||
|
"""
|
||||||
|
Returns statistics for a pool.
|
||||||
|
|
||||||
|
The pool name is provided by the action parameter 'pool-name'.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
pool_name = action_get("pool-name")
|
pool_name = action_get("pool-name")
|
||||||
cluster = connect()
|
cluster = connect()
|
||||||
|
@ -93,6 +134,13 @@ def pool_stats():
|
||||||
|
|
||||||
|
|
||||||
def delete_pool_snapshot():
|
def delete_pool_snapshot():
|
||||||
|
"""
|
||||||
|
Delete a pool snapshot.
|
||||||
|
|
||||||
|
Deletes a snapshot from the pool provided by the action
|
||||||
|
parameter 'pool-name', with the snapshot name provided by
|
||||||
|
action parameter 'snapshot-name'
|
||||||
|
"""
|
||||||
pool_name = action_get("pool-name")
|
pool_name = action_get("pool-name")
|
||||||
snapshot_name = action_get("snapshot-name")
|
snapshot_name = action_get("snapshot-name")
|
||||||
remove_pool_snapshot(service='ceph',
|
remove_pool_snapshot(service='ceph',
|
||||||
|
@ -102,6 +150,13 @@ def delete_pool_snapshot():
|
||||||
|
|
||||||
# Note only one or the other can be set
|
# Note only one or the other can be set
|
||||||
def set_pool_max_bytes():
|
def set_pool_max_bytes():
|
||||||
|
"""
|
||||||
|
Sets the max bytes quota for a pool.
|
||||||
|
|
||||||
|
Sets the pool quota maximum bytes for the pool specified by
|
||||||
|
the action parameter 'pool-name' to the value specified by
|
||||||
|
the action parameter 'max'
|
||||||
|
"""
|
||||||
pool_name = action_get("pool-name")
|
pool_name = action_get("pool-name")
|
||||||
max_bytes = action_get("max")
|
max_bytes = action_get("max")
|
||||||
set_pool_quota(service='ceph',
|
set_pool_quota(service='ceph',
|
||||||
|
@ -110,6 +165,13 @@ def set_pool_max_bytes():
|
||||||
|
|
||||||
|
|
||||||
def snapshot_ceph_pool():
|
def snapshot_ceph_pool():
|
||||||
|
"""
|
||||||
|
Snapshots a Ceph pool.
|
||||||
|
|
||||||
|
Snapshots the pool provided in action parameter 'pool-name' and
|
||||||
|
uses the parameter provided in the action parameter 'snapshot-name'
|
||||||
|
as the name for the snapshot.
|
||||||
|
"""
|
||||||
pool_name = action_get("pool-name")
|
pool_name = action_get("pool-name")
|
||||||
snapshot_name = action_get("snapshot-name")
|
snapshot_name = action_get("snapshot-name")
|
||||||
snapshot_pool(service='ceph',
|
snapshot_pool(service='ceph',
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from ceph_ops import get_health
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
get_health()
|
|
@ -708,6 +708,14 @@ class CephBasicDeployment(OpenStackAmuletDeployment):
|
||||||
if ret:
|
if ret:
|
||||||
amulet.raise_status(amulet.FAIL, msg=ret)
|
amulet.raise_status(amulet.FAIL, msg=ret)
|
||||||
|
|
||||||
|
def test_414_get_health_action(self):
|
||||||
|
"""Verify that getting health works"""
|
||||||
|
u.log.debug("Testing get-health")
|
||||||
|
|
||||||
|
sentry_unit = self.ceph0_sentry
|
||||||
|
action_id = u.run_action(sentry_unit, 'get-health')
|
||||||
|
assert u.wait_on_action(action_id), "HEALTH_OK"
|
||||||
|
|
||||||
def test_499_ceph_cmds_exit_zero(self):
|
def test_499_ceph_cmds_exit_zero(self):
|
||||||
"""Check basic functionality of ceph cli commands against
|
"""Check basic functionality of ceph cli commands against
|
||||||
all ceph units."""
|
all ceph units."""
|
||||||
|
|
|
@ -16,3 +16,4 @@ import sys
|
||||||
sys.path.append('hooks')
|
sys.path.append('hooks')
|
||||||
sys.path.append('lib')
|
sys.path.append('lib')
|
||||||
sys.path.append('unit_tests')
|
sys.path.append('unit_tests')
|
||||||
|
sys.path.append('actions')
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Copyright 2016 Canonical Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from mock import mock
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from test_utils import CharmTestCase
|
||||||
|
|
||||||
|
# python-apt is not installed as part of test-requirements but is imported by
|
||||||
|
# some charmhelpers modules so create a fake import.
|
||||||
|
mock_apt = mock.MagicMock()
|
||||||
|
sys.modules['apt'] = mock_apt
|
||||||
|
mock_apt.apt_pkg = mock.MagicMock()
|
||||||
|
|
||||||
|
# mocking for rados
|
||||||
|
mock_rados = mock.MagicMock()
|
||||||
|
sys.modules['rados'] = mock_rados
|
||||||
|
mock_rados.connect = mock.MagicMock()
|
||||||
|
|
||||||
|
# mocking for psutil
|
||||||
|
mock_psutil = mock.MagicMock()
|
||||||
|
sys.modules['psutil'] = mock_psutil
|
||||||
|
mock_psutil.disks = mock.MagicMock()
|
||||||
|
|
||||||
|
with mock.patch('charmhelpers.contrib.hardening.harden.harden') as mock_dec:
|
||||||
|
mock_dec.side_effect = (lambda *dargs, **dkwargs: lambda f:
|
||||||
|
lambda *args, **kwargs: f(*args, **kwargs))
|
||||||
|
# import health actions as actions
|
||||||
|
import ceph_ops as actions
|
||||||
|
|
||||||
|
|
||||||
|
class OpsTestCase(CharmTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(OpsTestCase, self).setUp(
|
||||||
|
actions, ["check_output",
|
||||||
|
"action_get",
|
||||||
|
"action_fail",
|
||||||
|
"open"])
|
||||||
|
|
||||||
|
def test_get_health(self):
|
||||||
|
actions.get_health()
|
||||||
|
cmd = ['ceph', 'health']
|
||||||
|
self.check_output.assert_called_once_with(cmd)
|
Loading…
Reference in New Issue