diff --git a/locales/en/plugin__kubevirt-plugin.json b/locales/en/plugin__kubevirt-plugin.json index 28e8e37f42..2a05004404 100644 --- a/locales/en/plugin__kubevirt-plugin.json +++ b/locales/en/plugin__kubevirt-plugin.json @@ -546,8 +546,10 @@ "IP addresses": "IP addresses", "It may take several minutes until the clone is done and the VirtualMachine is ready.": "It may take several minutes until the clone is done and the VirtualMachine is ready.", "It seems that your browser does not trust the certificate of the upload proxy. {uploadProxyURL && (\n <>\n Please{' '}\n \n approve this certificate\n {' '}\n and try again\n \n )}": "It seems that your browser does not trust the certificate of the upload proxy. {uploadProxyURL && (\n <>\n Please{' '}\n \n approve this certificate\n {' '}\n and try again\n \n )}", + "Kernel Samepage Merging (KSM)": "Kernel Samepage Merging (KSM)", "key": "key", "Key": "Key", + "KSM is a memory-saving de-duplication feature designed to fit more VirtualMachines into physical memory by sharing the data common between them.": "KSM is a memory-saving de-duplication feature designed to fit more VirtualMachines into physical memory by sharing the data common between them.", "Kubernetes NMState Operator": "Kubernetes NMState Operator", "KV data transfer rate": "KV data transfer rate", "Label selectors let you select Nodes based on the value of one or more labels.": "Label selectors let you select Nodes based on the value of one or more labels.", @@ -743,6 +745,7 @@ "Node labels": "Node labels", "Node port": "Node port", "Node selector": "Node selector", + "Node selector configuration": "Node selector configuration", "Nodes": "Nodes", "None": "None", "Not available": "Not available", @@ -873,6 +876,7 @@ "Reset": "Reset", "Resource": "Resource", "Resource already selected": "Resource already selected", + "Resource management": "Resource management", "Resource name": "Resource name", "Resources": "Resources", "Resources are being removed, please wait.": "Resources are being removed, please wait.", diff --git a/src/utils/components/NodeSelectorModal/NodeSelectorModal.tsx b/src/utils/components/NodeSelectorModal/NodeSelectorModal.tsx index adccb4f394..e1fc8f76f6 100644 --- a/src/utils/components/NodeSelectorModal/NodeSelectorModal.tsx +++ b/src/utils/components/NodeSelectorModal/NodeSelectorModal.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React, { FC, useMemo } from 'react'; import produce from 'immer'; import { NodeModel } from '@kubevirt-ui/kubevirt-api/console'; @@ -29,7 +29,7 @@ type NodeSelectorModalProps = { vmi?: V1VirtualMachineInstance; }; -const NodeSelectorModal: React.FC = ({ +const NodeSelectorModal: FC = ({ isOpen, nodes, nodesLoaded, @@ -50,7 +50,7 @@ const NodeSelectorModal: React.FC = ({ const onSelectorLabelAdd = () => onLabelAdd({ id: null, key: '', value: '' }); - const updatedVirtualMachine = React.useMemo(() => { + const updatedVirtualMachine = useMemo(() => { const updatedVM = produce(vm, (vmDraft: V1VirtualMachine) => { ensurePath(vmDraft, ['spec.template.template.spec.nodeSelector']); if (!vmDraft.spec.template.spec.nodeSelector) { diff --git a/src/views/clusteroverview/SettingsTab/ClusterTab/ClusterTab.tsx b/src/views/clusteroverview/SettingsTab/ClusterTab/ClusterTab.tsx index 18b7299711..60300a7827 100644 --- a/src/views/clusteroverview/SettingsTab/ClusterTab/ClusterTab.tsx +++ b/src/views/clusteroverview/SettingsTab/ClusterTab/ClusterTab.tsx @@ -7,6 +7,7 @@ import EnableLoadBalancerSection from './components/EnableLoadBalancerSection/En import EnablePreviewFeaturesSection from './components/EnablePreviewFeaturesSection/EnablePreviewFeaturesSection'; import GeneralInformation from './components/GeneralInformation/GeneralInformation'; import LiveMigrationSection from './components/LiveMigrationSection/LiveMigrationSection'; +import ResourceManagementSection from './components/ResourceManagementSection/ResourceManagementSection'; import TemplatesProjectSection from './components/TemplatesProjectSection/TemplatesProjectSection'; const ClusterTab: FC = () => { @@ -22,6 +23,8 @@ const ClusterTab: FC = () => { + + ); }; diff --git a/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/ResourceManagementSection.tsx b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/ResourceManagementSection.tsx new file mode 100644 index 0000000000..e1a2031f2e --- /dev/null +++ b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/ResourceManagementSection.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; + +import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; + +import ExpandSection from '../../../ExpandSection/ExpandSection'; + +import KernelSamepageMerging from './components/KernelSamepageMerging/KernelSamepageMerging'; + +const ResourceManagementSection: FC = () => { + const { t } = useKubevirtTranslation(); + + return ( + + + + ); +}; + +export default ResourceManagementSection; diff --git a/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/KernelSamepageMerging.scss b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/KernelSamepageMerging.scss new file mode 100644 index 0000000000..fcc445a516 --- /dev/null +++ b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/KernelSamepageMerging.scss @@ -0,0 +1,28 @@ +.KernelSamepageMerging { + &__ExpandSection { + padding-left: var(--pf-global--spacer--lg); + + .pf-c-expandable-section__content { + padding-left: var(--pf-global--spacer--lg); + } + + .pf-c-expandable-section__toggle { + padding-right: var(--pf-global--spacer--sm); + } + } + + &__HelpIcon, + .pf-c-switch { + vertical-align: -moz-middle-with-baseline !important; + } + + &__HelpIcon { + color: var(--pf-global--Color--100); + } + + &__HelpTextIcon { + .pf-c-popover__content { + width: 400px; + } + } +} diff --git a/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/KernelSamepageMerging.tsx b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/KernelSamepageMerging.tsx new file mode 100644 index 0000000000..cb93fccacf --- /dev/null +++ b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/KernelSamepageMerging.tsx @@ -0,0 +1,44 @@ +import React, { FC, useState } from 'react'; +import ExpandSection from 'src/views/clusteroverview/SettingsTab/ExpandSection/ExpandSection'; + +import HelpTextIcon from '@kubevirt-utils/components/HelpTextIcon/HelpTextIcon'; +import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; +import { PopoverPosition, Split, SplitItem, Switch } from '@patternfly/react-core'; + +import NodeSelectorConfiguration from './components/NodeSelectorConfiguration/NodeSelectorConfiguration'; + +import './KernelSamepageMerging.scss'; + +const KernelSamepageMerging: FC = () => { + const { t } = useKubevirtTranslation(); + const [isEnabled, setIsEnabled] = useState(false); + // TODO enable KSM if isEnabled + + return ( + + + + + + + + + + + + + + ); +}; + +export default KernelSamepageMerging; diff --git a/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/components/NodeSelectorConfiguration/NodeSelectorConfiguration.tsx b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/components/NodeSelectorConfiguration/NodeSelectorConfiguration.tsx new file mode 100644 index 0000000000..3dca4e6eba --- /dev/null +++ b/src/views/clusteroverview/SettingsTab/ClusterTab/components/ResourceManagementSection/components/KernelSamepageMerging/components/NodeSelectorConfiguration/NodeSelectorConfiguration.tsx @@ -0,0 +1,48 @@ +import React, { FC } from 'react'; + +import { useWizardVMContext } from '@catalog/utils/WizardVMContext'; +import { modelToGroupVersionKind, NodeModel } from '@kubevirt-ui/kubevirt-api/console'; +import { IoK8sApiCoreV1Node } from '@kubevirt-ui/kubevirt-api/kubernetes'; +import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider'; +import NodeSelectorModal from '@kubevirt-utils/components/NodeSelectorModal/NodeSelectorModal'; +import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; +import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; +import { Button, ButtonVariant } from '@patternfly/react-core'; +import { PencilAltIcon } from '@patternfly/react-icons'; + +const NodeSelectorConfiguration: FC = () => { + const { createModal } = useModal(); + const { t } = useKubevirtTranslation(); + const { updateVM } = useWizardVMContext(); + + const [nodes, nodesLoaded] = useK8sWatchResource({ + groupVersionKind: modelToGroupVersionKind(NodeModel), + isList: true, + }); + + const onNodeConfigure = () => + createModal(({ isOpen, onClose }) => ( + + )); + + return ( + + ); +}; + +export default NodeSelectorConfiguration; diff --git a/src/views/templates/details/tabs/scheduling/components/NodeSelector.tsx b/src/views/templates/details/tabs/scheduling/components/NodeSelector.tsx index 2a5639ffc7..8abe8e8fe7 100644 --- a/src/views/templates/details/tabs/scheduling/components/NodeSelector.tsx +++ b/src/views/templates/details/tabs/scheduling/components/NodeSelector.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { FC } from 'react'; import { TemplateSchedulingGridProps } from 'src/views/templates/details/tabs/scheduling/components/TemplateSchedulingLeftGrid'; import { getNodeSelector } from 'src/views/templates/utils/selectors'; @@ -7,6 +7,7 @@ import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTransla import { isEmpty } from '@kubevirt-utils/utils/utils'; import { Button, + ButtonVariant, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, @@ -17,7 +18,7 @@ import { PencilAltIcon } from '@patternfly/react-icons'; import NodeSelectorModal from './NodeSelectorModal'; -const NodeSelector: React.FC = ({ editable, onSubmit, template }) => { +const NodeSelector: FC = ({ editable, onSubmit, template }) => { const { t } = useKubevirtTranslation(); const { createModal } = useModal(); const nodeSelector = getNodeSelector(template); @@ -51,7 +52,7 @@ const NodeSelector: React.FC = ({ editable, onSubmi isInline onClick={onEditClick} type="button" - variant="link" + variant={ButtonVariant.link} > {nodeSelectorLabels}