From fe11e6d262c005b43dea99a1a23ddd71a9024efc Mon Sep 17 00:00:00 2001 From: Kanika Murarka Date: Wed, 5 Dec 2018 16:03:53 +0530 Subject: [PATCH] mgr/dashboard: check for existence of Grafana dashboard Fixes: http://tracker.ceph.com/issues/36356 Signed-off-by: Kanika Murarka --- .../mgr/dashboard/controllers/grafana.py | 100 ++---------------- .../cephfs-detail.component.html | 3 +- .../host-details/host-details.component.html | 3 +- .../ceph/cluster/hosts/hosts.component.html | 3 +- .../osd-details/osd-details.component.html | 3 +- .../osd/osd-list/osd-list.component.html | 3 +- .../pool/pool-list/pool-list.component.html | 6 +- .../rgw-daemon-details.component.html | 3 +- .../rgw-daemon-list.component.html | 3 +- .../src/app/shared/api/logs.service.ts | 4 + .../app/shared/api/settings.service.spec.ts | 6 ++ .../src/app/shared/api/settings.service.ts | 4 + .../components/grafana/grafana.component.html | 7 +- .../grafana/grafana.component.spec.ts | 11 +- .../components/grafana/grafana.component.ts | 10 +- .../frontend/src/locale/messages.xlf | 16 ++- .../mgr/dashboard/tests/test_grafana.py | 53 +++------- 17 files changed, 91 insertions(+), 147 deletions(-) mode change 100755 => 100644 src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts diff --git a/src/pybind/mgr/dashboard/controllers/grafana.py b/src/pybind/mgr/dashboard/controllers/grafana.py index e24c0cc161b76..ec444c5fca02e 100644 --- a/src/pybind/mgr/dashboard/controllers/grafana.py +++ b/src/pybind/mgr/dashboard/controllers/grafana.py @@ -1,87 +1,21 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import -import cherrypy import requests -from six.moves.urllib.parse import urlparse # pylint: disable=import-error -from . import ApiController, BaseController, Proxy, Endpoint, ReadPermission -from .. import logger +from . import ApiController, BaseController, Endpoint, ReadPermission from ..security import Scope from ..settings import Settings class GrafanaRestClient(object): - _instance = None - - @staticmethod - def _raise_for_validation(url, user, password): - msg = 'No {} found or misconfigured, please consult the ' \ - 'documentation about how to configure Grafana for the dashboard.' - - o = urlparse(url) - if not (o.netloc and o.scheme): - raise LookupError(msg.format('URL')) - - if not all((user, password)): - raise LookupError(msg.format('credentials')) - - def __init__(self, url, username, password): - """ - :type url: str - :type username: str - :type password: str - """ - self._raise_for_validation(url, username, password) - self._url = url.rstrip('/') - self._user = username - self._password = password - - @classmethod - def instance(cls): - """ - This method shall be used by default to create an instance and will use - the settings to retrieve the required credentials. - - :rtype: GrafanaRestClient - """ - if not cls._instance: - url = Settings.GRAFANA_API_URL - user = Settings.GRAFANA_API_USERNAME - password = Settings.GRAFANA_API_PASSWORD - - cls._instance = GrafanaRestClient(url, user, password) - - return cls._instance - - def proxy_request(self, method, path, params, data): - url = '{}/{}'.format(self._url, path.lstrip('/')) - - # Forwards some headers - headers = {k: v for k, v in cherrypy.request.headers.items() - if k.lower() in ('content-type', 'accept')} + def url_validation(self, method, path): response = requests.request( method, - url, - params=params, - data=data, - headers=headers, - auth=(self._user, self._password)) - logger.debug("proxying method=%s path=%s params=%s data=%s", method, - path, params, data) + path) - return response - - def is_service_online(self): - try: - response = self.instance().proxy_request('GET', '/', None, None) - response.raise_for_status() - except Exception as e: # pylint: disable=broad-except - logger.error(e) - return False, str(e) - - return True, '' + return response.status_code @ApiController('/grafana', Scope.GRAFANA) @@ -91,25 +25,13 @@ class Grafana(BaseController): @ReadPermission def url(self): response = {'instance': Settings.GRAFANA_API_URL} - return response - -@ApiController('/grafana/proxy', Scope.GRAFANA) -class GrafanaProxy(BaseController): - @Proxy() + @Endpoint() @ReadPermission - def __call__(self, path, **params): - grafana = GrafanaRestClient.instance() - method = cherrypy.request.method - - data = None - if cherrypy.request.body.length: - data = cherrypy.request.body.read() - - response = grafana.proxy_request(method, path, params, data) - - cherrypy.response.headers['Content-Type'] = response.headers[ - 'Content-Type'] - - return response.content + def validation(self, params): + grafana = GrafanaRestClient() + method = 'GET' + url = Settings.GRAFANA_API_URL + '/api/dashboards/uid/' + params + response = grafana.url_validation(method, url) + return response diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html index 0449b299cc9ca..a4848790b58da 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-detail/cephfs-detail.component.html @@ -43,7 +43,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html index ca992c9f16b32..219250d2f5a07 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-details/host-details.component.html @@ -1,7 +1,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html index e514b610ed0db..b0eb93470f8c6 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html @@ -27,7 +27,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html index a7238b7a3e9b5..ba2c34cfda467 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-details/osd-details.component.html @@ -44,7 +44,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html index 555d691abca85..dadc21beeddba 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/osd/osd-list/osd-list.component.html @@ -57,7 +57,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html index 3dea670f77771..16e48e0464a79 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-list/pool-list.component.html @@ -25,8 +25,9 @@ - @@ -37,7 +38,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html index 93a0c17e2c64f..d46bbb8c2ccef 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-details/rgw-daemon-details.component.html @@ -14,7 +14,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html index ee417def63ab7..7efc3c11594f8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-daemon-list/rgw-daemon-list.component.html @@ -14,7 +14,8 @@ - diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts index 81b868a5fec22..04dfa82a0551b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/logs.service.ts @@ -12,4 +12,8 @@ export class LogsService { getLogs() { return this.http.get('api/logs/all'); } + + validateDashboardUrl(uid) { + return this.http.get(`api/grafana/validation/${uid}`); + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts index 10dee3506e142..faae4237381b4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.spec.ts @@ -29,6 +29,12 @@ describe('SettingsService', () => { expect(service).toBeTruthy(); }); + it('should call validateGrafanaDashboardUrl', () => { + service.validateGrafanaDashboardUrl('s').subscribe(); + const req = httpTesting.expectOne('api/grafana/validation/s'); + expect(req.request.method).toBe('GET'); + }); + describe('getSettingsValue', () => { const testMethod = (data, expected: string) => { expect(service['getSettingsValue'](data)).toBe(expected); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts old mode 100755 new mode 100644 index 9385c05f1111b..a722ff6baff93 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/settings.service.ts @@ -27,4 +27,8 @@ export class SettingsService { private getSettingsValue(data: any): string { return data.value || data.instance || ''; } + + validateGrafanaDashboardUrl(uid) { + return this.http.get(`api/grafana/validation/${uid}`); + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html index d5c41961df303..477db02a6e55b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/grafana/grafana.component.html @@ -7,8 +7,13 @@ documentation on how to configure and enable the monitoring functionality. +Grafana Dashboard doesn't exist. Please refer to + documentation on how to + add dashboards to Grafana. +
+ *ngIf="grafanaExist && dashboardExist">