]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/grafana.py
import quincy beta 17.1.0
[ceph.git] / ceph / src / pybind / mgr / dashboard / grafana.py
1 # -*- coding: utf-8 -*-
2
3 import json
4 import logging
5 import os
6 import time
7
8 import requests
9
10 from .exceptions import GrafanaError
11 from .settings import Settings
12
13 logger = logging.getLogger('grafana')
14
15
16 class GrafanaRestClient(object):
17
18 @staticmethod
19 def url_validation(method, path):
20 response = requests.request(
21 method,
22 path,
23 verify=Settings.GRAFANA_API_SSL_VERIFY)
24 return response.status_code
25
26 @staticmethod
27 def push_dashboard(dashboard_obj):
28 if not Settings.GRAFANA_API_URL:
29 raise GrafanaError("The Grafana API URL is not set")
30 if not Settings.GRAFANA_API_URL.startswith('http'):
31 raise GrafanaError("The Grafana API URL is invalid")
32 if not Settings.GRAFANA_API_USERNAME:
33 raise GrafanaError("The Grafana API username is not set")
34 if not Settings.GRAFANA_API_PASSWORD:
35 raise GrafanaError("The Grafana API password is not set")
36 url = Settings.GRAFANA_API_URL.rstrip('/') + \
37 '/api/dashboards/db'
38 headers = {
39 'Accept': 'application/json',
40 'Content-Type': 'application/json',
41 }
42 payload = {
43 'dashboard': dashboard_obj,
44 'overwrite': True,
45 }
46 try:
47 response = requests.post(
48 url,
49 headers=headers,
50 data=json.dumps(payload),
51 auth=(Settings.GRAFANA_API_USERNAME,
52 Settings.GRAFANA_API_PASSWORD),
53 verify=Settings.GRAFANA_API_SSL_VERIFY
54 )
55 except requests.ConnectionError:
56 raise GrafanaError("Could not connect to Grafana server")
57 response.raise_for_status()
58 return response.status_code, response.json()
59
60
61 class Retrier(object):
62 def __init__(self, tries, sleep, func, *args, **kwargs):
63 """
64 Wraps a function. An instance of this class may be called to call that
65 function, retrying if it raises an exception. Sleeps between retries,
66 eventually reraising the original exception when retries are exhausted.
67 Once the function returns a value, that value is returned.
68
69 :param tries: How many times to try, before reraising the exception
70 :type tries: int
71 :param sleep: How many seconds to wait between tries
72 :type sleep: int|float
73 :param func: The function to execute
74 :type func: function
75 :param args: Any arguments to pass to the function
76 :type args: list
77 :param kwargs: Any keyword arguments to pass to the function
78 :type kwargs: dict
79 """
80 assert tries >= 1
81 self.tries = int(tries)
82 self.tried = 0
83 self.sleep = sleep
84 self.func = func
85 self.args = args
86 self.kwargs = kwargs
87
88 def __call__(self):
89 result = None
90 while self.tried < self.tries:
91 try:
92 result = self.func(*self.args, **self.kwargs)
93 except Exception: # pylint: disable=broad-except
94 if self.tried == self.tries - 1:
95 raise
96 else:
97 self.tried += 1
98 time.sleep(self.sleep)
99 else:
100 return result
101
102
103 def load_local_dashboards():
104 if os.environ.get('CEPH_DEV') == '1' or 'UNITTEST' in os.environ:
105 path = os.path.abspath(os.path.join(
106 os.path.dirname(__file__),
107 '../../../../monitoring/ceph-mixin/dashboards_out/'
108 ))
109 else:
110 path = '/etc/grafana/dashboards/ceph-dashboard'
111 dashboards = dict()
112 for item in [p for p in os.listdir(path) if p.endswith('.json')]:
113 db_path = os.path.join(path, item)
114 with open(db_path) as f:
115 dashboards[item] = json.loads(f.read())
116 return dashboards
117
118
119 def push_local_dashboards(tries=1, sleep=0):
120 try:
121 dashboards = load_local_dashboards()
122 except (EnvironmentError, ValueError):
123 logger.exception("Failed to load local dashboard files")
124 raise
125
126 def push():
127 try:
128 grafana = GrafanaRestClient()
129 for body in dashboards.values():
130 grafana.push_dashboard(body)
131 except Exception:
132 logger.exception("Failed to push dashboards to Grafana")
133 raise
134 retry = Retrier(tries, sleep, push)
135 retry()
136 return True