mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2025-12-13 21:21:44 +00:00
Add USB devices page skeleton
Signed-off-by: Francesco Torchia <francesco.torchia@suse.com>
This commit is contained in:
parent
e8fbeccc72
commit
ee963b7c1c
@ -419,6 +419,7 @@ export function init($plugin, store) {
|
|||||||
HCI.PCI_DEVICE,
|
HCI.PCI_DEVICE,
|
||||||
HCI.SR_IOVGPU_DEVICE,
|
HCI.SR_IOVGPU_DEVICE,
|
||||||
HCI.VGPU_DEVICE,
|
HCI.VGPU_DEVICE,
|
||||||
|
HCI.USB_DEVICE,
|
||||||
HCI.ADD_ONS,
|
HCI.ADD_ONS,
|
||||||
HCI.SECRET,
|
HCI.SECRET,
|
||||||
HCI.SETTING
|
HCI.SETTING
|
||||||
@ -752,6 +753,32 @@ export function init($plugin, store) {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
virtualType({
|
||||||
|
labelKey: 'harvester.usb.label',
|
||||||
|
group: 'advanced',
|
||||||
|
weight: 11,
|
||||||
|
name: HCI.USB_DEVICE,
|
||||||
|
namespaced: false,
|
||||||
|
route: {
|
||||||
|
name: `${ PRODUCT_NAME }-c-cluster-resource`,
|
||||||
|
params: { resource: HCI.USB_DEVICE }
|
||||||
|
},
|
||||||
|
exact: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
configureType(HCI.USB_DEVICE, {
|
||||||
|
isCreatable: false,
|
||||||
|
hiddenNamespaceGroupButton: true,
|
||||||
|
listGroups: [
|
||||||
|
{
|
||||||
|
value: 'node',
|
||||||
|
field: 'groupByNode',
|
||||||
|
hideColumn: 'node',
|
||||||
|
tooltipKey: 'resourceTable.groupBy.node'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
configureType(HCI.ADD_ONS, {
|
configureType(HCI.ADD_ONS, {
|
||||||
isCreatable: false,
|
isCreatable: false,
|
||||||
isRemovable: false,
|
isRemovable: false,
|
||||||
|
|||||||
@ -68,4 +68,5 @@ export const ADD_ONS = {
|
|||||||
RANCHER_LOGGING: 'rancher-logging',
|
RANCHER_LOGGING: 'rancher-logging',
|
||||||
RANCHER_MONITORING: 'rancher-monitoring',
|
RANCHER_MONITORING: 'rancher-monitoring',
|
||||||
VM_IMPORT_CONTROLLER: 'vm-import-controller',
|
VM_IMPORT_CONTROLLER: 'vm-import-controller',
|
||||||
|
USB_DEVICE_CONTROLLER: 'usbdevices-controller',
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
<script>
|
||||||
|
import Tabbed from '@shell/components/Tabbed';
|
||||||
|
import Tab from '@shell/components/Tabbed/Tab';
|
||||||
|
import { RadioGroup } from '@components/Form/Radio';
|
||||||
|
|
||||||
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'EditAddonUSB',
|
||||||
|
components: {
|
||||||
|
Tabbed,
|
||||||
|
Tab,
|
||||||
|
RadioGroup,
|
||||||
|
},
|
||||||
|
|
||||||
|
mixins: [CreateEditView],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Tabbed :side-tabs="true">
|
||||||
|
<Tab
|
||||||
|
name="basic"
|
||||||
|
:label="t('harvester.addons.usbController.titles.basic')"
|
||||||
|
:weight="99"
|
||||||
|
>
|
||||||
|
<RadioGroup
|
||||||
|
v-model="value.spec.enabled"
|
||||||
|
class="mb-20"
|
||||||
|
name="model"
|
||||||
|
:mode="mode"
|
||||||
|
:options="[true,false]"
|
||||||
|
:labels="[t('generic.enabled'), t('generic.disabled')]"
|
||||||
|
/>
|
||||||
|
</Tab>
|
||||||
|
</Tabbed>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
::v-deep .radio-group {
|
||||||
|
display: flex;
|
||||||
|
.radio-container {
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
<script>
|
||||||
|
import { _EDIT } from '@shell/config/query-params';
|
||||||
|
import { allHash } from '@shell/utils/promise';
|
||||||
|
import { HCI } from '../../../types';
|
||||||
|
import { STATE, SIMPLE_NAME } from '@shell/config/table-headers';
|
||||||
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||||
|
import Banner from '@components/Banner/Banner.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'VirtualMachineUSBDevices',
|
||||||
|
components: {
|
||||||
|
Banner,
|
||||||
|
LabeledSelect,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: _EDIT
|
||||||
|
},
|
||||||
|
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
|
||||||
|
vm: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetch() {
|
||||||
|
const hash = {
|
||||||
|
devices: this.$store.dispatch('harvester/findAll', { type: HCI.USB_DEVICE }),
|
||||||
|
vms: this.$store.dispatch(`harvester/findAll`, { type: HCI.VM })
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await allHash(hash);
|
||||||
|
|
||||||
|
for (const key in res) {
|
||||||
|
this[key] = res[key];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
deviceSchema: this.$store.getters['harvester/schemaFor'](HCI.USB_DEVICE),
|
||||||
|
deviceHeaders: [
|
||||||
|
{ ...STATE },
|
||||||
|
SIMPLE_NAME,
|
||||||
|
],
|
||||||
|
devices: [],
|
||||||
|
vms: [],
|
||||||
|
selectedDevices: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div> USB Devices </div>
|
||||||
|
</template>
|
||||||
@ -15,6 +15,11 @@ import Labels from '@shell/components/form/Labels';
|
|||||||
|
|
||||||
import NodeScheduling from '@shell/components/form/NodeScheduling';
|
import NodeScheduling from '@shell/components/form/NodeScheduling';
|
||||||
import PodAffinity from '@shell/components/form/PodAffinity';
|
import PodAffinity from '@shell/components/form/PodAffinity';
|
||||||
|
import AccessCredentials from './VirtualMachineAccessCredentials';
|
||||||
|
import PciDevices from './VirtualMachinePciDevices/index';
|
||||||
|
import VGpuDevices from './VirtualMachineVGpuDevices/index';
|
||||||
|
import UsbDevices from './VirtualMachineUSBDevices/index';
|
||||||
|
import RestartVMDialog from '../../dialog/RestartVMDialog';
|
||||||
import KeyValue from '@shell/components/form/KeyValue';
|
import KeyValue from '@shell/components/form/KeyValue';
|
||||||
|
|
||||||
import { clear } from '@shell/utils/array';
|
import { clear } from '@shell/utils/array';
|
||||||
@ -69,10 +74,11 @@ export default {
|
|||||||
PciDevices,
|
PciDevices,
|
||||||
RestartVMDialog,
|
RestartVMDialog,
|
||||||
UnitInput,
|
UnitInput,
|
||||||
VirtualMachineVGpuDevices,
|
VGpuDevices,
|
||||||
KeyValue,
|
KeyValue,
|
||||||
Banner,
|
Banner,
|
||||||
MessageLink
|
MessageLink,
|
||||||
|
UsbDevices,
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [CreateEditView, VM_MIXIN],
|
mixins: [CreateEditView, VM_MIXIN],
|
||||||
@ -652,10 +658,14 @@ export default {
|
|||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab v-if="enabledSriovgpu" :label="t('harvester.tab.vGpuDevices')" name="vGpuDevices" :weight="-6">
|
<Tab v-if="enabledSriovgpu" :label="t('harvester.tab.vGpuDevices')" name="vGpuDevices" :weight="-6">
|
||||||
<VirtualMachineVGpuDevices :mode="mode" :value="spec.template.spec" :vm="value" />
|
<VGpuDevices :mode="mode" :value="spec.template.spec" :vm="value" />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
<Tab v-if="isEdit" :label="t('harvester.tab.accessCredentials')" name="accessCredentials" :weight="-7">
|
<Tab v-if="enabledUSB" :label="t('harvester.tab.usbDevices')" name="usbDevices" :weight="-7">
|
||||||
|
<UsbDevices :mode="mode" :value="spec.template.spec" :vm="value" />
|
||||||
|
</Tab>
|
||||||
|
|
||||||
|
<Tab v-if="isEdit" :label="t('harvester.tab.accessCredentials')" name="accessCredentials" :weight="-8">
|
||||||
<AccessCredentials v-model:value="accessCredentials" :mode="mode" :resource="value" :is-qemu-installed="isQemuInstalled" />
|
<AccessCredentials v-model:value="accessCredentials" :mode="mode" :resource="value" :is-qemu-installed="isQemuInstalled" />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
||||||
|
|||||||
@ -241,6 +241,7 @@ harvester:
|
|||||||
accessCredentials: Access Credentials
|
accessCredentials: Access Credentials
|
||||||
pciDevices: PCI Devices
|
pciDevices: PCI Devices
|
||||||
vGpuDevices: vGPU Devices
|
vGpuDevices: vGPU Devices
|
||||||
|
usbDevices: USB Devices
|
||||||
vmScheduling: Virtual Machine Scheduling
|
vmScheduling: Virtual Machine Scheduling
|
||||||
quotas: Quotas
|
quotas: Quotas
|
||||||
snapshots: Snapshots
|
snapshots: Snapshots
|
||||||
@ -1221,6 +1222,9 @@ harvester:
|
|||||||
location: Driver Location
|
location: Driver Location
|
||||||
parsingSpecError:
|
parsingSpecError:
|
||||||
The field 'spec.valuesContent' has invalid format.
|
The field 'spec.valuesContent' has invalid format.
|
||||||
|
usbController:
|
||||||
|
titles:
|
||||||
|
basic: Basic
|
||||||
|
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
label: Load Balancers
|
label: Load Balancers
|
||||||
@ -1360,6 +1364,14 @@ harvester:
|
|||||||
howToUseDevice: 'Use the table below to enable vGPU devices you want to use in this virtual machine.'
|
howToUseDevice: 'Use the table below to enable vGPU devices you want to use in this virtual machine.'
|
||||||
deviceInTheSameHost: 'You can only select devices on the same host.'
|
deviceInTheSameHost: 'You can only select devices on the same host.'
|
||||||
|
|
||||||
|
usb:
|
||||||
|
label: USB Devices
|
||||||
|
noPermission: Please contact system admin to add Harvester addons first
|
||||||
|
goSetting:
|
||||||
|
prefix: The usb addon is not enabled, click
|
||||||
|
middle: here
|
||||||
|
suffix: to enable it to manage your USB devices.
|
||||||
|
|
||||||
harvesterVlanConfigMigrateDialog:
|
harvesterVlanConfigMigrateDialog:
|
||||||
targetClusterNetwork:
|
targetClusterNetwork:
|
||||||
label: Target Cluster Network
|
label: Target Cluster Network
|
||||||
|
|||||||
97
pkg/harvester/list/devices.harvesterhci.io.usbdevice.vue
Normal file
97
pkg/harvester/list/devices.harvesterhci.io.usbdevice.vue
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<script>
|
||||||
|
import { HCI } from '../types';
|
||||||
|
import { STATE, SIMPLE_NAME } from '@shell/config/table-headers';
|
||||||
|
import { allHash } from '@shell/utils/promise';
|
||||||
|
import Banner from '@components/Banner/Banner.vue';
|
||||||
|
import Loading from '@shell/components/Loading';
|
||||||
|
import MessageLink from '@shell/components/MessageLink';
|
||||||
|
import ResourceTable from '@shell/components/ResourceTable';
|
||||||
|
import { ADD_ONS } from '../config/harvester-map';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ListUSBDevices',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Banner,
|
||||||
|
Loading,
|
||||||
|
MessageLink,
|
||||||
|
ResourceTable
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetch() {
|
||||||
|
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||||
|
|
||||||
|
this.schema = this.$store.getters[`${ inStore }/schemaFor`](HCI.USB_DEVICE);
|
||||||
|
this.hasAddonSchema = this.$store.getters[`${ inStore }/schemaFor`](HCI.ADD_ONS);
|
||||||
|
|
||||||
|
if (this.hasSchema) {
|
||||||
|
try {
|
||||||
|
const hash = await allHash({
|
||||||
|
usbDevices: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.USB_DEVICE }),
|
||||||
|
addons: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.ADD_ONS }),
|
||||||
|
});
|
||||||
|
|
||||||
|
this.hasUSBAddon = hash.addons.find(addon => addon.name === ADD_ONS.USB_DEVICE_CONTROLLER)?.spec?.enabled === true;
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hasAddonSchema: false,
|
||||||
|
hasUSBAddon: false,
|
||||||
|
schema: null,
|
||||||
|
toUSBAddon: `${ HCI.ADD_ONS }/harvester-system/${ ADD_ONS.USB_DEVICE_CONTROLLER }?mode=edit`,
|
||||||
|
headers: [
|
||||||
|
{ ...STATE },
|
||||||
|
SIMPLE_NAME,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasSchema() {
|
||||||
|
return !!this.schema;
|
||||||
|
},
|
||||||
|
|
||||||
|
rows() {
|
||||||
|
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||||
|
|
||||||
|
return this.$store.getters[`${ inStore }/all`](HCI.USB_DEVICE) || [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
typeDisplay() {
|
||||||
|
return this.t('harvester.usb.label');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Loading v-if="$fetchState.pending" />
|
||||||
|
<div v-else-if="!hasAddonSchema">
|
||||||
|
<Banner color="warning">
|
||||||
|
{{ t('harvester.usb.noPermission') }}
|
||||||
|
</Banner>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="!hasUSBAddon">
|
||||||
|
<Banner color="warning">
|
||||||
|
<MessageLink
|
||||||
|
:to="toUSBAddon"
|
||||||
|
prefix-label="harvester.usb.goSetting.prefix"
|
||||||
|
middle-label="harvester.usb.goSetting.middle"
|
||||||
|
suffix-label="harvester.usb.goSetting.suffix"
|
||||||
|
/>
|
||||||
|
</Banner>
|
||||||
|
</div>
|
||||||
|
<ResourceTable
|
||||||
|
v-else-if="hasSchema"
|
||||||
|
:headers="headers"
|
||||||
|
:schema="schema"
|
||||||
|
:rows="rows"
|
||||||
|
:use-query-params-for-simple-filtering="true"
|
||||||
|
:sort-generation-fn="sortGenerationFn"
|
||||||
|
:rows-per-page="10"
|
||||||
|
@submit.prevent
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@ -119,12 +119,13 @@ export default {
|
|||||||
|
|
||||||
const hasPCISchema = !!this.$store.getters[`${ inStore }/schemaFor`](HCI.PCI_DEVICE);
|
const hasPCISchema = !!this.$store.getters[`${ inStore }/schemaFor`](HCI.PCI_DEVICE);
|
||||||
const hasSRIOVGPUSchema = !!this.$store.getters[`${ inStore }/schemaFor`](HCI.SR_IOVGPU_DEVICE);
|
const hasSRIOVGPUSchema = !!this.$store.getters[`${ inStore }/schemaFor`](HCI.SR_IOVGPU_DEVICE);
|
||||||
|
const hasUSBSchema = !!this.$store.getters[`${ inStore }/schemaFor`](HCI.USB_DEVICE);
|
||||||
|
|
||||||
const hasPCIAddon = res.addons.find(addon => addon.name === ADD_ONS.PCI_DEVICE_CONTROLLER)?.spec?.enabled === true;
|
const enabledAddons = res.addons.reduce((acc, addon) => ({ ...acc, [addon.name]: addon.spec?.enabled }), {});
|
||||||
const hasSriovgpuAddon = res.addons.find(addon => addon.name === ADD_ONS.NVIDIA_DRIVER_TOOLKIT_CONTROLLER)?.spec?.enabled === true;
|
|
||||||
|
|
||||||
this.enabledPCI = hasPCIAddon && hasPCISchema;
|
this.enabledPCI = hasPCISchema && enabledAddons[ADD_ONS.PCI_DEVICE_CONTROLLER];
|
||||||
this.enabledSriovgpu = hasSriovgpuAddon && hasPCIAddon && hasSRIOVGPUSchema;
|
this.enabledSriovgpu = hasSRIOVGPUSchema && enabledAddons[ADD_ONS.PCI_DEVICE_CONTROLLER] && enabledAddons[ADD_ONS.NVIDIA_DRIVER_TOOLKIT_CONTROLLER];
|
||||||
|
this.enabledUSB = hasUSBSchema && enabledAddons[ADD_ONS.USB_DEVICE_CONTROLLER];
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
@ -165,6 +166,7 @@ export default {
|
|||||||
saveNetworkDataAsClearText: false,
|
saveNetworkDataAsClearText: false,
|
||||||
enabledPCI: false,
|
enabledPCI: false,
|
||||||
enabledSriovgpu: false,
|
enabledSriovgpu: false,
|
||||||
|
enabledUSB: false,
|
||||||
immutableMode: this.realMode === _CREATE ? _CREATE : _VIEW,
|
immutableMode: this.realMode === _CREATE ? _CREATE : _VIEW,
|
||||||
terminationGracePeriodSeconds: '',
|
terminationGracePeriodSeconds: '',
|
||||||
cpuPinning: false,
|
cpuPinning: false,
|
||||||
|
|||||||
@ -38,6 +38,7 @@ export const HCI = {
|
|||||||
SR_IOV: 'devices.harvesterhci.io.sriovnetworkdevice',
|
SR_IOV: 'devices.harvesterhci.io.sriovnetworkdevice',
|
||||||
VGPU_DEVICE: 'devices.harvesterhci.io.vgpudevice',
|
VGPU_DEVICE: 'devices.harvesterhci.io.vgpudevice',
|
||||||
SR_IOVGPU_DEVICE: 'devices.harvesterhci.io.sriovgpudevice',
|
SR_IOVGPU_DEVICE: 'devices.harvesterhci.io.sriovgpudevice',
|
||||||
|
USB_DEVICE: 'devices.harvesterhci.io.usbdevice',
|
||||||
VLAN_CONFIG: 'network.harvesterhci.io.vlanconfig',
|
VLAN_CONFIG: 'network.harvesterhci.io.vlanconfig',
|
||||||
VLAN_STATUS: 'network.harvesterhci.io.vlanstatus',
|
VLAN_STATUS: 'network.harvesterhci.io.vlanstatus',
|
||||||
ADD_ONS: 'harvesterhci.io.addon',
|
ADD_ONS: 'harvesterhci.io.addon',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user