Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1870331: Not allow to change size for OCS based resource #6683

Merged
merged 1 commit into from Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,5 +1,5 @@
.co-clone-pvc-modal__details {
margin-top: var(--pf-global--spacer--xl);
margin-top: var(--pf-global--spacer--md);
}

.co-clone-pvc-modal__details-section {
Expand All @@ -14,3 +14,7 @@
.co-clone-pvc-modal__name--margin {
margin-bottom: var(--pf-global--spacer--sm);
}

.co-clone-pvc-modal__ocs-size .form-group{
margin-bottom: var(--pf-global--spacer--sm);
}
Expand Up @@ -3,7 +3,12 @@ import './_clone-pvc-modal.scss';
import * as React from 'react';

import { Form, FormGroup, TextInput } from '@patternfly/react-core';
import { k8sCreate, referenceFor, PersistentVolumeClaimKind } from '@console/internal/module/k8s';
import {
k8sCreate,
referenceFor,
PersistentVolumeClaimKind,
StorageClassResourceKind,
} from '@console/internal/module/k8s';
import {
LoadingInline,
ResourceIcon,
Expand All @@ -13,6 +18,7 @@ import {
RequestSizeInput,
validate,
resourceObjPath,
convertToBaseValue,
} from '@console/internal/components/utils';
import {
ModalBody,
Expand All @@ -33,6 +39,8 @@ import { getInstantVectorStats } from '@console/internal/components/graphs/utils
import { usePrometheusPoll } from '@console/internal/components/graphs/prometheus-poll-hook';
import { getRequestedPVCSize } from '@console/shared/src/selectors';
import { dropdownUnits, accessModeRadios } from '@console/internal/components/storage/shared';
import { useK8sGet } from '@console/internal/components/utils/k8s-get-hook';
import { isCephProvisioner } from '@console/shared';

const ClonePVCModal = withHandlePromise((props: ClonePVCModalProps) => {
const { close, cancel, resource, handlePromise, errorMessage, inProgress } = props;
Expand All @@ -42,11 +50,18 @@ const ClonePVCModal = withHandlePromise((props: ClonePVCModalProps) => {

const [clonePVCName, setClonePVCName] = React.useState(`${pvcName}-clone`);
const [requestedSize, setRequestedSize] = React.useState(defaultSize[0] || '');
const [requestedUnit, setRequestedUnit] = React.useState(defaultSize[1] || 'Gi');
const accessMode = accessModeRadios.find(
(mode) => mode.value === resource?.spec?.accessModes?.[0],
);

const [requestedUnit, setRequestedUnit] = React.useState(defaultSize[1] || 'Ti');
const [validSize, setValidSize] = React.useState(true);

const [scResource, scResourceLoaded, scResourceLoadError] = useK8sGet<StorageClassResourceKind>(
StorageClassModel,
resource?.spec?.storageClassName,
);

const pvcUsedCapacityQuery: string = `kubelet_volume_stats_used_bytes{persistentvolumeclaim='${pvcName}'}`;
const [response, error, loading] = usePrometheusPoll({
endpoint: PrometheusEndpoint.QUERY,
Expand All @@ -62,6 +77,10 @@ const ClonePVCModal = withHandlePromise((props: ClonePVCModalProps) => {
const requestedSizeInputChange = ({ value, unit }) => {
setRequestedSize(value);
setRequestedUnit(unit);
const cloneSizeInBytes = convertToBaseValue(value + unit);
const pvcSizeInBytes = convertToBaseValue(getRequestedPVCSize(resource));
const isValid = cloneSizeInBytes >= pvcSizeInBytes;
setValidSize(isValid);
};

const submit = (event: React.FormEvent<EventTarget>) => {
Expand Down Expand Up @@ -111,16 +130,28 @@ const ClonePVCModal = withHandlePromise((props: ClonePVCModalProps) => {
aria-label="Clone Pvc"
/>
</FormGroup>
<FormGroup label="Size" isRequired fieldId="clone-pvc-modal__size">
<RequestSizeInput
name="requestSize"
testID="input-request-size"
onChange={requestedSizeInputChange}
defaultRequestSizeUnit={requestedUnit}
defaultRequestSizeValue={requestedSize}
dropdownUnits={dropdownUnits}
required
/>
<FormGroup
label="Size"
isRequired
fieldId="clone-pvc-modal__size"
className="co-clone-pvc-modal__ocs-size"
helperTextInvalid="Size should be equal or greater than the requested size of PVC"
validated={validSize ? 'default' : 'error'}
>
{scResourceLoaded ? (
<RequestSizeInput
name="requestSize"
testID="input-request-size"
onChange={requestedSizeInputChange}
defaultRequestSizeUnit={requestedUnit}
defaultRequestSizeValue={requestedSize}
dropdownUnits={dropdownUnits}
isInputDisabled={scResourceLoadError || isCephProvisioner(scResource?.provisioner)}
required
/>
) : (
<div className="skeleton-text" />
Copy link
Contributor

@afreen23 afreen23 Sep 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

)}
</FormGroup>
<div className="co-clone-pvc-modal__details">
<p className="text-muted">PVC Details</p>
Expand Down Expand Up @@ -170,6 +201,7 @@ const ClonePVCModal = withHandlePromise((props: ClonePVCModalProps) => {
</ModalBody>
<ModalSubmitFooter
inProgress={inProgress}
submitDisabled={!validSize}
errorMessage={errorMessage}
submitText="Clone"
cancel={cancel}
Expand Down
Expand Up @@ -15,3 +15,7 @@
.co-restore-pvc-modal__input {
margin: var(--pf-global--spacer--md) 0;
}

.co-restore-pvc-modal__ocs-size .form-group{
margin-bottom: var(--pf-global--spacer--sm);
}
Expand Up @@ -10,6 +10,7 @@ import {
RequestSizeInput,
Timestamp,
resourcePathFromModel,
convertToBaseValue,
} from '@console/internal/components/utils';
import {
k8sCreate,
Expand All @@ -31,7 +32,7 @@ import {
VolumeSnapshotModel,
VolumeSnapshotClassModel,
} from '@console/internal/models';
import { getName, getNamespace, Status } from '@console/shared';
import { getName, getNamespace, Status, isCephProvisioner } from '@console/shared';
import { StorageClassDropdown } from '@console/internal/components/utils/storage-class-dropdown';
import { dropdownUnits } from '@console/internal/components/storage/shared';
import { useK8sGet } from '@console/internal/components/utils/k8s-get-hook';
Expand All @@ -48,8 +49,9 @@ const RestorePVCModal = withHandlePromise<RestorePVCModalProps>(
? `${defaultSize[0]} ${dropdownUnits[defaultSize[1]]}`
: '';
const [requestedSize, setRequestedSize] = React.useState(defaultSize?.[0] ?? '');
const [requestedUnit, setRequestedUnit] = React.useState(defaultSize?.[1] ?? 'Gi');
const [requestedUnit, setRequestedUnit] = React.useState(defaultSize?.[1] ?? 'Ti');
const [pvcSC, setPVCStorageClass] = React.useState('');
const [validSize, setValidSize] = React.useState(true);
const namespace = getNamespace(resource);
const snapshotName = getName(resource);

Expand All @@ -74,6 +76,10 @@ const RestorePVCModal = withHandlePromise<RestorePVCModalProps>(
const requestedSizeInputChange = ({ value, unit }) => {
setRequestedSize(value);
setRequestedUnit(unit);
const restoreSizeInBytes = convertToBaseValue(value + unit);
const snapshotSizeInBytes = convertToBaseValue(resource?.status?.restoreSize);
const isValid = restoreSizeInBytes >= snapshotSizeInBytes;
setValidSize(isValid);
};

const handleStorageClass = (updatedStorageClass) =>
Expand Down Expand Up @@ -119,7 +125,6 @@ const RestorePVCModal = withHandlePromise<RestorePVCModalProps>(
},
);
};

return (
<div className="modal-content modal-content--no-inner-scroll">
<ModalTitle>Restore as new PVC</ModalTitle>
Expand Down Expand Up @@ -165,16 +170,26 @@ const RestorePVCModal = withHandlePromise<RestorePVCModalProps>(
label="Size"
isRequired
fieldId="pvc-size"
className="co-restore-pvc-modal__input"
className="co-restore-pvc-modal__input co-restore-pvc-modal__ocs-size"
helperTextInvalid="Size should be equal or greater than the restore size of snapshot"
validated={validSize ? 'default' : 'error'}
>
<RequestSizeInput
name="requestSize"
onChange={requestedSizeInputChange}
defaultRequestSizeUnit={requestedUnit}
defaultRequestSizeValue={requestedSize}
dropdownUnits={dropdownUnits}
required
/>
{snapshotClassResourceLoaded ? (
<RequestSizeInput
name="requestSize"
onChange={requestedSizeInputChange}
defaultRequestSizeUnit={requestedUnit}
defaultRequestSizeValue={requestedSize}
dropdownUnits={dropdownUnits}
isInputDisabled={
snapshotClassResourceLoadError ||
isCephProvisioner(snapshotClassResource?.driver)
}
required
/>
) : (
<div className="skeleton-text" />
Copy link
Contributor

@afreen23 afreen23 Sep 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if you have error ? It will be always showing loading state ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, its better to disable size input in that case.

)}
</FormGroup>
<div className="co-restore-pvc-modal__details-section">
<p className="text-muted">{VolumeSnapshotModel.label} details</p>
Expand Down Expand Up @@ -213,6 +228,7 @@ const RestorePVCModal = withHandlePromise<RestorePVCModalProps>(
</ModalBody>
<ModalSubmitFooter
inProgress={inProgress}
submitDisabled={!validSize}
errorMessage={errorMessage}
submitText="Restore"
cancel={cancel}
Expand Down
3 changes: 3 additions & 0 deletions frontend/public/components/utils/request-size-input.tsx
Expand Up @@ -38,6 +38,7 @@ export class RequestSizeInput extends React.Component<RequestSizeInputProps> {
required={this.props.required}
value={this.props.defaultRequestSizeValue}
min={this.props.minValue}
disabled={this.props.isInputDisabled}
/>
<Dropdown
title={this.props.dropdownUnits[this.props.defaultRequestSizeUnit]}
Expand All @@ -46,6 +47,7 @@ export class RequestSizeInput extends React.Component<RequestSizeInputProps> {
className="btn-group"
items={this.props.dropdownUnits}
onChange={this.onUnitChange}
disabled={this.props.isInputDisabled}
required={this.props.required}
ariaLabel={`Number of ${this.props.dropdownUnits[this.props.defaultRequestSizeUnit]}`}
/>
Expand All @@ -69,4 +71,5 @@ export type RequestSizeInputProps = {
inputClassName?: string;
inputID?: string;
testID?: string;
isInputDisabled?: boolean;
};