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
@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')
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';
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: '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] },
--- /dev/null
+<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>
--- /dev/null
+.alert-row-icon {
+ vertical-align: top;
+ padding-right: 15px;
+}
+.alert-row-text {
+}
--- /dev/null
+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();
+ });
+});
--- /dev/null
+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();
+ }
+}
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';
FormsModule,
ReactiveFormsModule,
PerformanceCounterModule,
+ AlertModule.forRoot(),
BsDropdownModule.forRoot(),
TabsModule.forRoot(),
TooltipModule.forRoot(),
ModalModule.forRoot()
],
exports: [
+ Rgw501Component,
RgwDaemonListComponent,
RgwDaemonDetailsComponent,
RgwBucketFormComponent,
RgwUserDetailsComponent
],
declarations: [
+ Rgw501Component,
RgwDaemonListComponent,
RgwDaemonDetailsComponent,
RgwBucketFormComponent,