summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXav Paice <xav.paice@canonical.com>2017-04-26 18:59:46 +1200
committerXav Paice <xav.paice@canonical.com>2017-04-28 23:19:45 +1200
commit59f113d912d9c594c1f76824694f06626f77b8a1 (patch)
tree44b96c4700326b4441b8e64da16be52d5edd24b0
parent1fec99b09c1bb9c498cc4499f2dcb798127b58ad (diff)
Add ceph methods for reweight
Adds the following methods: - get_ceph_pg_stat - get_ceph_health - reweight_osd Change-Id: I23a1563875cfa53cf4341f17ce14c5322cc955ca
Notes
Notes (review): Code-Review+2: Chris Holcombe <chris.holcombe@canonical.com> Workflow+1: Chris Holcombe <chris.holcombe@canonical.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Fri, 28 Apr 2017 17:09:37 +0000 Reviewed-on: https://review.openstack.org/460000 Project: openstack/charms.ceph Branch: refs/heads/master
-rw-r--r--ceph/__init__.py72
-rw-r--r--unit_tests/test_ceph.py122
2 files changed, 194 insertions, 0 deletions
diff --git a/ceph/__init__.py b/ceph/__init__.py
index 7dab66c..f29adfc 100644
--- a/ceph/__init__.py
+++ b/ceph/__init__.py
@@ -2033,3 +2033,75 @@ def resolve_ceph_version(source):
2033 ''' 2033 '''
2034 os_release = get_os_codename_install_source(source) 2034 os_release = get_os_codename_install_source(source)
2035 return UCA_CODENAME_MAP.get(os_release) 2035 return UCA_CODENAME_MAP.get(os_release)
2036
2037
2038def get_ceph_pg_stat():
2039 """
2040 Returns the result of ceph pg stat
2041 :return: dict
2042 """
2043 try:
2044 tree = check_output(['ceph', 'pg', 'stat', '--format=json'])
2045 try:
2046 json_tree = json.loads(tree)
2047 if not json_tree['num_pg_by_state']:
2048 return None
2049 return json_tree
2050 except ValueError as v:
2051 log("Unable to parse ceph pg stat json: {}. Error: {}".format(
2052 tree, v.message))
2053 raise
2054 except subprocess.CalledProcessError as e:
2055 log("ceph pg stat command failed with message: {}".format(
2056 e.message))
2057 raise
2058
2059
2060def get_ceph_health():
2061 """
2062 Returns the health of the cluster from a 'ceph health'
2063 :return: dict
2064 Also raises CalledProcessError if our ceph command fails
2065 To get the overall status, use get_ceph_health()['overall_status']
2066 """
2067 try:
2068 tree = check_output(
2069 ['ceph', 'health', '--format=json'])
2070 try:
2071 json_tree = json.loads(tree)
2072 # Make sure children are present in the json
2073 if not json_tree['overall_status']:
2074 return None
2075 return json_tree
2076 except ValueError as v:
2077 log("Unable to parse ceph tree json: {}. Error: {}".format(
2078 tree, v.message))
2079 raise
2080 except subprocess.CalledProcessError as e:
2081 log("ceph osd tree command failed with message: {}".format(
2082 e.message))
2083 raise
2084
2085
2086def reweight_osd(osd_num, new_weight):
2087 """
2088 Changes the crush weight of an OSD to the value specified.
2089 :param osd_num: the osd id which should be changed
2090 :param new_weight: the new weight for the OSD
2091 :returns: bool. True if output looks right, else false.
2092 :raises CalledProcessError: if an error occurs invoking the systemd cmd
2093 """
2094 try:
2095 cmd_result = subprocess.check_output(
2096 ['ceph', 'osd', 'crush', 'reweight', "osd.{}".format(osd_num),
2097 new_weight], stderr=subprocess.STDOUT)
2098 expected_result = "reweighted item id {ID} name \'osd.{ID}\'".format(
2099 ID=osd_num) + " to {}".format(new_weight)
2100 log(cmd_result)
2101 if expected_result in cmd_result:
2102 return True
2103 return False
2104 except subprocess.CalledProcessError as e:
2105 log("ceph osd tree command failed with message: {}".format(
2106 e.message))
2107 raise
diff --git a/unit_tests/test_ceph.py b/unit_tests/test_ceph.py
index 0fa9f81..69d5d90 100644
--- a/unit_tests/test_ceph.py
+++ b/unit_tests/test_ceph.py
@@ -16,6 +16,7 @@ import mock
16import unittest 16import unittest
17import ceph 17import ceph
18from subprocess import CalledProcessError 18from subprocess import CalledProcessError
19import subprocess
19 20
20 21
21class TestDevice(): 22class TestDevice():
@@ -200,6 +201,127 @@ class CephTestCase(unittest.TestCase):
200 partition_list = ceph.get_partition_list('/dev/xvdb') 201 partition_list = ceph.get_partition_list('/dev/xvdb')
201 self.assertEqual(len(partition_list), 2) 202 self.assertEqual(len(partition_list), 2)
202 203
204 @mock.patch.object(ceph, 'check_output')
205 def test_get_ceph_pg_stat(self, output):
206 """It returns the current PG stat"""
207 output.return_value = """{
208 "num_pg_by_state": [
209 {
210 "name": "active+clean",
211 "num": 320
212 }
213 ],
214 "version": 7111,
215 "num_pgs": 320,
216 "num_bytes": 118111608230,
217 "raw_bytes_used": 355042729984,
218 "raw_bytes_avail": 26627104956416,
219 "raw_bytes": 26982147686400
220}"""
221 pg_stat = ceph.get_ceph_pg_stat()
222 self.assertEqual(pg_stat['num_pgs'], 320)
223
224 @mock.patch.object(ceph, 'check_output')
225 def test_get_ceph_health(self, output):
226 """It gives the current Ceph health"""
227 output.return_value = """{
228 "health": {
229 "health_services": [
230 {
231 "mons": [
232 {
233 "name": "node1",
234 "kb_total": 2883598592,
235 "kb_used": 61728860,
236 "kb_avail": 2675368308,
237 "avail_percent": 92,
238 "last_updated": "2017-04-25 22:17:36.966046",
239 "store_stats": {
240 "bytes_total": 18612017,
241 "bytes_sst": 0,
242 "bytes_log": 2172670,
243 "bytes_misc": 16439347,
244 "last_updated": "0.000000"
245 },
246 "health": "HEALTH_OK"
247 },
248 {
249 "name": "node2",
250 "kb_total": 2883598592,
251 "kb_used": 79776472,
252 "kb_avail": 2657320696,
253 "avail_percent": 92,
254 "last_updated": "2017-04-25 22:18:27.915641",
255 "store_stats": {
256 "bytes_total": 18517923,
257 "bytes_sst": 0,
258 "bytes_log": 3340129,
259 "bytes_misc": 15177794,
260 "last_updated": "0.000000"
261 },
262 "health": "HEALTH_OK"
263 },
264 {
265 "name": "node3",
266 "kb_total": 2883598592,
267 "kb_used": 77399744,
268 "kb_avail": 2659697424,
269 "avail_percent": 92,
270 "last_updated": "2017-04-25 22:18:27.934053",
271 "store_stats": {
272 "bytes_total": 18517892,
273 "bytes_sst": 0,
274 "bytes_log": 3340129,
275 "bytes_misc": 15177763,
276 "last_updated": "0.000000"
277 },
278 "health": "HEALTH_OK"
279 }
280 ]
281 }
282 ]
283 },
284 "timechecks": {
285 "epoch": 8,
286 "round": 3022,
287 "round_status": "finished",
288 "mons": [
289 {
290 "name": "node1",
291 "skew": 0,
292 "latency": 0,
293 "health": "HEALTH_OK"
294 },
295 {
296 "name": "node2",
297 "skew": 0,
298 "latency": 0.000765,
299 "health": "HEALTH_OK"
300 },
301 {
302 "name": "node3",
303 "skew": 0,
304 "latency": 0.000765,
305 "health": "HEALTH_OK"
306 }
307 ]
308 },
309 "summary": [],
310 "overall_status": "HEALTH_OK",
311 "detail": []
312}"""
313 health = ceph.get_ceph_health()
314 self.assertEqual(health['overall_status'], "HEALTH_OK")
315
316 @mock.patch.object(subprocess, 'check_output')
317 def test_reweight_osd(self, mock_reweight):
318 """It changes the weight of an OSD"""
319 mock_reweight.return_value = "reweighted item id 0 name 'osd.0' to 1"
320 reweight_result = ceph.reweight_osd('0', '1')
321 self.assertEqual(reweight_result, True)
322 mock_reweight.assert_called_once_with(
323 ['ceph', 'osd', 'crush', 'reweight', 'osd.0', '1'], stderr=-2)
324
203 325
204class CephVersionTestCase(unittest.TestCase): 326class CephVersionTestCase(unittest.TestCase):
205 @mock.patch.object(ceph, 'get_os_codename_install_source') 327 @mock.patch.object(ceph, 'get_os_codename_install_source')