<li class="breadcrumb-item">
<a routerLink="/block/rbd">Images</a></li>
<li class="breadcrumb-item active"
- i18n>{editing, select, 1 {Edit} other {Add}}</li>
+ i18n>{mode, select, editing {Edit} cloning {Clone} other {Add}}</li>
</ol>
</nav>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
- <span i18n>{editing, select, 1 {Edit} other {Add}}</span> RBD
+ <span i18n>{mode, select, editing {Edit} cloning {Clone} other {Add}}</span> RBD
</h3>
</div>
<div class="panel-body">
+ <!-- Parent -->
+ <div class="form-group"
+ *ngIf="rbdForm.controls.parent.value">
+ <label i18n
+ class="control-label col-sm-3"
+ for="name">{mode, select, cloning {Clone from} other {Parent}}
+ </label>
+ <div class="col-sm-9">
+ <input class="form-control"
+ type="text"
+ id="parent"
+ name="parent"
+ formControlName="parent">
+ <hr>
+ </div>
+ </div>
+
<!-- Name -->
<div class="form-group"
[ngClass]="{'has-error': (formDir.submitted || rbdForm.controls.name.dirty) && rbdForm.controls.name.invalid}">
</label>
<div class="col-sm-9">
<div class="checkbox checkbox-primary"
- *ngIf="!editing">
+ *ngIf="mode !== rbdFormMode.editing">
<input type="checkbox"
id="default-features"
name="default-features"
for="default-features">Use default features</label>
</div>
<div *ngIf="!featuresFormGroups.value.defaultFeatures">
- <br *ngIf="!editing">
+ <br *ngIf="mode !== rbdFormMode.editing">
<div class="checkbox checkbox-primary"
*ngFor="let feature of featuresList">
<input type="checkbox"
<cd-submit-button [form]="rbdForm"
type="button"
(submitAction)="submit()">
- <span i18n>{editing, select, 1 {Update} other {Create}}</span> RBD
+ <span i18n>{mode, select, editing {Update} cloning {Clone} other {Create}}</span> RBD
</cd-submit-button>
<button i18n
type="button"
import { NotificationService } from '../../../shared/services/notification.service';
import { TaskManagerMessageService } from '../../../shared/services/task-manager-message.service';
import { TaskManagerService } from '../../../shared/services/task-manager.service';
+import { RbdFormCloneRequestModel } from './rbd-form-clone-request.model';
import { RbdFormCreateRequestModel } from './rbd-form-create-request.model';
import { RbdFormEditRequestModel } from './rbd-form-edit-request.model';
+import { RbdFormMode } from './rbd-form-mode.enum';
import { RbdFormResponseModel } from './rbd-form-response.model';
@Component({
advancedEnabled = false;
- editing = false;
+ public rbdFormMode = RbdFormMode;
+ mode: RbdFormMode;
response: RbdFormResponseModel;
+ snapName: string;
defaultObjectSize = '4MiB';
'fast-diff': this.fastDiffFormControl,
});
this.rbdForm = new FormGroup({
+ parent: new FormControl(''),
name: new FormControl('', {
validators: [
Validators.required
}
disableForEdit() {
+ this.rbdForm.get('parent').disable();
this.rbdForm.get('pool').disable();
this.rbdForm.get('useDataPool').disable();
this.rbdForm.get('dataPool').disable();
this.rbdForm.get('stripingCount').disable();
}
+ disableForClone() {
+ this.rbdForm.get('parent').disable();
+ this.rbdForm.get('size').disable();
+ }
+
ngOnInit() {
if (this.router.url.startsWith('/rbd/edit')) {
- this.editing = true;
- }
- if (this.editing) {
+ this.mode = this.rbdFormMode.editing;
this.disableForEdit();
+ } else if (this.router.url.startsWith('/rbd/clone')) {
+ this.mode = this.rbdFormMode.cloning;
+ this.disableForClone();
+ }
+ if (this.mode === this.rbdFormMode.editing || this.mode === this.rbdFormMode.cloning) {
this.routeParamsSubscribe = this.route.params.subscribe(
- (params: { pool: string, name: string }) => {
+ (params: { pool: string, name: string, snap: string }) => {
const poolName = params.pool;
const rbdName = params.name;
+ this.snapName = params.snap;
this.rbdService.get(poolName, rbdName)
.subscribe((resp: RbdFormResponseModel) => {
- this.setResponse(resp);
+ this.setResponse(resp, this.snapName);
});
}
);
this.deepBoxCheck(feature, checked);
}
}
- if (this.editing && this.featuresFormGroups.get(feature).enabled) {
+ if (this.mode === this.rbdFormMode.editing && this.featuresFormGroups.get(feature).enabled) {
if (this.response.features_name.indexOf(feature) !== -1 && !details.allowDisable) {
this.featuresFormGroups.get(feature).disable();
}
}
- setResponse(response: RbdFormResponseModel) {
+ setResponse(response: RbdFormResponseModel, snapName: string) {
this.response = response;
- this.rbdForm.get('name').setValue(response.name);
+ if (this.mode === this.rbdFormMode.cloning) {
+ this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}@${snapName}`);
+ } else if (response.parent) {
+ const parent = response.parent;
+ this.rbdForm.get('parent')
+ .setValue(`${parent.pool_name}/${parent.image_name}@${parent.snap_name}`);
+ }
+ if (this.mode === this.rbdFormMode.editing) {
+ this.rbdForm.get('name').setValue(response.name);
+ }
this.rbdForm.get('pool').setValue(response.pool_name);
if (response.data_pool) {
this.rbdForm.get('useDataPool').setValue(true);
return request;
}
+ cloneRequest(): RbdFormCloneRequestModel {
+ const request = new RbdFormCloneRequestModel();
+ request.child_pool_name = this.rbdForm.get('pool').value;
+ request.child_image_name = this.rbdForm.get('name').value;
+ request.obj_size = this.formatter.toBytes(this.rbdForm.get('obj_size').value);
+ if (!this.defaultFeaturesFormControl.value) {
+ _.forIn(this.features, (feature) => {
+ if (this.featuresFormGroups.get(feature.key).value) {
+ request.features.push(feature.key);
+ }
+ });
+ } else {
+ request.features = null;
+ }
+ request.stripe_unit = this.formatter.toBytes(this.rbdForm.get('stripingUnit').value);
+ request.stripe_count = this.rbdForm.get('stripingCount').value;
+ request.data_pool = this.rbdForm.get('dataPool').value;
+ return request;
+ }
+
editAction() {
const request = this.editRequest();
const finishedTask = new FinishedTask();
});
}
+ cloneAction() {
+ const request = this.cloneRequest();
+ const finishedTask = new FinishedTask();
+ finishedTask.name = 'rbd/clone';
+ finishedTask.metadata = {
+ 'parent_pool_name': this.response.pool_name,
+ 'parent_image_name': this.response.name,
+ 'parent_snap_name': this.snapName,
+ 'child_pool_name': request.child_pool_name,
+ 'child_image_name': request.child_image_name
+ };
+ this.rbdService
+ .cloneSnapshot(this.response.pool_name, this.response.name, this.snapName, request)
+ .subscribe((resp) => {
+ if (resp.status === 202) {
+ this.notificationService.show(NotificationType.info,
+ `RBD clone in progress...`,
+ this.taskManagerMessageService.getDescription(finishedTask));
+ this.taskManagerService.subscribe(finishedTask.name, finishedTask.metadata,
+ (asyncFinishedTask: FinishedTask) => {
+ this.notificationService.notifyTask(asyncFinishedTask);
+ });
+ } else {
+ finishedTask.success = true;
+ this.notificationService.notifyTask(finishedTask);
+ }
+ this.router.navigate(['/block/rbd']);
+ }, (resp) => {
+ this.rbdForm.setErrors({'cdSubmitButton': true});
+ finishedTask.success = false;
+ finishedTask.exception = resp.error;
+ this.notificationService.notifyTask(finishedTask);
+ });
+ }
+
submit() {
- if (this.editing) {
+ if (this.mode === this.rbdFormMode.editing) {
this.editAction();
+ } else if (this.mode === this.rbdFormMode.cloning) {
+ this.cloneAction();
} else {
this.createAction();
}