Skip to content

Commit

Permalink
Added eviction strategy information on details page and a model with …
Browse files Browse the repository at this point in the history
…checkbox to control it.

Also, changed some styling and translation in dedicated-services-modal

Signed-off-by: metalice <mschatzm@redhat.com>
  • Loading branch information
metalice committed Nov 22, 2020
1 parent 757e95a commit 4c3ab99
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 26 deletions.
Expand Up @@ -17,6 +17,8 @@
"Policy has been updated outside this flow.": "Policy has been updated outside this flow.",
"Saving these changes will override any policy previously saved.": "Saving these changes will override any policy previously saved.",
"Reload Policy": "Reload Policy",
"Eviction Strategy": "Eviction Strategy",
"EvictionStrategy can be set to \"LiveMigrate\" if the VirtualMachineInstance should be migrated instead of shut-off in case of a node drain.": "EvictionStrategy can be set to \"LiveMigrate\" if the VirtualMachineInstance should be migrated instead of shut-off in case of a node drain.",
"Node Selector": "Node Selector",
"Tolerations": "Tolerations",
"Tolerations are applied to VMs, and allow (but do not require) the VMs to schedule onto nodes with matching taints.": "Tolerations are applied to VMs, and allow (but do not require) the VMs to schedule onto nodes with matching taints.",
Expand Down Expand Up @@ -48,6 +50,7 @@
"Flavor": "Flavor",
"Workload scheduled with dedicated resources (guaranteed policy)": "Workload scheduled with dedicated resources (guaranteed policy)",
"No Dedicated resources applied": "No Dedicated resources applied",
"No Eviction Strategy": "No Eviction Strategy",
"Virtual Machines": "Virtual Machines",
"Overview": "Overview",
"Details": "Details",
Expand Down

This file was deleted.

Expand Up @@ -19,7 +19,8 @@ import { useNodeQualifier } from '../shared/hooks';
import { ModalFooter } from '../../modal/modal-footer';
import { NodeChecker } from '../shared/NodeChecker/node-checker';
import { DEDICATED_RESOURCES_LABELS } from '../shared/consts';
import './dedicated-resources-modal.scss';

import '../shared/scheduling-modals.scss';

