mgr/dashboard: Display useful info if RGW is not configured

Signed-off-by: Volker Theile <vtheile@suse.com>
This commit is contained in:
Volker Theile 2018-05-07 16:50:14 +02:00
parent f49e192dd5
commit 83441af93c
8 changed files with 172 additions and 35 deletions

View File

@ -31,6 +31,23 @@ class RgwControllerTest(DashboardTestCase):
self.assertIn('rgw_status', data)
self.assertTrue(data['rgw_metadata'])
@authenticate
def test_rgw_status(self):
self._radosgw_admin_cmd([
'user', 'create', '--uid=admin', '--display-name=admin',
'--system', '--access-key=admin', '--secret=admin'
])
self._ceph_cmd(['dashboard', 'set-rgw-api-user-id', 'admin'])
self._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', 'admin'])
self._ceph_cmd(['dashboard', 'set-rgw-api-access-key', 'admin'])
data = self._get('/api/rgw/status')
self.assertStatus(200)
self.assertIn('available', data)
self.assertIn('message', data)
self.assertTrue(data['available'])
class RgwProxyExceptionsTest(DashboardTestCase):
@classmethod

View File

@ -14,7 +14,27 @@ from ..rest_client import RequestException
@ApiController('rgw')
@AuthRequired()
class Rgw(RESTController):
pass
@cherrypy.expose
@cherrypy.tools.json_out()
def status(self):
status = {'available': False, 'message': None}
try:
instance = RgwClient.admin_instance()
# Check if the service is online.
if not instance.is_service_online():
status['message'] = 'Failed to connect to the Object Gateway\'s Admin Ops API.'
raise RequestException(status['message'])
# If the API user ID is configured via 'ceph dashboard set-rgw-api-user-id <user_id>'
# (which is not mandatory), then ensure it is known by the RGW.
if instance.userid and not instance.is_system_user():
status['message'] = 'The user "{}" is unknown to the Object Gateway.'.format(
instance.userid)
raise RequestException(status['message'])
status['available'] = True
except RequestException:
pass
return status
@ApiController('rgw/daemon')

View File

