]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard_v2: Add hosts page
authorRicardo Marques <rimarques@suse.com>
Sat, 27 Jan 2018 00:05:54 +0000 (00:05 +0000)
committerRicardo Dias <rdias@suse.com>
Mon, 5 Mar 2018 13:07:03 +0000 (13:07 +0000)
Signed-off-by: Ricardo Marques <rimarques@suse.com>
23 files changed:
src/pybind/mgr/dashboard_v2/controllers/host.py [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/app-routing.module.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/app.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/app.component.spec.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/ceph.module.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/host.module.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.html [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.scss [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/service-list.pipe.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/service-list.pipe.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation.module.ts
src/pybind/mgr/dashboard_v2/frontend/src/app/core/navigation/navigation/navigation.component.html
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.html [deleted file]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.scss [deleted file]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.spec.ts [deleted file]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.ts [deleted file]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/pipes.module.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/host.service.ts [new file with mode: 0644]
src/pybind/mgr/dashboard_v2/frontend/src/app/shared/shared.module.ts

diff --git a/src/pybind/mgr/dashboard_v2/controllers/host.py b/src/pybind/mgr/dashboard_v2/controllers/host.py
new file mode 100644 (file)
index 0000000..5e280d7
--- /dev/null
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from ..tools import ApiController, AuthRequired, RESTController
+
+
+@ApiController('host')
+@AuthRequired()
+class Host(RESTController):
+    def list(self):
+        return self.mgr.list_servers()
index 4fb1abd512c89a51b8072a79dfdc05246371a493..b65f2b24fa61ccdafd7c6b8c3c3f0d68358c16d8 100644 (file)
@@ -1,13 +1,13 @@
 import { NgModule } from '@angular/core';
 import { Routes, RouterModule } from '@angular/router';
 import { AuthGuardService } from './shared/services/auth-guard.service';
-import { EmptyComponent } from './shared/empty/empty.component';
 import { LoginComponent } from './core/auth/login/login.component';
+import { HostsComponent } from './ceph/host/hosts/hosts.component';
 
 const routes: Routes = [
-  // TODO configure an appropriate default route (maybe on ceph module?)
-  { path: '', canActivate: [AuthGuardService], component: EmptyComponent },
-  { path: 'login', component: LoginComponent }
+  { path: '', redirectTo: 'hosts', pathMatch: 'full' },
+  { path: 'login', component: LoginComponent },
+  { path: 'hosts', component: HostsComponent, canActivate: [AuthGuardService] }
 ];
 
 @NgModule({
index 5bc0bbb62519822842def99ee94a636150c5c24f..31af1450115dd544dbd284feebb8a7ccd48cfafc 100644 (file)
@@ -1,5 +1,6 @@
 <cd-navigation *ngIf="!isLogginActive()"></cd-navigation>
 <div class="container-fluid"
      [ngClass]="{'full-height':isLogginActive()}">
+  <div *ngIf="!isLogginActive()" class="breadcrumb"></div>
   <router-outlet></router-outlet>
 </div>
index 56c7769a81a9fcf026b2a888c7bb0633d256d855..b7962ab6948ac9aba54e07cc445d12d233440be4 100644 (file)
@@ -4,6 +4,7 @@ import { AppComponent } from './app.component';
 import { CoreModule } from './core/core.module';
 import { SharedModule } from './shared/shared.module';
 import { ToastModule } from 'ng2-toastr';
+import { HostModule } from './ceph/host/host.module';
 
 describe('AppComponent', () => {
   beforeEach(async(() => {
@@ -12,7 +13,8 @@ describe('AppComponent', () => {
         RouterTestingModule,
         CoreModule,
         SharedModule,
-        ToastModule.forRoot()
+        ToastModule.forRoot(),
+        HostModule
       ],
       declarations: [
         AppComponent
index 9cdda334b93eebbf0dd2c4abe16752ebd0f1f080..6a8eda9a78e98d41f71e98eaaf89fe9279576f5e 100644 (file)
@@ -1,9 +1,11 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
+import { HostModule } from './host/host.module';
 
 @NgModule({
   imports: [
-    CommonModule
+    CommonModule,
+    HostModule
   ],
   declarations: []
 })
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/host.module.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/host.module.ts
new file mode 100644 (file)
index 0000000..c6055ae
--- /dev/null
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { HostsComponent } from './hosts/hosts.component';
+import { SharedModule } from '../../shared/shared.module';
+import { ServiceListPipe } from './service-list.pipe';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    SharedModule
+  ],
+  declarations: [HostsComponent, ServiceListPipe],
+})
+export class HostModule { }
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.html
new file mode 100644 (file)
index 0000000..a273491
--- /dev/null
@@ -0,0 +1,28 @@
+<table class="table table-bordered">
+  <thead>
+  <tr>
+    <th>
+      Hostname
+    </th>
+    <th>
+      Services
+    </th>
+    <th>
+      Version
+    </th>
+  </tr>
+  </thead>
+  <tbody>
+  <tr *ngFor="let host of hosts">
+    <td>
+      {{ host.hostname }}
+    </td>
+    <td>
+      {{ host.services | serviceList }}
+    </td>
+    <td>
+      {{ host.ceph_version | cephShortVersion }}
+    </td>
+  </tr>
+  </tbody>
+</table>
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.scss b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.spec.ts
new file mode 100644 (file)
index 0000000..2f294d7
--- /dev/null
@@ -0,0 +1,35 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HostsComponent } from './hosts.component';
+import { ServiceListPipe } from '../service-list.pipe';
+import { SharedModule } from '../../../shared/shared.module';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+
+describe('HostsComponent', () => {
+  let component: HostsComponent;
+  let fixture: ComponentFixture<HostsComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      imports: [
+        SharedModule,
+        HttpClientTestingModule
+      ],
+      declarations: [
+        HostsComponent,
+        ServiceListPipe
+      ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(HostsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/hosts/hosts.component.ts
new file mode 100644 (file)
index 0000000..99e4aea
--- /dev/null
@@ -0,0 +1,21 @@
+import { Component, OnInit } from '@angular/core';
+import { HostService } from '../../../shared/services/host.service';
+
+@Component({
+  selector: 'cd-hosts',
+  templateUrl: './hosts.component.html',
+  styleUrls: ['./hosts.component.scss']
+})
+export class HostsComponent implements OnInit {
+
+  hosts: any = [];
+
+  constructor(private hostService: HostService) { }
+
+  ngOnInit() {
+    this.hostService.list().then((resp) => {
+      this.hosts = resp;
+    });
+  }
+
+}
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/service-list.pipe.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/service-list.pipe.spec.ts
new file mode 100644 (file)
index 0000000..6edc89d
--- /dev/null
@@ -0,0 +1,8 @@
+import { ServiceListPipe } from './service-list.pipe';
+
+describe('ServiceListPipe', () => {
+  it('create an instance', () => {
+    const pipe = new ServiceListPipe();
+    expect(pipe).toBeTruthy();
+  });
+});
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/service-list.pipe.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/ceph/host/service-list.pipe.ts
new file mode 100644 (file)
index 0000000..aa66a13
--- /dev/null
@@ -0,0 +1,14 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+  name: 'serviceList'
+})
+export class ServiceListPipe implements PipeTransform {
+  transform(value: any, args?: any): any {
+    const strings = [];
+    value.forEach((server) => {
+      strings.push(server.type + '.' + server.id);
+    });
+    return strings.join(', ');
+  }
+}
index b4fbd416ffa940c8d121fc7121261b2430bff134..861a129450f14902fcc7fea422c749349c63ba4c 100644 (file)
@@ -5,6 +5,7 @@ import { AuthModule } from '../auth/auth.module';
 import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
 import { AppRoutingModule } from '../../app-routing.module';
 import { SharedModule } from '../../shared/shared.module';
+import { RouterModule } from '@angular/router';
 
 @NgModule({
   imports: [
@@ -12,7 +13,8 @@ import { SharedModule } from '../../shared/shared.module';
     AuthModule,
     BsDropdownModule.forRoot(),
     AppRoutingModule,
-    SharedModule
+    SharedModule,
+    RouterModule
   ],
   declarations: [NavigationComponent],
   exports: [NavigationComponent]
index 5648a9d7d85d9bfaf84e4b98d7b633236bee75cf..46982ed2830eabcce233c47bad71521955d9f17c 100644 (file)
            routerLink="/cephPools">Pools
         </a>
       </li>
+      -->
       <li routerLinkActive="active"
           class="tc_menuitem tc_menuitem_ceph_nodes">
         <a i18n
-           routerLink="/cephNodes">Nodes
+           routerLink="/hosts">Hosts
         </a>
       </li>
-      <li class="dropdown tc_menuitem tc_menuitem_ceph_rgw">
+      <!--<li class="dropdown tc_menuitem tc_menuitem_ceph_rgw">
         <a href=""
            class="dropdown-toggle"
            data-toggle="dropdown"><ng-container i18n>Object Gateway</ng-container> <span class="caret"></span>
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.html b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.html
deleted file mode 100644 (file)
index 15798c6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<!-- This component should be deleted by the developer that implements the first route / page -->
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.scss b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.scss
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.spec.ts
deleted file mode 100644 (file)
index 2bbad56..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { EmptyComponent } from './empty.component';
-
-describe('EmptyComponent', () => {
-  let component: EmptyComponent;
-  let fixture: ComponentFixture<EmptyComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [ EmptyComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(EmptyComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/empty/empty.component.ts
deleted file mode 100644 (file)
index 65aaf10..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-@Component({
-  selector: 'cd-empty',
-  templateUrl: './empty.component.html',
-  styleUrls: ['./empty.component.scss']
-})
-export class EmptyComponent implements OnInit {
-
-  constructor() { }
-
-  ngOnInit() {
-  }
-
-}
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/ceph-short-version.pipe.spec.ts
new file mode 100644 (file)
index 0000000..bfe10c2
--- /dev/null
@@ -0,0 +1,8 @@
+import { CephShortVersionPipe } from './ceph-short-version.pipe';
+
+describe('CephShortVersionPipe', () => {
+  it('create an instance', () => {
+    const pipe = new CephShortVersionPipe();
+    expect(pipe).toBeTruthy();
+  });
+});
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/ceph-short-version.pipe.ts
new file mode 100644 (file)
index 0000000..3ddece9
--- /dev/null
@@ -0,0 +1,20 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+  name: 'cephShortVersion'
+})
+export class CephShortVersionPipe implements PipeTransform {
+
+  transform(value: any, args?: any): any {
+    // Expect "ceph version 1.2.3-g9asdasd (as98d7a0s8d7)"
+    const result = /ceph version\s+([^ ]+)\s+\(.+\)/.exec(value);
+    if (result) {
+        // Return the "1.2.3-g9asdasd" part
+        return result[1];
+    } else {
+        // Unexpected format, pass it through
+        return value;
+    }
+  }
+
+}
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/pipes.module.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/pipes/pipes.module.ts
new file mode 100644 (file)
index 0000000..ff80c3b
--- /dev/null
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { CephShortVersionPipe } from './ceph-short-version.pipe';
+
+@NgModule({
+  imports: [CommonModule],
+  declarations: [CephShortVersionPipe],
+  exports: [CephShortVersionPipe],
+  providers: []
+})
+export class PipesModule {}
diff --git a/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/host.service.ts b/src/pybind/mgr/dashboard_v2/frontend/src/app/shared/services/host.service.ts
new file mode 100644 (file)
index 0000000..73bedce
--- /dev/null
@@ -0,0 +1,15 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class HostService {
+
+  constructor(private http: HttpClient) {
+  }
+
+  list() {
+    return this.http.get('/api/host').toPromise().then((resp: any) => {
+      return resp;
+    });
+  }
+}
index ef3e58a57dbfe1b8c4d2566538aac9fb71c66d7b..5c2e80731b4b2b2285bebfcbf036140e1b47680e 100644 (file)
@@ -3,17 +3,23 @@ import { CommonModule } from '@angular/common';
 import { AuthService } from './services/auth.service';
 import { AuthStorageService } from './services/auth-storage.service';
 import { AuthGuardService } from './services/auth-guard.service';
-import { EmptyComponent } from './empty/empty.component';
+import { PipesModule } from './pipes/pipes.module';
+import { HostService } from './services/host.service';
 
 @NgModule({
   imports: [
-    CommonModule
+    CommonModule,
+    PipesModule
   ],
-  declarations: [EmptyComponent],
+  declarations: [],
   providers: [
     AuthService,
     AuthStorageService,
-    AuthGuardService
+    AuthGuardService,
+    HostService
+  ],
+  exports: [
+    PipesModule
   ]
 })
 export class SharedModule { }