--- /dev/null
+# -*- 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()
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({
<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>
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(() => {
RouterTestingModule,
CoreModule,
SharedModule,
- ToastModule.forRoot()
+ ToastModule.forRoot(),
+ HostModule
],
declarations: [
AppComponent
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
+import { HostModule } from './host/host.module';
@NgModule({
imports: [
- CommonModule
+ CommonModule,
+ HostModule
],
declarations: []
})
--- /dev/null
+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 { }
--- /dev/null
+<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>
--- /dev/null
+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();
+ });
+});
--- /dev/null
+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;
+ });
+ }
+
+}
--- /dev/null
+import { ServiceListPipe } from './service-list.pipe';
+
+describe('ServiceListPipe', () => {
+ it('create an instance', () => {
+ const pipe = new ServiceListPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
--- /dev/null
+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(', ');
+ }
+}
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: [
AuthModule,
BsDropdownModule.forRoot(),
AppRoutingModule,
- SharedModule
+ SharedModule,
+ RouterModule
],
declarations: [NavigationComponent],
exports: [NavigationComponent]
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>
+++ /dev/null
-<!-- This component should be deleted by the developer that implements the first route / page -->
+++ /dev/null
-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();
- });
-});
+++ /dev/null
-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() {
- }
-
-}
--- /dev/null
+import { CephShortVersionPipe } from './ceph-short-version.pipe';
+
+describe('CephShortVersionPipe', () => {
+ it('create an instance', () => {
+ const pipe = new CephShortVersionPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
--- /dev/null
+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;
+ }
+ }
+
+}
--- /dev/null
+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 {}
--- /dev/null
+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;
+ });
+ }
+}
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 { }