Skip to content

Commit

Permalink
Merge pull request #21977 from votdev/info_no_rgw_mimic
Browse files Browse the repository at this point in the history
mimic: mgr/dashboard: Display notification if RGW is not configured

Reviewed-by: Ricardo Dias <rdias@suse.com>
Reviewed-by: Tatjana Dehler <tdehler@suse.com>
  • Loading branch information
LenzGr committed May 16, 2018
2 parents 0dba957 + 49db9a9 commit ec3e965
Show file tree
Hide file tree
Showing 15 changed files with 313 additions and 35 deletions.
17 changes: 17 additions & 0 deletions qa/tasks/mgr/dashboard/test_rgw.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ def test_rgw_daemon_get(self):
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
Expand Down
22 changes: 21 additions & 1 deletion src/pybind/mgr/dashboard/controllers/rgw.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,27 @@
@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')
Expand Down
81 changes: 48 additions & 33 deletions src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -24,47 +25,61 @@ 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' },
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuardService] },
{ 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] },
Expand Down
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.alert-row-icon {
vertical-align: top;
padding-right: 15px;
}
.alert-row-text {
}
Original file line number Diff line number Diff line change
@@ -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();
});
});
Original file line number Diff line number Diff line change
@@ -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();
}
}
12 changes: 11 additions & 1 deletion src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -45,12 +52,14 @@ import {
FormsModule,
ReactiveFormsModule,
PerformanceCounterModule,
AlertModule.forRoot(),
BsDropdownModule.forRoot(),
TabsModule.forRoot(),
TooltipModule.forRoot(),
ModalModule.forRoot()
],
exports: [
Rgw501Component,
RgwDaemonListComponent,
RgwDaemonDetailsComponent,
RgwBucketFormComponent,
Expand All @@ -60,6 +69,7 @@ import {
RgwUserDetailsComponent
],
declarations: [
Rgw501Component,
RgwDaemonListComponent,
RgwDaemonDetailsComponent,
RgwBucketFormComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { PipesModule } from '../pipes/pipes.module';
import { DeletionModalComponent } from './deletion-modal/deletion-modal.component';
import { ErrorPanelComponent } from './error-panel/error-panel.component';
import { HelperComponent } from './helper/helper.component';
import { InfoPanelComponent } from './info-panel/info-panel.component';
import { LoadingPanelComponent } from './loading-panel/loading-panel.component';
import { ModalComponent } from './modal/modal.component';
import { SparklineComponent } from './sparkline/sparkline.component';
Expand Down Expand Up @@ -37,6 +38,7 @@ import { ViewCacheComponent } from './view-cache/view-cache.component';
UsageBarComponent,
ErrorPanelComponent,
LoadingPanelComponent,
InfoPanelComponent,
ModalComponent,
DeletionModalComponent
],
Expand All @@ -48,6 +50,7 @@ import { ViewCacheComponent } from './view-cache/view-cache.component';
SubmitButtonComponent,
ErrorPanelComponent,
LoadingPanelComponent,
InfoPanelComponent,
UsageBarComponent
],
entryComponents: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<alert type="info">
<table>
<tr>
<td rowspan="2" class="info-panel-alert-icon">
<i class="fa fa-3x fa-info-circle alert-info"
aria-hidden="true"></i>
</td>
<td class="info-panel-alert-title">
{{ title }}
</td>
</tr>
<tr>
<td class="info-panel-alert-text">
<ng-content></ng-content>
</td>
</tr>
</table>
</alert>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.info-panel-alert-icon {
vertical-align: top;
padding-right: 15px; // See @alert-padding in bootstrap/less/variables.less
}
.info-panel-alert-title {
font-weight: bold;
}
.info-panel-alert-text {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AlertModule } from 'ngx-bootstrap';

import { InfoPanelComponent } from './info-panel.component';

describe('InfoPanelComponent', () => {
let component: InfoPanelComponent;
let fixture: ComponentFixture<InfoPanelComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ InfoPanelComponent ],
imports: [ AlertModule.forRoot() ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(InfoPanelComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'cd-info-panel',
templateUrl: './info-panel.component.html',
styleUrls: ['./info-panel.component.scss']
})
export class InfoPanelComponent {
/**
* The title to be displayed. Defaults to 'Information'.
* @type {string}
*/
@Input() title = 'Information';
}

0 comments on commit ec3e965

Please sign in to comment.