Skip to content

Commit

Permalink
Merge pull request openshift#6106 from glekner/add-golden-os-pvc
Browse files Browse the repository at this point in the history
Add Golden image switch to PVC upload form
  • Loading branch information
openshift-merge-robot authored Jul 26, 2020
2 parents 99c0004 + e2e4733 commit 9a3e2cb
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
.kv--create-upload__alert {
text-align: left;
}

.kv--create-upload__golden-switch {
margin-top: var(--pf-global--spacer--sm);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ import * as React from 'react';
import cx from 'classnames';
import { Helmet } from 'react-helmet';
import { match } from 'react-router';
import { FileUpload, ActionGroup, Alert, Button } from '@patternfly/react-core';
import {
FileUpload,
ActionGroup,
Alert,
Button,
Switch,
FormSelect,
FormSelectOption,
} from '@patternfly/react-core';
import { isCephProvisioner, isObjectSC } from '@console/shared/src/utils';
import { K8sResourceKind, apiVersionForModel } from '@console/internal/module/k8s';
import { K8sResourceKind, apiVersionForModel, TemplateKind } from '@console/internal/module/k8s';
import {
ButtonBar,
RequestSizeInput,
Expand All @@ -23,25 +31,57 @@ import {
dropdownUnits,
getAccessModeForProvisioner,
} from '@console/internal/components/storage/shared';
import {
useK8sWatchResource,
WatchK8sResource,
} from '@console/internal/components/utils/k8s-watch-hook';
import { DataVolumeModel } from '../../../models';
import { createUploadPVC } from '../../../k8s/requests/cdi-upload/cdi-upload-requests';
import { CDIUploadContext } from '../cdi-upload-provider';
import { UploadPVCFormStatus } from './upload-pvc-form-status';
import { PersistentVolumeClaimModel } from '@console/internal/models';
import { PersistentVolumeClaimModel, TemplateModel } from '@console/internal/models';
import { getName } from '@console/shared';
import { V1alpha1DataVolume } from '../../../types/vm/disk/V1alpha1DataVolume';
import { getTemplateOperatingSystems } from '../../../selectors/vm-template/advanced';
import { FormSelectPlaceholderOption } from '../../form/form-select-placeholder-option';
import {
TEMPLATE_TYPE_BASE,
TEMPLATE_TYPE_LABEL,
TEMPLATE_VM_GOLDEN_OS_NAMESPACE,
TEMPLATE_VM_COMMON_NAMESPACE,
} from '../../../constants';
import './upload-pvc-form.scss';

const templatesResource: WatchK8sResource = {
isList: true,
optional: true,
kind: TemplateModel.kind,
namespace: TEMPLATE_VM_COMMON_NAMESPACE,
selector: {
matchLabels: { [TEMPLATE_TYPE_LABEL]: TEMPLATE_TYPE_BASE },
},
};

const goldenPvcsResource: WatchK8sResource = {
isList: true,
optional: true,
kind: PersistentVolumeClaimModel.kind,
namespace: TEMPLATE_VM_GOLDEN_OS_NAMESPACE,
};

export const UploadPVCForm: React.FC<UploadPVCFormProps> = (props) => {
const [accessModeHelp, setAccessModeHelp] = React.useState('Permissions to the mounted drive.');
const [allowedAccessModes, setAllowedAccessModes] = React.useState(initialAccessModes);
const [storageClass, setStorageClass] = React.useState('');
const [pvcName, setPvcName] = React.useState('');
const [namespace, setNamespace] = React.useState(props.namespace);
const [accessMode, setAccessMode] = React.useState('ReadWriteOnce');
const [requestSizeValue, setRequestSizeValue] = React.useState('');
const [requestSizeUnit, setRequestSizeUnit] = React.useState('Gi');
const [storageProvisioner, setStorageProvisioner] = React.useState('');
const { namespace, onChange, fileName, handleFileChange, fileValue } = props;
const [isGolden, setIsGolden] = React.useState(false);
const [os, setOs] = React.useState('');
const { onChange, fileName, handleFileChange, fileValue, commonTemplates, goldenPvcs } = props;

React.useEffect(() => {
const updateDV = (): K8sResourceKind => {
Expand Down Expand Up @@ -127,6 +167,25 @@ export const UploadPVCForm: React.FC<UploadPVCFormProps> = (props) => {

const onlyPvcSCs = React.useCallback((sc: StorageClass) => !isObjectSC(sc), []);

const operatingSystems = getTemplateOperatingSystems(commonTemplates);

const handleOs = (osKey) => {
const operatingSystem = operatingSystems.find((newOs) => newOs.id === osKey);

setOs(osKey);
setPvcName(operatingSystem?.dataVolumeName || osKey);
setNamespace(operatingSystem?.dataVolumeNamespace || TEMPLATE_VM_GOLDEN_OS_NAMESPACE);
};

React.useEffect(() => {
if (isGolden && pvcName && !os) {
setPvcName('');
}
if (!isGolden) {
setNamespace(props.namespace);
}
}, [isGolden, os, props.namespace, pvcName]);

return (
<div>
<div className="form-group">
Expand All @@ -147,35 +206,87 @@ export const UploadPVCForm: React.FC<UploadPVCFormProps> = (props) => {
hideDefaultPreview
isRequired
/>
</div>
<div className="form-group">
<StorageClassDropdown
onChange={handleStorageClass}
id="storageclass-dropdown"
describedBy="storageclass-dropdown-help"
required={false}
name="storageClass"
filter={onlyPvcSCs}
<Switch
id="golden-os-switch"
className="kv--create-upload__golden-switch"
label="Attach this data to a Virtual Machine operating system"
isChecked={isGolden}
onChange={(checked) => setIsGolden(checked)}
/>
</div>
{isGolden && (
<>
<label className="control-label co-required" htmlFor="golden-os">
Operating System
</label>
<div className="form-group">
<FormSelect id="golden-os-select" onChange={handleOs} value={os} isRequired>
<FormSelectPlaceholderOption
placeholder="--- Pick an Operating system ---"
isDisabled={!!os}
/>
{operatingSystems.map(({ id, name, dataVolumeName }) =>
goldenPvcs?.find((pvc) => getName(pvc) === dataVolumeName) ? (
<FormSelectOption
isDisabled
key={id}
value={id}
label={`${name || id} - Default data image already exists`}
/>
) : (
<FormSelectOption key={id} value={id} label={name || id} />
),
)}
</FormSelect>
</div>
<label className="control-label co-required" htmlFor="pvc-namespace">
Namespace
</label>
<div className="form-group">
<input
disabled
className="pf-c-form-control"
type="text"
aria-describedby="pvc-namespace-help"
id="pvc-namespace"
value={namespace}
required
/>
<p className="help-block" id="pvc-namespace-help">
A unique namespace for the storage claim within the project.
</p>
</div>
</>
)}
<label className="control-label co-required" htmlFor="pvc-name">
Persistent Volume Claim Name
</label>
<div className="form-group">
<input
disabled={isGolden}
className="pf-c-form-control"
type="text"
onChange={handlePvcName}
placeholder="my-storage-claim"
placeholder={isGolden ? '' : 'my-storage-claim'}
aria-describedby="pvc-name-help"
id="pvc-name"
name="pvcName"
value={pvcName}
required
/>
<p className="help-block" id="pvc-name-help">
A unique name for the storage claim within the project.
</p>
</div>
<div className="form-group">
<StorageClassDropdown
onChange={handleStorageClass}
id="storageclass-dropdown"
describedBy="storageclass-dropdown-help"
required={false}
name="storageClass"
filter={onlyPvcSCs}
/>
</div>
<label className="control-label co-required" htmlFor="access-mode">
Access Mode
</label>
Expand Down Expand Up @@ -234,6 +345,12 @@ export const UploadPVCPage: React.FC<UploadPVCPageProps> = (props) => {
const [error, setError] = React.useState('');
const [isAllocating, setIsAllocating] = React.useState(false);
const [dvObj, setDvObj] = React.useState<V1alpha1DataVolume>(null);
const [commonTemplates, loadedTemplates, errorTemplates] = useK8sWatchResource<TemplateKind[]>(
templatesResource,
);
const [goldenPvcs, loadedPvcs, errorPvcs] = useK8sWatchResource<K8sResourceKind[]>(
goldenPvcsResource,
);

const { uploads, uploadData } = React.useContext(CDIUploadContext);
const namespace = props?.match?.params?.ns;
Expand Down Expand Up @@ -269,6 +386,12 @@ export const UploadPVCPage: React.FC<UploadPVCPageProps> = (props) => {
setFileValue(value);
};

React.useEffect(() => {
if (errorTemplates || errorPvcs) {
setError(errorTemplates || errorPvcs);
}
}, [errorTemplates, errorPvcs]);

return (
<>
<Helmet>
Expand All @@ -289,8 +412,10 @@ export const UploadPVCPage: React.FC<UploadPVCPageProps> = (props) => {
fileValue={fileValue}
fileName={fileName}
handleFileChange={handleFileChange}
commonTemplates={commonTemplates}
goldenPvcs={goldenPvcs}
/>
<ButtonBar errorMessage={error}>
<ButtonBar inProgress={!loadedTemplates || !loadedPvcs} errorMessage={error}>
<ActionGroup className="pf-c-form">
<Button id="save-changes" type="submit" variant="primary">
Upload
Expand Down Expand Up @@ -326,6 +451,8 @@ export type UploadPVCFormProps = {
namespace: string;
fileValue: string | File;
fileName: string;
commonTemplates: TemplateKind[];
goldenPvcs: K8sResourceKind[];
onChange: (K8sResourceKind) => void;
handleFileChange: (value, filename, event) => void;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export const TEMPLATE_OS_NAME_ANNOTATION = 'name.os.template.kubevirt.io';
export const TEMPLATE_DATAVOLUME_ANNOTATION = 'datavolume.template.kubevirt.io';
export const TEMPLATE_VM_DOMAIN_LABEL = 'kubevirt.io/domain';
export const TEMPLATE_VM_SIZE_LABEL = 'kubevirt.io/size';
export const TEMPLATE_VM_GOLDEN_OS_NAMESPACE = 'openshift-cnv-base-images';
export const TEMPLATE_VM_COMMON_NAMESPACE = 'openshift';

export const LABEL_USED_TEMPLATE_NAME = 'vm.kubevirt.io/template';
export const LABEL_USED_TEMPLATE_NAMESPACE = 'vm.kubevirt.io/template.namespace';
Expand Down

0 comments on commit 9a3e2cb

Please sign in to comment.