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
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()
--- /dev/null
+# -*- 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()
+ }
<a i18n
routerLink="/dashboard">
<i class="fa fa-heartbeat fa-fw"
- [ngStyle]="topLevelData?.health_status | healthColor"></i>
+ [ngStyle]="summaryData?.health_status | healthColor"></i>
<span>Dashboard</span>
</a>
</li>
class="dropdown-menu">
<li routerLinkActive="active"
class="tc_submenuitem tc_submenuitem_cephfs_fs"
- *ngFor="let fs of topLevelData?.filesystems">
+ *ngFor="let fs of summaryData?.filesystems">
<a i18n
class="dropdown-item"
routerLink="/cephfs/{{fs.id}}">{{ fs.name }}
</a>
</li>
<li class="tc_submenuitem tc_submenuitem_cephfs_nofs"
- *ngIf="topLevelData.filesystems.length === 0">
+ *ngIf="summaryData.filesystems.length === 0">
<span i18n>There are no filesystems</span>
</li>
</ul>
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',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent implements OnInit {
- topLevelData: any;
+ summaryData: any;
rbdPools: Array<any> = [];
- 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;
});
}
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 { }
--- /dev/null
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { inject, TestBed } from '@angular/core/testing';
+
+import { SharedModule } from '../shared.module';
+import { SummaryService } from './summary.service';
+
+describe('SummaryService', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [SummaryService],
+ imports: [HttpClientTestingModule, SharedModule]
+ });
+ });
+
+ it(
+ 'should be created',
+ inject([SummaryService], (service: SummaryService) => {
+ expect(service).toBeTruthy();
+ })
+ );
+});
--- /dev/null
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+import { Subject } from 'rxjs/Subject';
+
+import { AuthStorageService } from './auth-storage.service';
+
+@Injectable()
+export class SummaryService {
+ // Observable sources
+ private summaryDataSource = new Subject();
+
+ // Observable streams
+ summaryData$ = this.summaryDataSource.asObservable();
+
+ constructor(private http: HttpClient, private authStorageService: AuthStorageService) {
+ this.refresh();
+ }
+
+ refresh() {
+ if (this.authStorageService.isLoggedIn()) {
+ this.http.get('/api/summary').subscribe(data => {
+ this.summaryDataSource.next(data);
+ });
+ }
+
+ setTimeout(() => {
+ this.refresh();
+ }, 5000);
+ }
+}
+++ /dev/null
-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';
-
-describe('TopLevelService', () => {
- beforeEach(() => {
- TestBed.configureTestingModule({
- providers: [TopLevelService],
- imports: [HttpClientTestingModule, SharedModule]
- });
- });
-
- it(
- 'should be created',
- inject([TopLevelService], (service: TopLevelService) => {
- expect(service).toBeTruthy();
- })
- );
-});
+++ /dev/null
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-
-import { Subject } from 'rxjs/Subject';
-
-import { AuthStorageService } from './auth-storage.service';
-
-@Injectable()
-export class TopLevelService {
- // Observable sources
- private topLevelDataSource = new Subject();
-
- // Observable streams
- topLevelData$ = this.topLevelDataSource.asObservable();
-
- constructor(private http: HttpClient, private authStorageService: AuthStorageService) {
- this.refresh();
- }
-
- refresh() {
- if (this.authStorageService.isLoggedIn()) {
- this.http.get('/api/dashboard/toplevel').subscribe(data => {
- this.topLevelDataSource.next(data);
- });
- }
-
- setTimeout(() => {
- this.refresh();
- }, 5000);
- }
-}
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")
--- /dev/null
+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'])