From 92ef46eb8f29e95654c02e61a9050d852ac7c02a Mon Sep 17 00:00:00 2001 From: Sebastian Wagner Date: Thu, 22 Feb 2018 14:52:08 +0100 Subject: [PATCH] mgr/dashboard_v2: Move `dashboard/toplevel` to a new controller Details: * Moved `/dashboard/toplevel` API endpoint to `/summary`. * Moved testcase to `tests/test_summary.py`. * Also renamed service in the frontend. Signed-off-by: Sebastian Wagner --- .../mgr/dashboard_v2/controllers/dashboard.py | 32 +------------- .../mgr/dashboard_v2/controllers/summary.py | 42 +++++++++++++++++++ .../navigation/navigation.component.html | 6 +-- .../navigation/navigation.component.ts | 10 ++--- .../app/shared/services/services.module.ts | 4 +- ...ervice.spec.ts => summary.service.spec.ts} | 8 ++-- ...op-level.service.ts => summary.service.ts} | 10 ++--- .../mgr/dashboard_v2/tests/test_dashboard.py | 12 ------ .../mgr/dashboard_v2/tests/test_summary.py | 20 +++++++++ 9 files changed, 82 insertions(+), 62 deletions(-) create mode 100644 src/pybind/mgr/dashboard_v2/controllers/summary.py rename src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/{top-level.service.spec.ts => summary.service.spec.ts} (67%) rename src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/{top-level.service.ts => summary.service.ts} (67%) create mode 100644 src/pybind/mgr/dashboard_v2/tests/test_summary.py diff --git a/src/pybind/mgr/dashboard_v2/controllers/dashboard.py b/src/pybind/mgr/dashboard_v2/controllers/dashboard.py index 21637f4f97862..da8a3b341c4f9 100644 --- a/src/pybind/mgr/dashboard_v2/controllers/dashboard.py +++ b/src/pybind/mgr/dashboard_v2/controllers/dashboard.py @@ -9,8 +9,7 @@ import time import cherrypy from mgr_module import CommandResult -from ..services.ceph_service import CephService -from ..tools import ApiController, AuthRequired, BaseController, NotificationQueue, ViewCache +from ..tools import ApiController, AuthRequired, BaseController, NotificationQueue LOG_BUFFER_SIZE = 30 @@ -55,35 +54,6 @@ class Dashboard(BaseController): for l in lines: buf.appendleft(l) - @ViewCache() - def _rbd_pool_ls(self): - return [pool['pool_name'] for pool in CephService.get_pool_list('rbd')] - - @cherrypy.expose - @cherrypy.tools.json_out() - def toplevel(self): - fsmap = self.mgr.get("fs_map") - - filesystems = [ - { - "id": f['id'], - "name": f['mdsmap']['fs_name'] - } - for f in fsmap['filesystems'] - ] - - _, data = self._rbd_pool_ls() - if data is None: - self.mgr.log.warning("Failed to get RBD pool list") - data = [] - data.sort() - - return { - 'health_status': self.health_data()['status'], - 'filesystems': filesystems, - 'rbd_pools': data - } - # pylint: disable=R0914 @cherrypy.expose @cherrypy.tools.json_out() diff --git a/src/pybind/mgr/dashboard_v2/controllers/summary.py b/src/pybind/mgr/dashboard_v2/controllers/summary.py new file mode 100644 index 0000000000000..a3c0ed0fbd6f6 --- /dev/null +++ b/src/pybind/mgr/dashboard_v2/controllers/summary.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +import json + +import cherrypy + +from ..tools import AuthRequired, ApiController, BaseController +from ..services.ceph_service import CephService + + +@ApiController('summary') +@AuthRequired() +class Summary(BaseController): + def _rbd_pool_data(self): + pool_names = [pool['pool_name'] for pool in CephService.get_pool_list('rbd')] + return sorted(pool_names) + + def _health_status(self): + health_data = self.mgr.get("health") + return json.loads(health_data["json"])['status'] + + def _filesystems(self): + fsmap = self.mgr.get("fs_map") + return [ + { + "id": f['id'], + "name": f['mdsmap']['fs_name'] + } + for f in fsmap['filesystems'] + ] + + @cherrypy.expose + @cherrypy.tools.json_out() + def default(self): + return { + 'rbd_pools': self._rbd_pool_data(), + 'health_status': self._health_status(), + 'filesystems': self._filesystems(), + 'mgr_id': self.mgr.get_mgr_id(), + 'have_mon_connection': self.mgr.have_mon_connection() + } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.html index 6b33769a2f4a1..1b7d6dfb2f166 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.html +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.html @@ -32,7 +32,7 @@ + [ngStyle]="summaryData?.health_status | healthColor"> Dashboard @@ -129,14 +129,14 @@ class="dropdown-menu">
  • + *ngFor="let fs of summaryData?.filesystems"> {{ fs.name }}
  • + *ngIf="summaryData.filesystems.length === 0"> There are no filesystems
  • diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.ts index 37fae9d9e747e..70087338dadef 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { TopLevelService } from '../../../shared/services/top-level.service'; +import { SummaryService } from '../../../shared/services/summary.service'; @Component({ selector: 'cd-navigation', @@ -7,14 +7,14 @@ import { TopLevelService } from '../../../shared/services/top-level.service'; styleUrls: ['./navigation.component.scss'] }) export class NavigationComponent implements OnInit { - topLevelData: any; + summaryData: any; rbdPools: Array = []; - constructor(private topLevelService: TopLevelService) {} + constructor(private summaryService: SummaryService) {} ngOnInit() { - this.topLevelService.topLevelData$.subscribe((data: any) => { - this.topLevelData = data; + this.summaryService.summaryData$.subscribe((data: any) => { + this.summaryData = data; this.rbdPools = data.rbd_pools; }); } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/services.module.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/services.module.ts index 2901b4b90e61b..051f970ac6d45 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/services.module.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/services.module.ts @@ -3,14 +3,14 @@ import { NgModule } from '@angular/core'; import { ConfigurationService } from './configuration.service'; import { FormatterService } from './formatter.service'; +import { SummaryService } from './summary.service'; import { TcmuIscsiService } from './tcmu-iscsi.service'; -import { TopLevelService } from './top-level.service'; @NgModule({ imports: [ CommonModule ], declarations: [], - providers: [FormatterService, TopLevelService, TcmuIscsiService, ConfigurationService] + providers: [FormatterService, SummaryService, TcmuIscsiService, ConfigurationService] }) export class ServicesModule { } diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/top-level.service.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/summary.service.spec.ts similarity index 67% rename from src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/top-level.service.spec.ts rename to src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/summary.service.spec.ts index 3962cb62b1f3b..23af9836a147a 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/top-level.service.spec.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/summary.service.spec.ts @@ -2,19 +2,19 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { inject, TestBed } from '@angular/core/testing'; import { SharedModule } from '../shared.module'; -import { TopLevelService } from './top-level.service'; +import { SummaryService } from './summary.service'; -describe('TopLevelService', () => { +describe('SummaryService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [TopLevelService], + providers: [SummaryService], imports: [HttpClientTestingModule, SharedModule] }); }); it( 'should be created', - inject([TopLevelService], (service: TopLevelService) => { + inject([SummaryService], (service: SummaryService) => { expect(service).toBeTruthy(); }) ); diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/top-level.service.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/summary.service.ts similarity index 67% rename from src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/top-level.service.ts rename to src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/summary.service.ts index 5df5ee9275708..0bc4566b43d4f 100644 --- a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/top-level.service.ts +++ b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/summary.service.ts @@ -6,12 +6,12 @@ import { Subject } from 'rxjs/Subject'; import { AuthStorageService } from './auth-storage.service'; @Injectable() -export class TopLevelService { +export class SummaryService { // Observable sources - private topLevelDataSource = new Subject(); + private summaryDataSource = new Subject(); // Observable streams - topLevelData$ = this.topLevelDataSource.asObservable(); + summaryData$ = this.summaryDataSource.asObservable(); constructor(private http: HttpClient, private authStorageService: AuthStorageService) { this.refresh(); @@ -19,8 +19,8 @@ export class TopLevelService { refresh() { if (this.authStorageService.isLoggedIn()) { - this.http.get('/api/dashboard/toplevel').subscribe(data => { - this.topLevelDataSource.next(data); + this.http.get('/api/summary').subscribe(data => { + this.summaryDataSource.next(data); }); } diff --git a/src/pybind/mgr/dashboard_v2/tests/test_dashboard.py b/src/pybind/mgr/dashboard_v2/tests/test_dashboard.py index 739cb24bf8d50..833ebd542a963 100644 --- a/src/pybind/mgr/dashboard_v2/tests/test_dashboard.py +++ b/src/pybind/mgr/dashboard_v2/tests/test_dashboard.py @@ -6,18 +6,6 @@ from .helper import ControllerTestCase, authenticate class DashboardTest(ControllerTestCase): - @authenticate - def test_toplevel(self): - data = self._get("/api/dashboard/toplevel") - self.assertStatus(200) - - self.assertIn('filesystems', data) - self.assertIn('health_status', data) - self.assertIn('rbd_pools', data) - self.assertIsNotNone(data['filesystems']) - self.assertIsNotNone(data['health_status']) - self.assertIsNotNone(data['rbd_pools']) - @authenticate def test_health(self): data = self._get("/api/dashboard/health") diff --git a/src/pybind/mgr/dashboard_v2/tests/test_summary.py b/src/pybind/mgr/dashboard_v2/tests/test_summary.py new file mode 100644 index 0000000000000..91a9f7a34df0c --- /dev/null +++ b/src/pybind/mgr/dashboard_v2/tests/test_summary.py @@ -0,0 +1,20 @@ +from dashboard_v2.tests.helper import ControllerTestCase, authenticate + + +class SummaryTest(ControllerTestCase): + + @authenticate + def test_summary(self): + data = self._get("/api/summary") + self.assertStatus(200) + + self.assertIn('filesystems', data) + self.assertIn('health_status', data) + self.assertIn('rbd_pools', data) + self.assertIn('mgr_id', data) + self.assertIn('have_mon_connection', data) + self.assertIsNotNone(data['filesystems']) + self.assertIsNotNone(data['health_status']) + self.assertIsNotNone(data['rbd_pools']) + self.assertIsNotNone(data['mgr_id']) + self.assertIsNotNone(data['have_mon_connection']) -- 2.39.5