export const DedicatedResourcesModal = withHandlePromise<DedicatedResourcesModalProps>(
({
Expand Down Expand Up @@ -71,7 +72,7 @@ export const DedicatedResourcesModal = withHandlePromise<DedicatedResourcesModal
<ModalTitle>{t('kubevirt-plugin~Dedicated Resources')}</ModalTitle>
<ModalBody>
<Checkbox
className="kubevirt-dedicated-resources__checkbox"
className="kubevirt-scheduling__checkbox"
label={t(
'kubevirt-plugin~Schedule this workload with dedicated resources (guaranteed policy)',
)}
Expand All @@ -80,18 +81,14 @@ export const DedicatedResourcesModal = withHandlePromise<DedicatedResourcesModal
onChange={(flag) => setIsPinned(flag)}
id="dedicated-resources-checkbox"
/>
<Text
className="kubevirt-dedicated-resources__helper-text"
component={TextVariants.small}
>
{t('kubevirt-plugin~Available only on Nodes with labels')}{' '}
<Label kind={NodeModel.kind} name="cpumanager" value="true" expand />
<Text className="kubevirt-scheduling__helper-text" component={TextVariants.small}>
{t('kubevirt-plugin~Available only on Nodes with labels')}
</Text>
<Label kind={NodeModel.kind} name="cpumanager" value="true" expand />
<NodeChecker qualifiedNodes={qualifiedNodes} />
</ModalBody>
<ModalFooter
id="dedicated-resources"
className="kubevirt-dedicated-resources__footer"
errorMessage={errorMessage}
inProgress={!isLoaded(nodes) || inProgress}
isSimpleError={!!loadError}
Expand Down
@@ -0,0 +1,72 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import {
createModalLauncher,
ModalTitle,
ModalBody,
ModalComponentProps,
} from '@console/internal/components/factory';
import { k8sPatch } from '@console/internal/module/k8s';
import { Checkbox, TextVariants, Text } from '@patternfly/react-core';
import { withHandlePromise, HandlePromiseProps } from '@console/internal/components/utils';
import { ModalFooter } from '../../modal/modal-footer';
import { getEvictionStrategyPatch } from '../../../../k8s/patches/vm/vm-scheduling-patches';
import { getVMLikeModel } from '../../../../selectors/vm/vmlike';
import { VMLikeEntityKind } from '../../../../types/vmLike';
import '../shared/scheduling-modals.scss';

const EvictionStrategyModal = withHandlePromise<EvictionStrategyModalWithPromiseProps>((props) => {
const { vmLikeEntity, evictionStrategy, inProgress, close, handlePromise } = props;

const { t } = useTranslation();
const [isCheckedEvictionStrategy, setIsCheckedEvictionStrategy] = React.useState<boolean>(
!!evictionStrategy,
);

const onModalSubmit = () => {
if (isCheckedEvictionStrategy !== !!evictionStrategy) {
handlePromise(
k8sPatch(
getVMLikeModel(vmLikeEntity),
vmLikeEntity,
getEvictionStrategyPatch(vmLikeEntity, isCheckedEvictionStrategy),
),
close,
);
}
};

return (
<div className="modal-content">
<ModalTitle>{t('kubevirt-plugin~Eviction Strategy')}</ModalTitle>
<ModalBody>
<Checkbox
id="eviction-strategy"
className="kubevirt-scheduling__checkbox"
isChecked={isCheckedEvictionStrategy}
onChange={() => setIsCheckedEvictionStrategy((value) => !value)}
label="LiveMigrate"
/>
<Text className="kubevirt-scheduling__helper-text" component={TextVariants.small}>
{t(
'kubevirt-plugin~EvictionStrategy can be set to "LiveMigrate" if the VirtualMachineInstance should be migrated instead of shut-off in case of a node drain.',
)}
</Text>
</ModalBody>
<ModalFooter
onCancel={close}
inProgress={inProgress}
onSubmit={onModalSubmit}
submitButtonText={t('kubevirt-plugin~Save')}
/>
</div>
);
});

type EvictionStrategyModalWithPromiseProps = HandlePromiseProps &
ModalComponentProps & {
vmLikeEntity: VMLikeEntityKind;
evictionStrategy: string;
};

export default createModalLauncher(EvictionStrategyModal);
Expand Up @@ -11,3 +11,13 @@
color: var(--pf-global--Color--200);
}
}

.kubevirt-scheduling__checkbox {
margin-top: var(--pf-global--spacer--md);
margin-bottom: var(--pf-global--spacer--md);
}

.kubevirt-scheduling__helper-text {
color: var(--pf-global--Color--200);
margin-right: var(--pf-global--spacer--sm);
}
Expand Up @@ -9,6 +9,7 @@ import dedicatedResourcesModal from '../modals/scheduling-modals/dedicated-resou
import tolerationsModal from '../modals/scheduling-modals/tolerations-modal/connected-tolerations-modal';
import nodeSelectorModal from '../modals/scheduling-modals/node-selector-modal/connected-node-selector-modal';
import affinityModal from '../modals/scheduling-modals/affinity-modal/connected-affinity-modal';
import evictionStrategyModal from '../modals/scheduling-modals/eviction-strategy-modal/eviction-strategy-modal';
import { getRowsDataFromAffinity } from '../modals/scheduling-modals/affinity-modal/helpers';
import { getDescription } from '../../selectors/selectors';
import {
Expand Down Expand Up @@ -141,6 +142,7 @@ export const VMTemplateSchedulingList: React.FC<VMTemplateResourceSummaryProps>
});
const isCPUPinned = isDedicatedCPUPlacement(vm);
const nodeSelector = vmWrapper?.getNodeSelector();
const evictionStrategy = vmWrapper?.getEvictionStrategy();
const tolerations = vmWrapper?.getTolerations() || [];
const tolerationsLabels = tolerations.reduce((acc, { key, value }) => {
acc[key] = value;
Expand Down Expand Up @@ -224,6 +226,19 @@ export const VMTemplateSchedulingList: React.FC<VMTemplateResourceSummaryProps>
? t('kubevirt-plugin~Workload scheduled with dedicated resources (guaranteed policy)')
: t('kubevirt-plugin~No Dedicated resources applied')}
</VMDetailsItem>
<VMDetailsItem
title={t('kubevirt-plugin~Eviction Strategy')}
idValue={prefixedID(id, 'eviction-strategy')}
canEdit={canUpdateTemplate}
onEditClick={() =>
evictionStrategyModal({ vmLikeEntity: vm, evictionStrategy, blocking: true })
}
editButtonId={prefixedID(id, 'eviction-strategy-edit')}
>
{evictionStrategy || (
<p className="text-muted">{t('kubevirt-plugin~No Eviction Strategy')}</p>
)}
</VMDetailsItem>
</dl>
</div>
</>
Expand Down
Expand Up @@ -12,6 +12,7 @@ import { descriptionModal, vmFlavorModal } from '../modals';
import { BootOrderModal } from '../modals/boot-order-modal/boot-order-modal';
import dedicatedResourcesModal from '../modals/scheduling-modals/dedicated-resources-modal/connected-dedicated-resources-modal';
import nodeSelectorModal from '../modals/scheduling-modals/node-selector-modal/connected-node-selector-modal';
import evictionStrategyModal from '../modals/scheduling-modals/eviction-strategy-modal/eviction-strategy-modal';
import tolerationsModal from '../modals/scheduling-modals/tolerations-modal/connected-tolerations-modal';
import affinityModal from '../modals/scheduling-modals/affinity-modal/connected-affinity-modal';
import { getRowsDataFromAffinity } from '../modals/scheduling-modals/affinity-modal/helpers';
Expand Down Expand Up @@ -288,6 +289,7 @@ export const VMSchedulingList: React.FC<VMSchedulingListProps> = ({
});
const isCPUPinned = vmiLikeWrapper?.isDedicatedCPUPlacement();
const nodeSelector = vmiLikeWrapper?.getNodeSelector();
const evictionStrategy = vmiLikeWrapper?.getEvictionStrategy();
const tolerationsWrapperCount = (vmiLikeWrapper?.getTolerations() || []).length;
const affinityWrapperCount = getRowsDataFromAffinity(vmiLikeWrapper?.getAffinity())?.length;

Expand Down Expand Up @@ -372,6 +374,20 @@ export const VMSchedulingList: React.FC<VMSchedulingListProps> = ({
? t('kubevirt-plugin~Workload scheduled with dedicated resources (guaranteed policy)')
: t('kubevirt-plugin~No Dedicated resources applied')}
</VMDetailsItem>

<VMDetailsItem
title={t('kubevirt-plugin~Eviction Strategy')}
idValue={prefixedID(id, 'eviction-strategy')}
canEdit={canEdit}
onEditClick={() =>
evictionStrategyModal({ vmLikeEntity: vm, evictionStrategy, blocking: true })
}
editButtonId={prefixedID(id, 'eviction-strategy-edit')}
>
{evictionStrategy || (
<p className="text-muted">{t('kubevirt-plugin~No Eviction Strategy')}</p>
)}
</VMDetailsItem>
</dl>
</div>
</>
Expand Down
Expand Up @@ -38,3 +38,15 @@ export const getAffinityPatch = (vmLikeEntity: VMLikeEntityKind, affinity: Affin
: getVMLikePatches(vmLikeEntity, () => [
new PatchBuilder('/spec/template/spec/affinity').remove().build(),
]);

export const getEvictionStrategyPatch = (
vmLikeEntity: VMLikeEntityKind,
isEvictionStrategyChecked: boolean,
): Patch[] =>
isEvictionStrategyChecked
? getVMLikePatches(vmLikeEntity, () => [
new PatchBuilder('/spec/template/spec/evictionStrategy').add('LiveMigrate').build(),
])
: getVMLikePatches(vmLikeEntity, () => [
new PatchBuilder('/spec/template/spec/evictionStrategy').remove().build(),
]);
Expand Up @@ -3,7 +3,7 @@ import * as _ from 'lodash';
import { getLabels } from '@console/shared/src/selectors/common';
import { compareOwnerReference } from '@console/shared/src/utils/owner-references';
import { K8sResourceWrapper } from '../common/k8s-resource-wrapper';
import { CPURaw, V1NetworkInterface, VMKind } from '../../../types/vm';
import { CPURaw, V1NetworkInterface, VMISpec, VMKind } from '../../../types';
import {
getCloudInitVolume,
getDataVolumeTemplates,
Expand Down Expand Up @@ -43,9 +43,10 @@ export class VMWrapper extends K8sResourceWrapper<VMKind, VMWrapper> implements
getOperatingSystem = () => findKeySuffixValue(this.getLabels(), TEMPLATE_OS_LABEL);
getWorkloadProfile = () => findKeySuffixValue(this.getLabels(), TEMPLATE_WORKLOAD_LABEL);
getFlavor = () => findKeySuffixValue(this.getLabels(), TEMPLATE_FLAVOR_LABEL);

getMemory = () => this.data?.spec?.template?.spec?.domain?.resources?.requests?.memory;
getCPU = (): CPURaw => this.data?.spec?.template?.spec?.domain?.cpu;
getVirtualMachineInstanceSpec = (): VMISpec => this.data?.spec?.template?.spec;
getEvictionStrategy = (): string => this.getVirtualMachineInstanceSpec()?.evictionStrategy;
getMemory = () => this.getVirtualMachineInstanceSpec()?.domain?.resources?.requests?.memory;
getCPU = (): CPURaw => this.getVirtualMachineInstanceSpec()?.domain?.cpu;

getTemplateLabels = (defaultValue = {}) =>
getLabels(_.get(this.data, 'spec.template'), defaultValue);
Expand Down
@@ -1,5 +1,5 @@
/* eslint-disable lines-between-class-members */
import { CPURaw, VMIKind } from '../../../types/vm';
import { CPURaw, VMIKind, VMISpec } from '../../../types';
import { K8sResourceWrapper } from '../common/k8s-resource-wrapper';
import {
getVMIDisks,
Expand Down Expand Up @@ -30,9 +30,10 @@ export class VMIWrapper extends K8sResourceWrapper<VMIKind, VMIWrapper> implemen
getOperatingSystem = () => findKeySuffixValue(this.getLabels(), TEMPLATE_OS_LABEL);
getWorkloadProfile = () => findKeySuffixValue(this.getLabels(), TEMPLATE_WORKLOAD_LABEL);
getFlavor = () => findKeySuffixValue(this.getLabels(), TEMPLATE_FLAVOR_LABEL);

getMemory = () => this.data?.spec?.domain?.resources?.requests?.memory;
getCPU = (): CPURaw => this.data?.spec?.domain?.cpu;
getVirtualMachineInstanceSpec = (): VMISpec => this.data?.spec;
getEvictionStrategy = (): string => this.getVirtualMachineInstanceSpec()?.evictionStrategy;
getMemory = () => this.getVirtualMachineInstanceSpec()?.domain?.resources?.requests?.memory;
getCPU = (): CPURaw => this.getVirtualMachineInstanceSpec()?.domain?.cpu;

getNetworkInterfaces = (defaultValue = []) => getVMIInterfaces(this.data, defaultValue);

Expand Down
2 changes: 1 addition & 1 deletion frontend/packages/kubevirt-plugin/src/types/vm/index.ts
Expand Up @@ -11,7 +11,7 @@ export type VMISpec = {
dnsConfig: any;
dnsPolicy: string;
domain?: any;
evictionStrategy: any;
evictionStrategy?: string;
hostname: string;
livenessProbe: any;
networks?: any[];
Expand Down

0 comments on commit 4c3ab99

Please sign in to comment.