@ -16,6 +16,7 @@ import {
PerformanceCounterComponent
} from './ceph/performance-counter/performance-counter/performance-counter.component';
import { PoolListComponent } from './ceph/pool/pool-list/pool-list.component';
import { Rgw501Component } from './ceph/rgw/rgw-501/rgw-501.component';
import { RgwBucketFormComponent } from './ceph/rgw/rgw-bucket-form/rgw-bucket-form.component';
import { RgwBucketListComponent } from './ceph/rgw/rgw-bucket-list/rgw-bucket-list.component';
import { RgwDaemonListComponent } from './ceph/rgw/rgw-daemon-list/rgw-daemon-list.component';
@ -24,6 +25,7 @@ import { RgwUserListComponent } from './ceph/rgw/rgw-user-list/rgw-user-list.com
import { LoginComponent } from './core/auth/login/login.component';
import { NotFoundComponent } from './core/not-found/not-found.component';
import { AuthGuardService } from './shared/services/auth-guard.service';
import { ModuleStatusGuardService } from './shared/services/module-status-guard.service';
const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
@ -31,40 +33,53 @@ const routes: Routes = [
{ path: 'hosts', component: HostsComponent, canActivate: [AuthGuardService] },
{ path: 'login', component: LoginComponent },
{ path: 'hosts', component: HostsComponent, canActivate: [AuthGuardService] },
{ path: 'rgw/501/:message', component: Rgw501Component, canActivate: [AuthGuardService] },
{
path: 'rgw/daemon',
component: RgwDaemonListComponent,
canActivate: [AuthGuardService]
},
{
path: 'rgw/user',
component: RgwUserListComponent,
canActivate: [AuthGuardService]
},
{
path: 'rgw/user/add',
component: RgwUserFormComponent,
canActivate: [AuthGuardService]
},
{
path: 'rgw/user/edit/:uid',
component: RgwUserFormComponent,
canActivate: [AuthGuardService]
},
{
path: 'rgw/bucket',
component: RgwBucketListComponent,
canActivate: [AuthGuardService]
},
{
path: 'rgw/bucket/add',
component: RgwBucketFormComponent,
canActivate: [AuthGuardService]
},
{
path: 'rgw/bucket/edit/:bucket',
component: RgwBucketFormComponent,
canActivate: [AuthGuardService]
path: 'rgw',
canActivateChild: [ModuleStatusGuardService],
data: {
moduleStatusGuardConfig: {
apiPath: 'rgw',
redirectTo: 'rgw/501'
}
},
children: [
{
path: 'daemon',
component: RgwDaemonListComponent,
canActivate: [AuthGuardService]
},
{
path: 'user',
component: RgwUserListComponent,
canActivate: [AuthGuardService]
},
{
path: 'user/add',
component: RgwUserFormComponent,
canActivate: [AuthGuardService]
},
{
path: 'user/edit/:uid',
component: RgwUserFormComponent,
canActivate: [AuthGuardService]
},
{
path: 'bucket',
component: RgwBucketListComponent,
canActivate: [AuthGuardService]
},
{
path: 'bucket/add',
component: RgwBucketFormComponent,
canActivate: [AuthGuardService]
},
{
path: 'bucket/edit/:bucket',
component: RgwBucketFormComponent,
canActivate: [AuthGuardService]
}
]
},
{ path: 'block/iscsi', component: IscsiComponent, canActivate: [AuthGuardService] },
{ path: 'block/rbd', component: RbdListComponent, canActivate: [AuthGuardService] },

View File

@ -0,0 +1,12 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li i18n
class="breadcrumb-item">Object Gateway</li>
</ol>
</nav>
<cd-info-panel>
{{ message }}
<ng-container i18n>
Please consult the <a href="http://docs.ceph.com/docs/mimic/mgr/dashboard/#enabling-the-object-gateway-management-frontend">documentation</a> on how to configure and enable the Object Gateway management functionality.
</ng-container>
</cd-info-panel>

View File

@ -0,0 +1,6 @@
.alert-row-icon {
vertical-align: top;
padding-right: 15px;
}
.alert-row-text {
}

View File

@ -0,0 +1,31 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { SharedModule } from '../../../shared/shared.module';
import { Rgw501Component } from './rgw-501.component';
describe('Rgw501Component', () => {
let component: Rgw501Component;
let fixture: ComponentFixture<Rgw501Component>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ Rgw501Component ],
imports: [
RouterTestingModule,
SharedModule
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(Rgw501Component);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,26 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import * as _ from 'lodash';
@Component({
selector: 'cd-rgw-501',
templateUrl: './rgw-501.component.html',
styleUrls: ['./rgw-501.component.scss']
})
export class Rgw501Component implements OnInit, OnDestroy {
message = 'The Object Gateway service is not configured.';
routeParamsSubscribe: any;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.routeParamsSubscribe = this.route.params.subscribe((params: { message: string }) => {
this.message = params.message;
});
}
ngOnDestroy() {
this.routeParamsSubscribe.unsubscribe();
}
}

View File

@ -2,11 +2,18 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BsDropdownModule, ModalModule, TabsModule, TooltipModule } from 'ngx-bootstrap';
import {
AlertModule,
BsDropdownModule,
ModalModule,
TabsModule,
TooltipModule
} from 'ngx-bootstrap';
import { AppRoutingModule } from '../../app-routing.module';
import { SharedModule } from '../../shared/shared.module';
import { PerformanceCounterModule } from '../performance-counter/performance-counter.module';
import { Rgw501Component } from './rgw-501/rgw-501.component';
import { RgwBucketDetailsComponent } from './rgw-bucket-details/rgw-bucket-details.component';
import { RgwBucketFormComponent } from './rgw-bucket-form/rgw-bucket-form.component';
import { RgwBucketListComponent } from './rgw-bucket-list/rgw-bucket-list.component';
@ -45,12 +52,14 @@ import {
FormsModule,
ReactiveFormsModule,
PerformanceCounterModule,
AlertModule.forRoot(),
BsDropdownModule.forRoot(),
TabsModule.forRoot(),
TooltipModule.forRoot(),
ModalModule.forRoot()
],
exports: [
Rgw501Component,
RgwDaemonListComponent,
RgwDaemonDetailsComponent,
RgwBucketFormComponent,
@ -60,6 +69,7 @@ import {
RgwUserDetailsComponent
],
declarations: [
Rgw501Component,
RgwDaemonListComponent,
RgwDaemonDetailsComponent,
RgwBucketFormComponent,