mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-03 12:46:06 +08:00
Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8111f0ad7 | ||
|
|
6d627f82e9 | ||
|
|
cfc7a76fe7 | ||
|
|
71d3067354 | ||
|
|
9ecc372009 | ||
|
|
62b80b3cec | ||
|
|
1cf94ee550 | ||
|
|
dfaa9fbe33 | ||
|
|
94b1c24479 | ||
|
|
e0b2b9ec57 | ||
|
|
06b38a0f99 | ||
|
|
4be3634c82 | ||
|
|
de103ff91e | ||
|
|
37a91601c9 | ||
|
|
9794671ccd | ||
|
|
337f9186f1 | ||
|
|
7c187e894d | ||
|
|
c2df13ad73 | ||
|
|
93f027a57c | ||
|
|
da83f04b6c | ||
|
|
a97cb08e3f | ||
|
|
3fdc9f03a3 | ||
|
|
c8a613874a | ||
|
|
2db7ee7397 |
@@ -15,7 +15,7 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
# The FOSSA token is shared between all repos in Harvester's GH org. It can
|
||||
# be used directly and there is no need to request specific access to EIO.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
workflow_call: # This tells GH that the workflow is reusable
|
||||
workflow_call: # This tells GH that the workflow is reusable
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
+11
-5
@@ -1,17 +1,22 @@
|
||||
{
|
||||
"name": "harvester-ui-extension",
|
||||
"version": "1.8.0-dev",
|
||||
"version": "1.8.0-rc1",
|
||||
"private": false,
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-class-static-block": "7.28.6",
|
||||
"@rancher/shell": "3.0.9-rc.1",
|
||||
"@rancher/shell": "3.0.9-rc.6",
|
||||
"@vue-flow/background": "^1.3.0",
|
||||
"@vue-flow/controls": "^1.1.1",
|
||||
"@vue-flow/core": "^1.33.5",
|
||||
"@vue-flow/minimap": "^1.4.0",
|
||||
"cache-loader": "^4.1.0",
|
||||
"color": "4.2.3",
|
||||
"ip": "2.0.1",
|
||||
"node-polyfill-webpack-plugin": "^3.0.0",
|
||||
"elkjs": "^0.11.0",
|
||||
"vue-draggable-next": "^2.2.1",
|
||||
"yaml": "^2.5.1"
|
||||
},
|
||||
@@ -24,13 +29,13 @@
|
||||
"glob": "7.2.3",
|
||||
"glob-parent": "6.0.2",
|
||||
"json5": "2.2.3",
|
||||
"@types/lodash": "4.17.23",
|
||||
"@types/lodash": "4.17.24",
|
||||
"merge": "2.1.1",
|
||||
"node-forge": "1.3.3",
|
||||
"nth-check": "2.1.1",
|
||||
"qs": "6.14.1",
|
||||
"qs": "6.15.0",
|
||||
"roarr": "7.21.4",
|
||||
"semver": "7.7.3",
|
||||
"semver": "7.7.4",
|
||||
"@vue/cli-service/html-webpack-plugin": "^5.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -38,6 +43,7 @@
|
||||
"build": "./node_modules/.bin/vue-cli-service build",
|
||||
"clean": "./node_modules/@rancher/shell/scripts/clean",
|
||||
"lint": "./node_modules/.bin/eslint --max-warnings 0 --ext .js,.ts,.vue .",
|
||||
"lint:fix": "./node_modules/.bin/eslint --fix --max-warnings 0 --ext .js,.ts,.vue .",
|
||||
"build-pkg": "./node_modules/@rancher/shell/scripts/build-pkg.sh",
|
||||
"serve-pkgs": "./node_modules/@rancher/shell/scripts/serve-pkgs",
|
||||
"publish-pkgs": "./node_modules/@rancher/shell/scripts/extension/publish",
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
<script>
|
||||
import MessageLink from '@shell/components/MessageLink';
|
||||
import CreateEditView from '@shell/mixins/create-edit-view';
|
||||
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||
import { HCI_SETTING } from '../../config/settings';
|
||||
import { Checkbox } from '@components/Form/Checkbox';
|
||||
import { Banner } from '@components/Banner';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterEditClusterRegistrationURL',
|
||||
|
||||
components: {
|
||||
LabeledInput, MessageLink, Checkbox, Banner
|
||||
},
|
||||
|
||||
mixins: [CreateEditView],
|
||||
|
||||
data() {
|
||||
let parseDefaultValue = {};
|
||||
|
||||
try {
|
||||
parseDefaultValue = JSON.parse(this.value.value);
|
||||
} catch (error) {
|
||||
parseDefaultValue.url = this.value.value;
|
||||
parseDefaultValue.insecureSkipTLSVerify = true;
|
||||
}
|
||||
|
||||
return {
|
||||
parseDefaultValue,
|
||||
errors: []
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
toCA() {
|
||||
return `${ HCI_SETTING.ADDITIONAL_CA }?mode=edit`;
|
||||
},
|
||||
clusterRegistrationTLSVerifyEnabled() {
|
||||
return this.$store.getters['harvester-common/getFeatureEnabled']('clusterRegistrationTLSVerify');
|
||||
},
|
||||
registrationURL: {
|
||||
get() {
|
||||
return this.clusterRegistrationTLSVerifyEnabled ? this.parseDefaultValue.url : this.parseDefaultValue;
|
||||
},
|
||||
|
||||
set(value) {
|
||||
if (this.clusterRegistrationTLSVerifyEnabled) {
|
||||
this.parseDefaultValue.url = value;
|
||||
} else {
|
||||
this.parseDefaultValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getDefaultValue() {
|
||||
if (this.clusterRegistrationTLSVerifyEnabled) {
|
||||
return { url: '', insecureSkipTLSVerify: false };
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
updateUrl() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
update() {
|
||||
if (this.clusterRegistrationTLSVerifyEnabled) {
|
||||
this.value['value'] = JSON.stringify(this.parseDefaultValue);
|
||||
} else {
|
||||
this.value['value'] = this.parseDefaultValue;
|
||||
}
|
||||
},
|
||||
|
||||
useDefault() {
|
||||
this.parseDefaultValue = this.getDefaultValue();
|
||||
},
|
||||
|
||||
updateInsecureSkipTLSVerify(newValue) {
|
||||
const { url = '' } = this.parseDefaultValue;
|
||||
|
||||
this.parseDefaultValue = { url, insecureSkipTLSVerify: newValue };
|
||||
this.update();
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="row"
|
||||
>
|
||||
<div class="col span-12">
|
||||
<Banner color="info">
|
||||
<MessageLink
|
||||
:to="toCA"
|
||||
target="_blank"
|
||||
prefix-label="harvester.setting.clusterRegistrationUrl.tip.prefix"
|
||||
middle-label="harvester.setting.clusterRegistrationUrl.tip.middle"
|
||||
suffix-label="harvester.setting.clusterRegistrationUrl.tip.suffix"
|
||||
/>
|
||||
</Banner>
|
||||
<LabeledInput
|
||||
v-model:value="registrationURL"
|
||||
class="mb-20"
|
||||
:mode="mode"
|
||||
:label="t('harvester.setting.clusterRegistrationUrl.url')"
|
||||
@update:value="updateUrl"
|
||||
/>
|
||||
<div v-if="clusterRegistrationTLSVerifyEnabled">
|
||||
<Checkbox
|
||||
v-model:value="parseDefaultValue.insecureSkipTLSVerify"
|
||||
class="check mb-5"
|
||||
type="checkbox"
|
||||
:label="t('harvester.setting.clusterRegistrationUrl.insecureSkipTLSVerify')"
|
||||
@update:value="updateInsecureSkipTLSVerify"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -69,6 +69,15 @@ export default {
|
||||
:mode="mode"
|
||||
label-key="harvester.setting.vmForceDeletionPolicy.period"
|
||||
/>
|
||||
|
||||
<LabeledInput
|
||||
v-if="parseDefaultValue.enable"
|
||||
v-model:value.number="parseDefaultValue.vmMigrationTimeout"
|
||||
class="mb-20"
|
||||
type="number"
|
||||
:mode="mode"
|
||||
label-key="harvester.setting.vmForceDeletionPolicy.vmMigrationTimeout"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -58,7 +58,12 @@ const FEATURE_FLAGS = {
|
||||
'resumeUpgradePausedNode',
|
||||
],
|
||||
'v1.7.1': [],
|
||||
'v1.8.0': []
|
||||
'v1.8.0': [
|
||||
'hotplugCdRom',
|
||||
'supportBundleFileNameSetting',
|
||||
'clusterRegistrationTLSVerify',
|
||||
'vGPUAsPCIDevice',
|
||||
],
|
||||
};
|
||||
|
||||
const generateFeatureFlags = () => {
|
||||
|
||||
@@ -39,6 +39,12 @@ export const VOLUME_TYPE = [{
|
||||
value: 'cd-rom'
|
||||
}];
|
||||
|
||||
export const VOLUME_HOTPLUG_ACTION = {
|
||||
INSERT_CDROM_IMAGE: 'INSERT_CDROM_IMAGE',
|
||||
EJECT_CDROM_IMAGE: 'EJECT_CDROM_IMAGE',
|
||||
DETACH_DISK: 'DETACH_DISK'
|
||||
};
|
||||
|
||||
export const ACCESS_CREDENTIALS = {
|
||||
RESET_PWD: 'userPassword',
|
||||
INJECT_SSH: 'sshPublicKey'
|
||||
|
||||
@@ -28,6 +28,7 @@ export const HCI = {
|
||||
NODE_ROLE_CONTROL_PLANE: 'node-role.kubernetes.io/control-plane',
|
||||
NODE_ROLE_ETCD: 'node-role.harvesterhci.io/witness',
|
||||
PROMOTE_STATUS: 'harvesterhci.io/promote-status',
|
||||
CLONE_BACKEND_STORAGE_STATUS: 'harvesterhci.io/clone-backend-storage-status',
|
||||
MIGRATION_STATE: 'harvesterhci.io/migrationState',
|
||||
VOLUME_CLAIM_TEMPLATE: 'harvesterhci.io/volumeClaimTemplates',
|
||||
IMAGE_NAME: 'harvesterhci.io/image-name',
|
||||
|
||||
@@ -16,6 +16,7 @@ export const HCI_SETTING = {
|
||||
DEFAULT_STORAGE_CLASS: 'default-storage-class',
|
||||
SUPPORT_BUNDLE_TIMEOUT: 'support-bundle-timeout',
|
||||
SUPPORT_BUNDLE_EXPIRATION: 'support-bundle-expiration',
|
||||
SUPPORT_BUNDLE_FILE_NAME: 'support-bundle-file-name',
|
||||
SUPPORT_BUNDLE_IMAGE: 'support-bundle-image',
|
||||
SUPPORT_BUNDLE_NODE_COLLECTION_TIMEOUT: 'support-bundle-node-collection-timeout',
|
||||
STORAGE_NETWORK: 'storage-network',
|
||||
@@ -71,6 +72,9 @@ export const HCI_ALLOWED_SETTINGS = {
|
||||
[HCI_SETTING.OVERCOMMIT_CONFIG]: { kind: 'json', from: 'import' },
|
||||
[HCI_SETTING.SUPPORT_BUNDLE_TIMEOUT]: { kind: 'number' },
|
||||
[HCI_SETTING.SUPPORT_BUNDLE_EXPIRATION]: { kind: 'number' },
|
||||
[HCI_SETTING.SUPPORT_BUNDLE_FILE_NAME]: {
|
||||
kind: 'string', canReset: true, featureFlag: 'supportBundleFileNameSetting'
|
||||
},
|
||||
[HCI_SETTING.SUPPORT_BUNDLE_NODE_COLLECTION_TIMEOUT]: { kind: 'number', featureFlag: 'supportBundleNodeCollectionTimeoutSetting' },
|
||||
[HCI_SETTING.SUPPORT_BUNDLE_IMAGE]: { kind: 'json', from: 'import' },
|
||||
[HCI_SETTING.STORAGE_NETWORK]: {
|
||||
@@ -123,7 +127,8 @@ export const HCI_ALLOWED_SETTINGS = {
|
||||
|
||||
export const HCI_SINGLE_CLUSTER_ALLOWED_SETTING = {
|
||||
[HCI_SETTING.CLUSTER_REGISTRATION_URL]: {
|
||||
kind: 'url',
|
||||
kind: 'custom',
|
||||
from: 'import',
|
||||
canReset: true,
|
||||
},
|
||||
[HCI_SETTING.UI_PL]: {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,10 @@ import { Card } from '@components/Card';
|
||||
import { Banner } from '@components/Banner';
|
||||
import AsyncButton from '@shell/components/AsyncButton';
|
||||
|
||||
const VOLUME = 'volume';
|
||||
const NETWORK = 'network';
|
||||
const CDROM = 'cdrom';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterHotUnplug',
|
||||
|
||||
@@ -40,19 +44,37 @@ export default {
|
||||
},
|
||||
|
||||
isVolume() {
|
||||
return this.modalData.type === 'volume';
|
||||
return this.modalData.type === VOLUME;
|
||||
},
|
||||
|
||||
titleKey() {
|
||||
return this.isVolume ? 'harvester.virtualMachine.hotUnplug.detachVolume.title' : 'harvester.virtualMachine.hotUnplug.detachNIC.title';
|
||||
const keys = {
|
||||
[VOLUME]: 'harvester.virtualMachine.hotUnplug.detachVolume.title',
|
||||
[CDROM]: 'harvester.virtualMachine.hotUnplug.ejectCdRomVolume.title',
|
||||
[NETWORK]: 'harvester.virtualMachine.hotUnplug.detachNIC.title',
|
||||
};
|
||||
|
||||
return keys[this.modalData.type];
|
||||
},
|
||||
|
||||
actionLabelKey() {
|
||||
return this.isVolume ? 'harvester.virtualMachine.hotUnplug.detachVolume.actionLabel' : 'harvester.virtualMachine.hotUnplug.detachNIC.actionLabel';
|
||||
const keys = {
|
||||
[VOLUME]: 'harvester.virtualMachine.hotUnplug.detachVolume.actionLabels',
|
||||
[CDROM]: 'harvester.virtualMachine.hotUnplug.ejectCdRomVolume.actionLabels',
|
||||
[NETWORK]: 'harvester.virtualMachine.hotUnplug.detachNIC.actionLabels',
|
||||
};
|
||||
|
||||
return keys[this.modalData.type];
|
||||
},
|
||||
|
||||
successMessageKey() {
|
||||
return this.isVolume ? 'harvester.virtualMachine.hotUnplug.detachVolume.success' : 'harvester.virtualMachine.hotUnplug.detachNIC.success';
|
||||
const keys = {
|
||||
[VOLUME]: 'harvester.virtualMachine.hotUnplug.detachVolume.success',
|
||||
[CDROM]: 'harvester.virtualMachine.hotUnplug.ejectCdRomVolume.success',
|
||||
[NETWORK]: 'harvester.virtualMachine.hotUnplug.detachNIC.success',
|
||||
};
|
||||
|
||||
return keys[this.modalData.type];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -65,10 +87,12 @@ export default {
|
||||
try {
|
||||
let res;
|
||||
|
||||
if (this.isVolume) {
|
||||
if (this.modalData.type === VOLUME) {
|
||||
res = await this.actionResource.doAction('removeVolume', { diskName: this.name });
|
||||
} else {
|
||||
} else if (this.modalData.type === NETWORK) {
|
||||
res = await this.actionResource.doAction('removeNic', { interfaceName: this.name });
|
||||
} else {
|
||||
res = await this.actionResource.doAction('ejectCdRomVolume', { deviceName: this.name });
|
||||
}
|
||||
|
||||
if (res._status === 200 || res._status === 204) {
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
<script>
|
||||
import { exceptionToErrorsArray } from '@shell/utils/error';
|
||||
import { mapState, mapGetters } from 'vuex';
|
||||
import { Card } from '@components/Card';
|
||||
import { Banner } from '@components/Banner';
|
||||
import AsyncButton from '@shell/components/AsyncButton';
|
||||
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations';
|
||||
import { HCI } from '../types';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterInsertCdRomVolume',
|
||||
|
||||
emits: ['close'],
|
||||
|
||||
components: {
|
||||
AsyncButton,
|
||||
Card,
|
||||
LabeledInput,
|
||||
LabeledSelect,
|
||||
Banner
|
||||
},
|
||||
|
||||
props: {
|
||||
resources: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
try {
|
||||
this.images = await this.$store.dispatch('harvester/findAll', { type: HCI.IMAGE });
|
||||
} catch (err) {
|
||||
this.errors = exceptionToErrorsArray(err);
|
||||
this.images = [];
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
imageName: '',
|
||||
images: [],
|
||||
errors: [],
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState('action-menu', ['modalData']),
|
||||
...mapGetters({ t: 'i18n/t' }),
|
||||
|
||||
actionResource() {
|
||||
return this.resources?.[0];
|
||||
},
|
||||
|
||||
isFormValid() {
|
||||
return this.imageName !== '';
|
||||
},
|
||||
|
||||
deviceName() {
|
||||
return this.modalData.name;
|
||||
},
|
||||
|
||||
imagesOption() {
|
||||
return this.images
|
||||
.filter((image) => {
|
||||
const labels = image.metadata?.labels || {};
|
||||
const type = labels[HCI_ANNOTATIONS.IMAGE_SUFFIX];
|
||||
|
||||
return type === 'iso';
|
||||
})
|
||||
.map((image) => {
|
||||
return ({
|
||||
label: this.imageOptionLabel(image),
|
||||
value: image.id,
|
||||
disabled: image.isImportedImage
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.imageName = '';
|
||||
this.errors = [];
|
||||
this.$emit('close');
|
||||
},
|
||||
|
||||
imageOptionLabel(image) {
|
||||
return `${ image.metadata.namespace }/${ image.spec.displayName }`;
|
||||
},
|
||||
|
||||
async save(buttonCb) {
|
||||
if (!this.actionResource) {
|
||||
buttonCb(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
deviceName: this.deviceName,
|
||||
imageName: this.imageName
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await this.actionResource.doAction('insertCdRomVolume', payload);
|
||||
|
||||
if ([200, 204].includes(res?._status)) {
|
||||
this.$store.dispatch('growl/success', {
|
||||
title: this.t('generic.notification.title.succeed'),
|
||||
message: this.t('harvester.modal.insertCdRomVolume.success', {
|
||||
deviceName: this.deviceName,
|
||||
imageName: this.imageName,
|
||||
})
|
||||
}, { root: true });
|
||||
|
||||
this.close();
|
||||
buttonCb(true);
|
||||
} else {
|
||||
this.errors = exceptionToErrorsArray(res);
|
||||
buttonCb(false);
|
||||
}
|
||||
} catch (err) {
|
||||
this.errors = exceptionToErrorsArray(err);
|
||||
buttonCb(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card
|
||||
ref="modal"
|
||||
name="modal"
|
||||
:show-highlight-border="false"
|
||||
>
|
||||
<template #title>
|
||||
<h4
|
||||
v-clean-html="t('harvester.modal.insertCdRomVolume.title')"
|
||||
class="text-default-text"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<LabeledInput
|
||||
v-model:value="deviceName"
|
||||
:label="t('generic.name')"
|
||||
disabled
|
||||
/>
|
||||
<LabeledSelect
|
||||
v-model:value="imageName"
|
||||
class="mt-20"
|
||||
:label="t('harvester.modal.insertCdRomVolume.image')"
|
||||
:options="imagesOption"
|
||||
required
|
||||
/>
|
||||
<Banner
|
||||
v-for="(err, i) in errors"
|
||||
:key="i"
|
||||
:label="err"
|
||||
color="error"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #actions>
|
||||
<div class="actions">
|
||||
<div class="buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="btn role-secondary mr-10"
|
||||
@click="close"
|
||||
>
|
||||
{{ t('generic.cancel') }}
|
||||
</button>
|
||||
|
||||
<AsyncButton
|
||||
mode="apply"
|
||||
:disabled="!isFormValid"
|
||||
@click="save"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.actions {
|
||||
width: 100%;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,7 @@ import { Checkbox } from '@components/Form/Checkbox';
|
||||
import CruResource from '@shell/components/CruResource';
|
||||
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { set } from '@shell/utils/object';
|
||||
import { Banner } from '@components/Banner';
|
||||
import KeyValue from '@shell/components/form/KeyValue';
|
||||
import NodeScheduling from '@shell/components/form/NodeScheduling';
|
||||
@@ -22,6 +23,7 @@ import Reserved from './kubevirt.io.virtualmachine/VirtualMachineReserved';
|
||||
import Volume from './kubevirt.io.virtualmachine/VirtualMachineVolume';
|
||||
import Network from './kubevirt.io.virtualmachine/VirtualMachineNetwork';
|
||||
import CpuMemory from './kubevirt.io.virtualmachine/VirtualMachineCpuMemory';
|
||||
import CpuModel from './kubevirt.io.virtualmachine/VirtualMachineCpuModel';
|
||||
import CloudConfig from './kubevirt.io.virtualmachine/VirtualMachineCloudConfig';
|
||||
import SSHKey from './kubevirt.io.virtualmachine/VirtualMachineSSHKey';
|
||||
|
||||
@@ -38,6 +40,7 @@ export default {
|
||||
Network,
|
||||
Checkbox,
|
||||
CpuMemory,
|
||||
CpuModel,
|
||||
CruResource,
|
||||
CloudConfig,
|
||||
LabeledSelect,
|
||||
@@ -70,12 +73,12 @@ export default {
|
||||
|
||||
return {
|
||||
templateId,
|
||||
templateValue: null,
|
||||
templateSpec: null,
|
||||
versionName: '',
|
||||
description: '',
|
||||
defaultVersion: null,
|
||||
isDefaultVersion: false,
|
||||
templateValue: null,
|
||||
templateSpec: null,
|
||||
versionName: '',
|
||||
description: '',
|
||||
defaultVersion: null,
|
||||
isDefaultVersion: false,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -154,6 +157,18 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateCpuModel(value) {
|
||||
if (!this.spec?.template?.spec?.domain?.cpu) {
|
||||
set(this.spec, 'template.spec.domain.cpu', {});
|
||||
}
|
||||
|
||||
if (value && value !== '') {
|
||||
set(this.spec.template.spec.domain.cpu, 'model', value);
|
||||
} else {
|
||||
delete this.spec.template.spec.domain.cpu.model;
|
||||
}
|
||||
},
|
||||
|
||||
async saveVMT(buttonCb) {
|
||||
this.parseVM();
|
||||
|
||||
@@ -436,6 +451,17 @@ export default {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-20">
|
||||
<div class="col span-6">
|
||||
<CpuModel
|
||||
:value="spec.template.spec.domain.cpu?.model || ''"
|
||||
:mode="mode"
|
||||
@update:value="updateCpuModel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-20">
|
||||
<a
|
||||
v-if="showAdvanced"
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<script>
|
||||
import YAML from 'yaml';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { CONFIG_MAP } from '@shell/config/types';
|
||||
import { Banner } from '@components/Banner';
|
||||
|
||||
const CPU_MODEL_CONFIG_MAP_ID = 'harvester-system/node-cpu-model-configuration';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterCpuModel',
|
||||
|
||||
emits: ['update:value'],
|
||||
|
||||
components: {
|
||||
LabeledSelect,
|
||||
Banner
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'create',
|
||||
},
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
try {
|
||||
await this.$store.dispatch(`${ inStore }/find`, { type: CONFIG_MAP, id: CPU_MODEL_CONFIG_MAP_ID });
|
||||
this.fetchError = null;
|
||||
} catch (e) {
|
||||
this.fetchError = this.t('harvester.virtualMachine.cpuModel.fetchError', { error: e.message || e });
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return { fetchError: null };
|
||||
},
|
||||
|
||||
computed: {
|
||||
localValue: {
|
||||
get() {
|
||||
return this.value ?? '';
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:value', val ?? '');
|
||||
}
|
||||
},
|
||||
|
||||
cpuModelConfigMap() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
return this.$store.getters[`${ inStore }/byId`](
|
||||
CONFIG_MAP,
|
||||
CPU_MODEL_CONFIG_MAP_ID
|
||||
);
|
||||
},
|
||||
|
||||
cpuModelOptions() {
|
||||
if (!this.cpuModelConfigMap?.data?.cpuModels) {
|
||||
return [{ label: this.t('generic.default'), value: '' }];
|
||||
}
|
||||
|
||||
let cpuModelsData;
|
||||
|
||||
try {
|
||||
cpuModelsData = YAML.parse(this.cpuModelConfigMap.data?.cpuModels || '');
|
||||
} catch (e) {
|
||||
return [{ label: this.t('generic.default'), value: '' }];
|
||||
}
|
||||
|
||||
const options = [];
|
||||
|
||||
options.push({
|
||||
label: this.t('generic.default'),
|
||||
value: ''
|
||||
});
|
||||
|
||||
// Add global models (host-model, host-passthrough)
|
||||
const globalModels = cpuModelsData.globalModels || [];
|
||||
|
||||
globalModels.forEach((modelName) => {
|
||||
options.push({
|
||||
label: modelName,
|
||||
value: modelName
|
||||
});
|
||||
});
|
||||
|
||||
// Add regular models with node count
|
||||
const modelEntries = Object.entries(cpuModelsData.models || {});
|
||||
|
||||
// Sort models alphabetically for consistent display
|
||||
modelEntries.sort((a, b) => a[0].localeCompare(b[0]));
|
||||
|
||||
modelEntries.forEach(([modelName, modelInfo]) => {
|
||||
const readyCount = modelInfo.readyCount || 0;
|
||||
const label = this.t('harvester.virtualMachine.cpuModel.optionLabel', { modelName, count: readyCount });
|
||||
|
||||
options.push({
|
||||
label,
|
||||
value: modelName
|
||||
});
|
||||
});
|
||||
|
||||
return options;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Banner
|
||||
v-if="fetchError"
|
||||
color="error"
|
||||
class="mb-20"
|
||||
>
|
||||
{{ fetchError }}
|
||||
</Banner>
|
||||
<LabeledSelect
|
||||
v-model:value="localValue"
|
||||
:label="t('harvester.virtualMachine.cpuModel.label')"
|
||||
:options="cpuModelOptions"
|
||||
:mode="mode"
|
||||
:disabled="!!fetchError"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
+30
-7
@@ -31,6 +31,7 @@ export default {
|
||||
const _hash = {
|
||||
pciclaims: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.PCI_CLAIM }),
|
||||
sriovs: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.SR_IOV }),
|
||||
srigpuovs: this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.SR_IOVGPU_DEVICE }),
|
||||
};
|
||||
|
||||
await allHash(_hash);
|
||||
@@ -106,19 +107,32 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
parentSriovOptions() {
|
||||
allSriovs() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
const allSriovs = this.$store.getters[`${ inStore }/all`](HCI.SR_IOV) || [];
|
||||
|
||||
return allSriovs.map((sriov) => {
|
||||
return sriov.id;
|
||||
});
|
||||
return this.$store.getters[`${ inStore }/all`](HCI.SR_IOV) || [];
|
||||
},
|
||||
allSriovGPUs() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
return this.$store.getters[`${ inStore }/all`](HCI.SR_IOVGPU_DEVICE) || [];
|
||||
},
|
||||
parentSriovOptions() {
|
||||
return this.allSriovs.map((sriov) => sriov.id);
|
||||
},
|
||||
parentSriovGPUOptions() {
|
||||
return this.allSriovGPUs.map((sriovgpu) => sriovgpu.id);
|
||||
},
|
||||
parentSriovLabel() {
|
||||
return HCI_ANNOTATIONS.PARENT_SRIOV;
|
||||
}
|
||||
},
|
||||
parentSriovGPULabel() {
|
||||
return HCI_ANNOTATIONS.PARENT_SRIOV_GPU;
|
||||
},
|
||||
vGPUAsPCIDeviceEnabled() {
|
||||
return this.$store.getters['harvester-common/getFeatureEnabled']('vGPUAsPCIDevice');
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
enableGroup(rows = []) {
|
||||
const row = rows[0];
|
||||
@@ -206,6 +220,15 @@ export default {
|
||||
:rows="rows"
|
||||
@change-rows="changeRows"
|
||||
/>
|
||||
<FilterBySriov
|
||||
v-if="vGPUAsPCIDeviceEnabled"
|
||||
ref="filterByParentSRIOVGPU"
|
||||
:parent-sriov-options="parentSriovGPUOptions"
|
||||
:parent-sriov-label="parentSriovGPULabel"
|
||||
:label="t('harvester.sriov.parentSriovGPU')"
|
||||
:rows="rows"
|
||||
@change-rows="changeRows"
|
||||
/>
|
||||
</template>
|
||||
</ResourceTable>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { set } from '@shell/utils/object';
|
||||
import { HCI } from '../../../types';
|
||||
import DeviceList from './DeviceList';
|
||||
import CompatibilityMatrix from '../CompatibilityMatrix';
|
||||
import MessageLink from '@shell/components/MessageLink';
|
||||
|
||||
export default {
|
||||
name: 'VirtualMachinePCIDevices',
|
||||
@@ -15,7 +16,8 @@ export default {
|
||||
LabeledSelect,
|
||||
DeviceList,
|
||||
CompatibilityMatrix,
|
||||
Banner
|
||||
Banner,
|
||||
MessageLink
|
||||
},
|
||||
props: {
|
||||
mode: {
|
||||
@@ -138,6 +140,13 @@ export default {
|
||||
return inUse;
|
||||
},
|
||||
|
||||
toVGpuDevicesPage() {
|
||||
return {
|
||||
name: 'harvester-c-cluster-resource',
|
||||
params: { cluster: this.$store.getters['clusterId'], resource: HCI.VGPU_DEVICE },
|
||||
};
|
||||
},
|
||||
|
||||
devicesByNode() {
|
||||
return this.enabledDevices?.reduce((acc, device) => {
|
||||
const nodeName = device.status?.nodeName;
|
||||
@@ -232,7 +241,12 @@ export default {
|
||||
<div class="row">
|
||||
<div class="col span-12">
|
||||
<Banner color="info">
|
||||
<t k="harvester.pci.howToUseDevice" />
|
||||
<MessageLink
|
||||
:to="toVGpuDevicesPage"
|
||||
prefix-label="harvester.pci.howToUseDevice.prefix"
|
||||
middle-label="harvester.pci.howToUseDevice.middle"
|
||||
suffix-label="harvester.pci.howToUseDevice.suffix"
|
||||
/>
|
||||
</Banner>
|
||||
<Banner
|
||||
v-if="selectedDevices.length > 0"
|
||||
|
||||
@@ -13,11 +13,12 @@ import { ucFirst, randomStr } from '@shell/utils/string';
|
||||
import { removeObject } from '@shell/utils/array';
|
||||
import { _VIEW, _EDIT, _CREATE } from '@shell/config/query-params';
|
||||
import { PLUGIN_DEVELOPER, DEV } from '@shell/store/prefs';
|
||||
import { SOURCE_TYPE } from '../../../config/harvester-map';
|
||||
import { VOLUME_HOTPLUG_ACTION, SOURCE_TYPE } from '../../../config/harvester-map';
|
||||
import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../../../config/harvester';
|
||||
import { HCI } from '../../../types';
|
||||
import { VOLUME_MODE } from '@pkg/harvester/config/types';
|
||||
import { OFF } from '../../../models/kubevirt.io.virtualmachine';
|
||||
import { EMPTY_IMAGE } from '../../../utils/vm';
|
||||
|
||||
export default {
|
||||
emits: ['update:value'],
|
||||
@@ -117,6 +118,10 @@ export default {
|
||||
return this.mode === _CREATE;
|
||||
},
|
||||
|
||||
isHotplugCdRomFeatureEnabled() {
|
||||
return this.$store.getters['harvester-common/getFeatureEnabled']('hotplugCdRom');
|
||||
},
|
||||
|
||||
defaultStorageClass() {
|
||||
const defaultStorage = this.$store.getters['harvester/all'](STORAGE_CLASS).find((sc) => sc.isDefault);
|
||||
|
||||
@@ -146,7 +151,7 @@ export default {
|
||||
value: {
|
||||
handler(neu) {
|
||||
const rows = clone(neu).map((V) => {
|
||||
if (!this.isCreate && V.source !== SOURCE_TYPE.CONTAINER && !V.newCreateId) {
|
||||
if (!this.isCreate && V.source !== SOURCE_TYPE.CONTAINER && !V.newCreateId && V.image !== EMPTY_IMAGE) {
|
||||
V.to = {
|
||||
name: `${ HARVESTER_PRODUCT }-c-cluster-resource-namespace-id`,
|
||||
params: {
|
||||
@@ -217,8 +222,48 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
unplugVolume(volume) {
|
||||
this.vm.unplugVolume(volume.name);
|
||||
canDoVolumeHotplugAction(volume) {
|
||||
if (!this.isHotplugCdRomFeatureEnabled && volume.type === 'cd-rom') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (volume.hotpluggable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return volume.type === 'cd-rom' && volume.bus === 'sata' && volume.image === EMPTY_IMAGE;
|
||||
},
|
||||
|
||||
getVolumeHotplugAction(volume) {
|
||||
if (volume.type === 'cd-rom' && volume.bus === 'sata') {
|
||||
if (volume.image === EMPTY_IMAGE) {
|
||||
return VOLUME_HOTPLUG_ACTION.INSERT_CDROM_IMAGE;
|
||||
}
|
||||
|
||||
return VOLUME_HOTPLUG_ACTION.EJECT_CDROM_IMAGE;
|
||||
}
|
||||
|
||||
return VOLUME_HOTPLUG_ACTION.DETACH_DISK;
|
||||
},
|
||||
|
||||
getVolumeHotplugActionLabel(volume) {
|
||||
const labels = {
|
||||
[VOLUME_HOTPLUG_ACTION.DETACH_DISK]: 'harvester.virtualMachine.hotUnplug.detachVolume.actionLabel',
|
||||
[VOLUME_HOTPLUG_ACTION.INSERT_CDROM_IMAGE]: 'harvester.modal.insertCdRomVolume.actionLabel',
|
||||
[VOLUME_HOTPLUG_ACTION.EJECT_CDROM_IMAGE]: 'harvester.virtualMachine.hotUnplug.ejectCdRomVolume.actionLabel',
|
||||
};
|
||||
|
||||
return labels[this.getVolumeHotplugAction(volume)];
|
||||
},
|
||||
|
||||
hotplugVolume(volume) {
|
||||
const calls = {
|
||||
[VOLUME_HOTPLUG_ACTION.DETACH_DISK]: () => this.vm.unplugVolume(volume.name),
|
||||
[VOLUME_HOTPLUG_ACTION.INSERT_CDROM_IMAGE]: () => this.vm.insertCdRomVolume(volume.name),
|
||||
[VOLUME_HOTPLUG_ACTION.EJECT_CDROM_IMAGE]: () => this.vm.ejectCdRomVolume(volume.name),
|
||||
};
|
||||
|
||||
return calls[this.getVolumeHotplugAction(volume)]();
|
||||
},
|
||||
|
||||
componentFor(type) {
|
||||
@@ -346,12 +391,12 @@ export default {
|
||||
<i class="icon icon-x" />
|
||||
</button>
|
||||
<button
|
||||
v-if="volume.hotpluggable && isView"
|
||||
v-if="canDoVolumeHotplugAction(volume) && isView"
|
||||
type="button"
|
||||
class="role-link btn btn-sm remove"
|
||||
@click="unplugVolume(volume)"
|
||||
@click="hotplugVolume(volume)"
|
||||
>
|
||||
{{ t('harvester.virtualMachine.hotUnplug.detachVolume.actionLabel') }}
|
||||
{{ t(getVolumeHotplugActionLabel(volume)) }}
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
+77
-5
@@ -14,6 +14,7 @@ import { _VIEW } from '@shell/config/query-params';
|
||||
import LabelValue from '@shell/components/LabelValue';
|
||||
import { ucFirst } from '@shell/utils/string';
|
||||
import { GIBIBYTE } from '../../../../utils/unit';
|
||||
import { EMPTY_IMAGE } from '../../../../utils/vm';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterEditVMImage',
|
||||
@@ -96,8 +97,20 @@ export default {
|
||||
return this.mode === _VIEW;
|
||||
},
|
||||
|
||||
isExistingCdrom() {
|
||||
return this.value.type === 'cd-rom' && !this.value.newCreateId;
|
||||
},
|
||||
|
||||
isEmptyImage() {
|
||||
return this.value.image === EMPTY_IMAGE;
|
||||
},
|
||||
|
||||
isHotplugCdRomFeatureEnabled() {
|
||||
return this.$store.getters['harvester-common/getFeatureEnabled']('hotplugCdRom');
|
||||
},
|
||||
|
||||
imagesOption() {
|
||||
return this.images
|
||||
const images = this.images
|
||||
.filter((image) => {
|
||||
if (!image.isReady) return false;
|
||||
|
||||
@@ -114,6 +127,19 @@ export default {
|
||||
value: image.id,
|
||||
disabled: image.isImportedImage
|
||||
}));
|
||||
|
||||
const options = [];
|
||||
|
||||
if (this.isHotplugCdRomFeatureEnabled) {
|
||||
options.push({
|
||||
label: this.t('harvester.virtualMachine.volume.emptyImage'),
|
||||
value: EMPTY_IMAGE,
|
||||
disabled: false
|
||||
});
|
||||
}
|
||||
options.push(...images);
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
imageName() {
|
||||
@@ -179,6 +205,7 @@ export default {
|
||||
'value.type'(neu) {
|
||||
if (neu === 'cd-rom') {
|
||||
this.value['bus'] = 'sata';
|
||||
this.updateHotpluggable();
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
@@ -221,12 +248,48 @@ export default {
|
||||
|
||||
return label;
|
||||
},
|
||||
|
||||
update() {
|
||||
this.value.hasDiskError = this.showDiskTooSmallError;
|
||||
this.$emit('update');
|
||||
},
|
||||
|
||||
updateHotpluggable() {
|
||||
if (this.value.type !== 'cd-rom') {
|
||||
this.value['hotpluggable'] = false;
|
||||
} else {
|
||||
this.value['hotpluggable'] = (this.value.bus === 'sata');
|
||||
}
|
||||
},
|
||||
|
||||
onTypeChange() {
|
||||
if (this.value.image === EMPTY_IMAGE && this.value.type !== 'cd-rom') {
|
||||
this.value['image'] = '';
|
||||
}
|
||||
|
||||
this.updateHotpluggable();
|
||||
this.update();
|
||||
},
|
||||
|
||||
onBusChange() {
|
||||
if (this.value.image === EMPTY_IMAGE && this.value.bus !== 'sata') {
|
||||
this.value['image'] = '';
|
||||
}
|
||||
|
||||
this.updateHotpluggable();
|
||||
this.update();
|
||||
},
|
||||
|
||||
onImageChange() {
|
||||
if (this.value.image === EMPTY_IMAGE) {
|
||||
this.value['type'] = 'cd-rom';
|
||||
this.value['bus'] = 'sata';
|
||||
this.value['size'] = `0${ GIBIBYTE }`;
|
||||
this.update();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const imageResource = this.$store.getters['harvester/all'](HCI.IMAGE)?.find( (I) => this.value.image === I.id);
|
||||
const isIsoImage = /iso$/i.test(imageResource?.imageSuffix);
|
||||
const imageSize = Math.max(imageResource?.status?.size, imageResource?.status?.virtualSize);
|
||||
@@ -239,6 +302,8 @@ export default {
|
||||
this.value['bus'] = 'virtio';
|
||||
}
|
||||
|
||||
this.updateHotpluggable();
|
||||
|
||||
if (imageSize) {
|
||||
let imageSizeGiB = Math.ceil(imageSize / 1024 / 1024 / 1024);
|
||||
|
||||
@@ -256,6 +321,10 @@ export default {
|
||||
},
|
||||
|
||||
checkImageExists(imageId) {
|
||||
if (imageId === EMPTY_IMAGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!!imageId && this.imagesOption.length > 0 && !findBy(this.imagesOption, 'value', imageId)) {
|
||||
this.$store.dispatch('growl/error', {
|
||||
title: this.$store.getters['i18n/t']('harvester.vmTemplate.tips.notExistImage.title', { name: imageId }),
|
||||
@@ -283,6 +352,7 @@ export default {
|
||||
>
|
||||
<LabeledInput
|
||||
v-model:value="value.name"
|
||||
:disabled="!isCreate && isExistingCdrom"
|
||||
:label="t('harvester.fields.name')"
|
||||
required
|
||||
:mode="mode"
|
||||
@@ -302,10 +372,11 @@ export default {
|
||||
>
|
||||
<LabeledSelect
|
||||
v-model:value="value.type"
|
||||
:disabled="!isCreate && isExistingCdrom"
|
||||
:label="t('harvester.fields.type')"
|
||||
:options="VOLUME_TYPE"
|
||||
:mode="mode"
|
||||
@update:value="update"
|
||||
@update:value="onTypeChange"
|
||||
/>
|
||||
</InputOrDisplay>
|
||||
</div>
|
||||
@@ -323,7 +394,7 @@ export default {
|
||||
>
|
||||
<LabeledSelect
|
||||
v-model:value="value.image"
|
||||
:disabled="idx === 0 && !isCreate && !value.newCreateId && isVirtualType"
|
||||
:disabled="(idx === 0 || isExistingCdrom) && (!isCreate && !value.newCreateId && isVirtualType)"
|
||||
:label="t('harvester.fields.image')"
|
||||
:options="imagesOption"
|
||||
:mode="mode"
|
||||
@@ -351,7 +422,7 @@ export default {
|
||||
:label="t('harvester.fields.size')"
|
||||
:mode="mode"
|
||||
:required="validateRequired"
|
||||
:disabled="isResizeDisabled"
|
||||
:disabled="isResizeDisabled || isEmptyImage || (!isCreate && isExistingCdrom)"
|
||||
:suffix="GIBIBYTE"
|
||||
@update:value="update"
|
||||
/>
|
||||
@@ -374,7 +445,8 @@ export default {
|
||||
:label="t('harvester.virtualMachine.volume.bus')"
|
||||
:mode="mode"
|
||||
:options="InterfaceOption"
|
||||
@update:value="update"
|
||||
:disabled="!isCreate && isExistingCdrom"
|
||||
@update:value="onBusChange"
|
||||
/>
|
||||
</InputOrDisplay>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { isEqual } from 'lodash';
|
||||
import { mapGetters } from 'vuex';
|
||||
import Tabbed from '@shell/components/Tabbed';
|
||||
import { clone } from '@shell/utils/object';
|
||||
import { clone, set } from '@shell/utils/object';
|
||||
import Tab from '@shell/components/Tabbed/Tab';
|
||||
import { Checkbox } from '@components/Form/Checkbox';
|
||||
import CruResource from '@shell/components/CruResource';
|
||||
@@ -32,6 +32,7 @@ import PciDevices from './VirtualMachinePciDevices/index';
|
||||
import AccessCredentials from './VirtualMachineAccessCredentials';
|
||||
import CloudConfig from './VirtualMachineCloudConfig';
|
||||
import CpuMemory from './VirtualMachineCpuMemory';
|
||||
import CpuModel from './VirtualMachineCpuModel';
|
||||
import Network from './VirtualMachineNetwork';
|
||||
import Volume from './VirtualMachineVolume';
|
||||
import SSHKey from './VirtualMachineSSHKey';
|
||||
@@ -57,6 +58,7 @@ export default {
|
||||
SSHKey,
|
||||
Network,
|
||||
CpuMemory,
|
||||
CpuModel,
|
||||
CloudConfig,
|
||||
NodeScheduling,
|
||||
PodAffinity,
|
||||
@@ -209,6 +211,10 @@ export default {
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
vGPUAsPCIDeviceEnabled() {
|
||||
return this.$store.getters['harvester-common/getFeatureEnabled']('vGPUAsPCIDevice');
|
||||
},
|
||||
usbPassthroughEnabled() {
|
||||
return this.$store.getters['harvester-common/getFeatureEnabled']('usbPassthrough');
|
||||
},
|
||||
@@ -538,6 +544,18 @@ export default {
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
updateCpuModel(value) {
|
||||
if (!this.spec?.template?.spec?.domain?.cpu) {
|
||||
set(this.spec, 'template.spec.domain.cpu', {});
|
||||
}
|
||||
|
||||
if (value && value !== '') {
|
||||
set(this.spec.template.spec.domain.cpu, 'model', value);
|
||||
} else {
|
||||
delete this.spec.template.spec.domain.cpu.model;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -726,7 +744,7 @@ export default {
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
v-if="enabledSriovgpu"
|
||||
v-if="enabledSriovgpu && !vGPUAsPCIDeviceEnabled"
|
||||
:label="t('harvester.tab.vGpuDevices')"
|
||||
name="vGpuDevices"
|
||||
:weight="-6"
|
||||
@@ -870,6 +888,16 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-20">
|
||||
<div class="col span-6">
|
||||
<CpuModel
|
||||
v-model:value="cpuModel"
|
||||
:mode="mode"
|
||||
@update:value="updateCpuModel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-20">
|
||||
<a
|
||||
v-if="showAdvanced"
|
||||
|
||||
@@ -306,11 +306,11 @@ export default {
|
||||
:weight="1"
|
||||
>
|
||||
<div class="row mb-20">
|
||||
<div class="col span-6">
|
||||
<div class="col span-12">
|
||||
<UnitInput
|
||||
v-model:value="value.spec.httpTimeoutSeconds"
|
||||
:label="t('harvester.addons.vmImport.ova.fields.httpTimeout')"
|
||||
placeholder="Default: 600"
|
||||
:placeholder="t('harvester.addons.vmImport.ova.placeholders.httpTimeout')"
|
||||
suffix="Seconds"
|
||||
:mode="mode"
|
||||
/>
|
||||
|
||||
@@ -7,6 +7,7 @@ import harvesterStore from './store/harvester-store';
|
||||
import customValidators from './validators';
|
||||
import { PRODUCT_NAME } from './config/harvester';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import './styles/vue-flow.scss';
|
||||
|
||||
// Init the package
|
||||
export default function (plugin: IPlugin) {
|
||||
|
||||
@@ -164,6 +164,11 @@ harvester:
|
||||
vmNetwork: Virtual Machine Network
|
||||
macAddress: MAC Address
|
||||
macAddressTooltip: If left blank, the MAC address will be automatically generated.
|
||||
insertCdRomVolume:
|
||||
success: '{ imageName } is inserted into device { deviceName }.'
|
||||
title: Insert Image
|
||||
image: Image
|
||||
actionLabel: Insert Image
|
||||
cpuMemoryHotplug:
|
||||
success: 'CPU and Memory are updated to the virtual machine { vm }.'
|
||||
title: Edit CPU and Memory
|
||||
@@ -196,6 +201,9 @@ harvester:
|
||||
info: Info
|
||||
warning: Warning
|
||||
error: Error
|
||||
restartRequired:
|
||||
title: '{count} {count, plural, =1 {Virtual Machine is} other {Virtual Machines are}} Pending Restart'
|
||||
message: 'Please restart { vmNames } to apply updated configurations'
|
||||
action:
|
||||
createVM: Create Virtual Machine
|
||||
start: Start
|
||||
@@ -347,7 +355,10 @@ harvester:
|
||||
available: Available Devices
|
||||
compatibleNodes: Compatible Nodes
|
||||
impossibleSelection: 'There are no hosts with all of the selected devices.'
|
||||
howToUseDevice: 'Use the table below to enable PCI passthrough on each device you want to use in this virtual machine.'
|
||||
howToUseDevice:
|
||||
prefix: 'Use the table below to enable PCI passthrough on each device you want to use in this virtual machine.<br>For vGPU devices, please enable them on the'
|
||||
middle: vGPU Devices
|
||||
suffix: page first.
|
||||
deviceInTheSameHost: 'You can only select devices on the same host.'
|
||||
oldFormatDevices:
|
||||
help: |-
|
||||
@@ -417,7 +428,7 @@ harvester:
|
||||
volume:
|
||||
upperType: Volume name
|
||||
lowerType: volume name
|
||||
needImageOrExisting: 'At least an image volume or an existing root-disk volume is required!'
|
||||
needAtLeastOneBootable: 'At least one bootable volume is required!'
|
||||
image:
|
||||
ruleTip: 'The URL you have entered ends in an extension that we do not support. We only accept image files that end in .img, .iso, .qcow, .qcow2, .raw.'
|
||||
ruleFileTip: 'The file you have chosen ends in an extension that we do not support. We only accept image files that end in .img, .iso, .qcow, .qcow2, .raw.'
|
||||
@@ -613,6 +624,10 @@ harvester:
|
||||
virtualMachine:
|
||||
label: Virtual Machines
|
||||
osType: OS Type
|
||||
cpuModel:
|
||||
label: CPU Model
|
||||
fetchError: 'Failed to load CPU model configuration: {error}'
|
||||
optionLabel: "{modelName} ({count} {count, plural, one {node} other {nodes}})"
|
||||
hotplug:
|
||||
title: Enable CPU and memory hotplug
|
||||
tooltip: The default maximum CPU and maximum memory are {hotPlugTimes} times based on CPU and memory.
|
||||
@@ -623,6 +638,10 @@ harvester:
|
||||
title: 'Are you sure that you want to detach volume {name}?'
|
||||
actionLabel: Detach Volume
|
||||
success: 'Volume { name } is detached successfully.'
|
||||
ejectCdRomVolume:
|
||||
title: 'Are you sure that you want to eject image from device {name}?'
|
||||
actionLabel: Eject Image
|
||||
success: 'Image from device { name } is ejected successfully.'
|
||||
detachNIC:
|
||||
title: 'Are you sure that you want to detach network interface {name}?'
|
||||
actionLabel: Detach Network Interface
|
||||
@@ -729,6 +748,7 @@ harvester:
|
||||
unmount:
|
||||
title: Are you sure?
|
||||
message: Are you sure you want to unmount this volume?
|
||||
emptyImage: No media
|
||||
network:
|
||||
title: Network
|
||||
addNetwork: Add Network
|
||||
@@ -1000,7 +1020,7 @@ harvester:
|
||||
createTitle: Create Schedule
|
||||
createButtonText: Create Schedule
|
||||
scheduleType: Virtual Machine Schedule Type
|
||||
cron:
|
||||
cron:
|
||||
label: Cron Schedule
|
||||
editButton: Edit
|
||||
detail:
|
||||
@@ -1129,6 +1149,25 @@ harvester:
|
||||
banner: The supported field in ACL match can refer to <a href="https://kubeovn.github.io/docs/v1.14.x/en/guide/subnet/#subnet-acl" target="_blank">KubeOvn Subnet ACL document</a>
|
||||
|
||||
vpc:
|
||||
viewTopology: Topology
|
||||
topology:
|
||||
loading: Loading topology...
|
||||
empty: No resources found
|
||||
visibility:
|
||||
vpc: VPC
|
||||
subnets: Subnets
|
||||
overlayNetworks: Overlay Networks
|
||||
vms: VMs
|
||||
labels:
|
||||
cidr: CIDR
|
||||
provider: Provider
|
||||
type: Type
|
||||
clusterNetwork: Cluster Network
|
||||
network: Network
|
||||
subnet: Subnet
|
||||
ip: IP
|
||||
mac: MAC
|
||||
peering: Peering
|
||||
noAddonEnabled:
|
||||
prefix: The kubeovn-operator add-on is not enabled, click
|
||||
middle: here
|
||||
@@ -1232,6 +1271,7 @@ harvester:
|
||||
tip: 'Specify an IP range in the IPv4 CIDR format. <code>Number of IPs Required = Number of Nodes * 2 + Number of Disks * 2 + Number of Images to Download/Upload </code>. For more information about storage network settings, see the <a href="{url}" target="_blank">documentation</a>.'
|
||||
vmForceDeletionPolicy:
|
||||
period: Period
|
||||
vmMigrationTimeout: VM Migration Timeout
|
||||
vmMigrationNetwork:
|
||||
parseError: "Failed to parse existing configuration."
|
||||
fetchError: "Failed to load required network resources: {error}. Please refresh the page or try again later."
|
||||
@@ -1314,6 +1354,12 @@ harvester:
|
||||
retention: How long to retain metrics
|
||||
retentionSize: Maximum size of metrics
|
||||
clusterRegistrationUrl:
|
||||
url: URL
|
||||
insecureSkipTLSVerify: Insecure Skip TLS Verify
|
||||
tip:
|
||||
prefix: Harvester secures cluster registration via TLS by default. If opt out "Insecure SKip TLS Verify", you must provide custom CA certificates using the
|
||||
middle: 'additional-ca'
|
||||
suffix: setting.
|
||||
message: To completely unset the imported Harvester cluster, please also remove it on the Rancher Dashboard UI via the <code> Virtualization Management </code> page.
|
||||
ntpServers:
|
||||
isNotIPV4: The address you entered is not IPv4 or host. Please enter a valid IPv4 address or a host address.
|
||||
@@ -1657,10 +1703,11 @@ harvester:
|
||||
datacenter: The exact name of the Datacenter object in vCenter
|
||||
ova:
|
||||
fields:
|
||||
url: OVA URL
|
||||
url: URL
|
||||
httpTimeout: HTTP Timeout
|
||||
placeholders:
|
||||
url: "e.g. https://download.example.com/images/my-vm.ova"
|
||||
httpTimeout: "Default: 600"
|
||||
|
||||
rancherVcluster:
|
||||
accessRancher: Access the Rancher Dashboard
|
||||
@@ -1788,7 +1835,8 @@ harvester:
|
||||
numVFs: Number Of Virtual Functions
|
||||
vfAddresses: Virtual Functions Addresses
|
||||
showMore: Show More
|
||||
parentSriov: Filter By Parent SR-IOV
|
||||
parentSriov: Filter By Parent SR-IOV Netork Device
|
||||
parentSriovGPU: Filter By Parent SR-IOV GPU Device
|
||||
|
||||
sriovgpu:
|
||||
label: SR-IOV GPU Devices
|
||||
@@ -1929,6 +1977,7 @@ advancedSettings:
|
||||
'harv-additional-ca': 'Custom CA root certificates for TLS validation.'
|
||||
'harv-overcommit-config': 'Resource overcommit configuration.'
|
||||
'harv-support-bundle-timeout': 'Support bundle timeout configuration in minutes, use 0 to disable the timeout.'
|
||||
'harv-support-bundle-file-name': 'Support bundle file name configuration.'
|
||||
'harv-support-bundle-expiration': 'Support bundle expiration configuration in minutes.'
|
||||
'harv-support-bundle-node-collection-timeout': 'Support bundle node collection timeout configuration in minutes.'
|
||||
'harv-vm-force-reset-policy': Configuration for the force-reset action when a virtual machine is stuck on a node that is down.
|
||||
@@ -2130,3 +2179,23 @@ typeLabel:
|
||||
one { IP Pool }
|
||||
other { IP Pools }
|
||||
}
|
||||
migration.harvesterhci.io.openstacksource: |-
|
||||
{count, plural,
|
||||
one { OpenStack Source }
|
||||
other { OpenStack Sources }
|
||||
}
|
||||
migration.harvesterhci.io.vmwaresource: |-
|
||||
{count, plural,
|
||||
one { VMware Source }
|
||||
other { VMware Sources }
|
||||
}
|
||||
migration.harvesterhci.io.ovasource: |-
|
||||
{count, plural,
|
||||
one { OVA Source }
|
||||
other { OVA Sources }
|
||||
}
|
||||
migration.harvesterhci.io.virtualmachineimport: |-
|
||||
{count, plural,
|
||||
one { Virtual Machine Import }
|
||||
other { Virtual Machine Imports }
|
||||
}
|
||||
|
||||
@@ -155,6 +155,15 @@ export default {
|
||||
return location;
|
||||
},
|
||||
|
||||
viewTopology(group) {
|
||||
const vpc = group.key;
|
||||
const resource = this.$store.getters[`harvester/byId`](HCI.VPC, vpc);
|
||||
|
||||
if (resource && resource.goToDetail) {
|
||||
resource.goToDetail();
|
||||
}
|
||||
},
|
||||
|
||||
showVpcAction(event, group) {
|
||||
const vpc = group.key;
|
||||
|
||||
@@ -218,6 +227,14 @@ export default {
|
||||
>
|
||||
{{ t('harvester.vpc.createSubnet') }}
|
||||
</router-link>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="viewTopology(group)"
|
||||
>
|
||||
<i class="icon icon-globe mr-5" />
|
||||
{{ t('harvester.vpc.viewTopology') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm role-multi-action actions mr-10"
|
||||
|
||||
@@ -110,11 +110,12 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
hasNode: false,
|
||||
allVMs: [],
|
||||
allVMIs: [],
|
||||
allNodeNetworks: [],
|
||||
allClusterNetworks: [],
|
||||
hasNode: false,
|
||||
allVMs: [],
|
||||
allVMIs: [],
|
||||
allNodeNetworks: [],
|
||||
allClusterNetworks: [],
|
||||
restartNotificationDisplayed: false,
|
||||
HCI
|
||||
};
|
||||
},
|
||||
@@ -174,6 +175,48 @@ export default {
|
||||
this['allVMIs'] = vmis;
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
// clear restart message before component unmount
|
||||
this.$store.dispatch('growl/clear');
|
||||
},
|
||||
|
||||
watch: {
|
||||
allVMs: {
|
||||
handler(neu) {
|
||||
const vmNames = [];
|
||||
|
||||
neu.forEach((vm) => {
|
||||
if (vm.isRestartRequired) {
|
||||
vmNames.push(vm.metadata.name);
|
||||
}
|
||||
});
|
||||
const count = vmNames.length;
|
||||
|
||||
if ( count === 0 && this.restartNotificationDisplayed) {
|
||||
this.restartNotificationDisplayed = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
// clear old notification before showing new one
|
||||
if (this.restartNotificationDisplayed) {
|
||||
this.$store.dispatch('growl/clear');
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0 && vmNames.length > 0) {
|
||||
this.$store.dispatch('growl/warning', {
|
||||
title: this.t('harvester.notification.restartRequired.title', { count }),
|
||||
message: this.t('harvester.notification.restartRequired.message', { vmNames: vmNames.join(', ') }),
|
||||
timeout: 10000,
|
||||
}, { root: true });
|
||||
this.restartNotificationDisplayed = true;
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
lockIconTooltipMessage(row) {
|
||||
const message = '';
|
||||
@@ -243,6 +286,12 @@ export default {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.growl-container {
|
||||
z-index: 56 !important; // set to be lower than the vm action menu (z-index: 57)
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.state {
|
||||
display: flex;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<script>
|
||||
import ResourceTable from '@shell/components/ResourceTable';
|
||||
import Loading from '@shell/components/Loading';
|
||||
import { SCHEMA } from '@shell/config/types';
|
||||
import { HCI } from '../types';
|
||||
|
||||
const schema = {
|
||||
id: HCI.VMIMPORT_SOURCE_OVA,
|
||||
type: SCHEMA,
|
||||
attributes: {
|
||||
kind: HCI.VMIMPORT_SOURCE_OVA,
|
||||
namespaced: true
|
||||
},
|
||||
metadata: { name: HCI.VMIMPORT_SOURCE_OVA },
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'HarvesterVMImportSourceOVA',
|
||||
components: { ResourceTable, Loading },
|
||||
inheritAttrs: false,
|
||||
|
||||
async fetch() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
this.rows = await this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.VMIMPORT_SOURCE_OVA });
|
||||
|
||||
const configSchema = this.$store.getters[`${ inStore }/schemaFor`](HCI.VMIMPORT_SOURCE_OVA);
|
||||
|
||||
if (!configSchema?.collectionMethods.find((x) => x.toLowerCase() === 'post')) {
|
||||
this.$store.dispatch('type-map/configureType', { match: HCI.VMIMPORT_SOURCE_OVA, isCreatable: false });
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return { rows: [] };
|
||||
},
|
||||
|
||||
computed: {
|
||||
schema() {
|
||||
return schema;
|
||||
}
|
||||
},
|
||||
|
||||
typeDisplay() {
|
||||
return this.$store.getters['type-map/labelFor'](schema, 99);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Loading v-if="$fetchState.pending" />
|
||||
<ResourceTable
|
||||
v-else
|
||||
v-bind="$attrs"
|
||||
:groupable="true"
|
||||
:schema="schema"
|
||||
:rows="rows"
|
||||
key-field="_key"
|
||||
/>
|
||||
</template>
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
} from '../../config/harvester-map';
|
||||
import { HCI_SETTING } from '../../config/settings';
|
||||
import { HCI } from '../../types';
|
||||
import { parseVolumeClaimTemplates } from '../../utils/vm';
|
||||
import { parseVolumeClaimTemplates, EMPTY_IMAGE } from '../../utils/vm';
|
||||
import impl, { QGA_JSON, USB_TABLET } from './impl';
|
||||
import { GIBIBYTE } from '../../utils/unit';
|
||||
import { VOLUME_MODE } from '@pkg/harvester/config/types';
|
||||
@@ -182,6 +182,7 @@ export default {
|
||||
immutableMode: this.realMode === _CREATE ? _CREATE : _VIEW,
|
||||
terminationGracePeriodSeconds: '',
|
||||
cpuPinning: false,
|
||||
cpuModel: '',
|
||||
};
|
||||
},
|
||||
|
||||
@@ -394,6 +395,7 @@ export default {
|
||||
const efiPersistentStateEnabled = this.isEFIPersistentStateEnabled(spec);
|
||||
const secureBoot = this.isSecureBoot(spec);
|
||||
const cpuPinning = this.isCpuPinning(spec);
|
||||
const cpuModel = spec.template.spec.domain.cpu?.model || '';
|
||||
|
||||
const secretRef = this.getSecret(spec);
|
||||
const accessCredentials = this.getAccessCredentials(spec);
|
||||
@@ -431,6 +433,7 @@ export default {
|
||||
this['tpmPersistentStateEnabled'] = tpmPersistentStateEnabled;
|
||||
this['secureBoot'] = secureBoot;
|
||||
this['cpuPinning'] = cpuPinning;
|
||||
this['cpuModel'] = cpuModel;
|
||||
|
||||
this['hasCreateVolumes'] = hasCreateVolumes;
|
||||
this['networkRows'] = networkRows;
|
||||
@@ -508,12 +511,15 @@ export default {
|
||||
|
||||
const type = DISK?.cdrom ? CD_ROM : DISK?.disk ? HARD_DISK : '';
|
||||
|
||||
if (volume?.containerDisk) { // SOURCE_TYPE.CONTAINER
|
||||
if (type === CD_ROM && volume === undefined) {
|
||||
// Empty CD_ROM
|
||||
source = SOURCE_TYPE.IMAGE;
|
||||
image = EMPTY_IMAGE;
|
||||
size = `0${ GIBIBYTE }`;
|
||||
} else if (volume.containerDisk) { // SOURCE_TYPE.CONTAINER
|
||||
source = SOURCE_TYPE.CONTAINER;
|
||||
container = volume.containerDisk.image;
|
||||
}
|
||||
|
||||
if (volume.persistentVolumeClaim && volume.persistentVolumeClaim?.claimName) {
|
||||
} else if (volume.persistentVolumeClaim && volume.persistentVolumeClaim?.claimName) {
|
||||
volumeName = volume.persistentVolumeClaim.claimName;
|
||||
const DVT = _volumeClaimTemplates.find( (T) => T.metadata.name === volumeName);
|
||||
|
||||
@@ -701,25 +707,41 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
needVolumeRelatedInfo(R) {
|
||||
// return [needVolume, needVolumeClaimTemplate]
|
||||
if (R.source === SOURCE_TYPE.CONTAINER) {
|
||||
return [true, false];
|
||||
}
|
||||
|
||||
if (R.source === SOURCE_TYPE.IMAGE && R.image === EMPTY_IMAGE) {
|
||||
return [false, false];
|
||||
}
|
||||
|
||||
return [true, true];
|
||||
},
|
||||
|
||||
parseDiskRows(disk) {
|
||||
const disks = [];
|
||||
const volumes = [];
|
||||
const diskNameLabels = [];
|
||||
const volumeClaimTemplates = [];
|
||||
|
||||
disk.forEach( (R, index) => {
|
||||
const prefixName = this.value.metadata?.name || '';
|
||||
const dataVolumeName = this.parseDataVolumeName(R, prefixName);
|
||||
|
||||
const _disk = this.parseDisk(R, index);
|
||||
const _volume = this.parseVolume(R, dataVolumeName);
|
||||
const _dataVolumeTemplate = this.parseVolumeClaimTemplate(R, dataVolumeName);
|
||||
|
||||
disks.push(_disk);
|
||||
volumes.push(_volume);
|
||||
diskNameLabels.push(dataVolumeName);
|
||||
|
||||
if (R.source !== SOURCE_TYPE.CONTAINER) {
|
||||
const prefixName = this.value.metadata?.name || '';
|
||||
const dataVolumeName = this.parseDataVolumeName(R, prefixName);
|
||||
const [needVolume, needVolumeClaimTemplate] = this.needVolumeRelatedInfo(R);
|
||||
|
||||
if (needVolume) {
|
||||
const _volume = this.parseVolume(R, dataVolumeName);
|
||||
|
||||
volumes.push(_volume);
|
||||
}
|
||||
if (needVolumeClaimTemplate) {
|
||||
const _dataVolumeTemplate = this.parseVolumeClaimTemplate(R, dataVolumeName);
|
||||
|
||||
volumeClaimTemplates.push(_dataVolumeTemplate);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SteveModel from '@shell/plugins/steve/steve-class';
|
||||
import { escapeHtml } from '@shell/utils/string';
|
||||
import { HCI } from '../types';
|
||||
import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations';
|
||||
|
||||
const STATUS_DISPLAY = {
|
||||
enabled: {
|
||||
@@ -32,7 +33,7 @@ export default class PCIDevice extends SteveModel {
|
||||
out.push(
|
||||
{
|
||||
action: 'enablePassthroughBulk',
|
||||
enabled: !this.isEnabling,
|
||||
enabled: !this.isEnabling && !this.isvGPUDevice,
|
||||
icon: 'icon icon-fw icon-dot',
|
||||
label: 'Enable Passthrough',
|
||||
bulkable: true,
|
||||
@@ -41,7 +42,7 @@ export default class PCIDevice extends SteveModel {
|
||||
},
|
||||
{
|
||||
action: 'disablePassthrough',
|
||||
enabled: this.isEnabling && this.claimedByMe,
|
||||
enabled: this.isEnabling && this.claimedByMe && !this.isvGPUDevice,
|
||||
icon: 'icon icon-fw icon-dot-open',
|
||||
label: 'Disable Passthrough',
|
||||
bulkable: true,
|
||||
@@ -52,6 +53,14 @@ export default class PCIDevice extends SteveModel {
|
||||
return out;
|
||||
}
|
||||
|
||||
get isvGPUDevice() {
|
||||
if (!this.vGPUAsPCIDeviceFeatureEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!this.metadata?.labels?.[HCI_ANNOTATIONS.PARENT_SRIOV_GPU] || this.status?.resourceName.includes('nvidia.com');
|
||||
}
|
||||
|
||||
get canYaml() {
|
||||
return false;
|
||||
}
|
||||
@@ -176,6 +185,10 @@ export default class PCIDevice extends SteveModel {
|
||||
return this.status?.description;
|
||||
}
|
||||
|
||||
get vGPUAsPCIDeviceFeatureEnabled() {
|
||||
return this.$rootGetters['harvester-common/getFeatureEnabled']('vGPUAsPCIDevice');
|
||||
}
|
||||
|
||||
showDetachWarning() {
|
||||
this.$dispatch('growl/warning', {
|
||||
title: this.$rootGetters['i18n/t']('harvester.pci.detachWarning.title'),
|
||||
|
||||
@@ -536,8 +536,7 @@ export default class HciNode extends HarvesterResource {
|
||||
get isStopped() {
|
||||
const inventory = this.inventory || {};
|
||||
|
||||
return inventory.spec?.powerActionRequested === 'shutdown' &&
|
||||
inventory.status?.powerAction?.actionStatus === 'complete';
|
||||
return inventory.status?.machinePowerState === 'off';
|
||||
}
|
||||
|
||||
get isStopping() {
|
||||
@@ -553,8 +552,7 @@ export default class HciNode extends HarvesterResource {
|
||||
get isStarted() {
|
||||
const inventory = this.inventory || {};
|
||||
|
||||
return inventory.spec?.powerActionRequested === 'poweron' &&
|
||||
inventory.status?.powerAction?.actionStatus === 'complete';
|
||||
return inventory.status?.machinePowerState === 'on';
|
||||
}
|
||||
|
||||
get isStarting() {
|
||||
|
||||
@@ -52,11 +52,19 @@ export default class HciSetting extends HarvesterResource {
|
||||
});
|
||||
}
|
||||
|
||||
get clusterRegistrationTLSVerifyFeatureEnabled() {
|
||||
return this.$rootGetters['harvester-common/getFeatureEnabled']('clusterRegistrationTLSVerify');
|
||||
}
|
||||
|
||||
get customValue() {
|
||||
if (this.metadata.name === HCI_SETTING.STORAGE_NETWORK) {
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(this.value), null, 2);
|
||||
} catch (e) {}
|
||||
} else if (this.metadata.name === HCI_SETTING.CLUSTER_REGISTRATION_URL) {
|
||||
try {
|
||||
return this.clusterRegistrationTLSVerifyFeatureEnabled ? JSON.stringify(JSON.parse(this.value), null, 2) : this.value;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -183,7 +183,7 @@ export default class VirtVm extends HarvesterResource {
|
||||
},
|
||||
{
|
||||
action: 'ejectCDROM',
|
||||
enabled: !!this.actions?.ejectCdRom,
|
||||
enabled: !this.hotplugCdRomEnabled && !!this.actions?.ejectCdRom,
|
||||
icon: 'icon icon-delete',
|
||||
label: this.t('harvester.action.ejectCDROM')
|
||||
},
|
||||
@@ -401,6 +401,17 @@ export default class VirtVm extends HarvesterResource {
|
||||
});
|
||||
}
|
||||
|
||||
ejectCdRomVolume(diskName) {
|
||||
const resources = this;
|
||||
|
||||
this.$dispatch('promptModal', {
|
||||
resources,
|
||||
name: diskName,
|
||||
type: 'cdrom',
|
||||
component: 'HarvesterHotUnplug',
|
||||
});
|
||||
}
|
||||
|
||||
unplugNIC(networkName) {
|
||||
const resources = this;
|
||||
|
||||
@@ -523,6 +534,16 @@ export default class VirtVm extends HarvesterResource {
|
||||
});
|
||||
}
|
||||
|
||||
insertCdRomVolume(diskName) {
|
||||
const resources = this;
|
||||
|
||||
this.$dispatch('promptModal', {
|
||||
resources,
|
||||
name: diskName,
|
||||
component: 'HarvesterInsertCdRomVolume',
|
||||
});
|
||||
}
|
||||
|
||||
addHotplugNic(resources = this) {
|
||||
this.$dispatch('promptModal', {
|
||||
resources,
|
||||
@@ -749,11 +770,11 @@ export default class VirtVm extends HarvesterResource {
|
||||
}
|
||||
|
||||
get isPending() {
|
||||
if (this &&
|
||||
if ((this &&
|
||||
!this.isVMExpectedRunning &&
|
||||
this.isVMCreated &&
|
||||
this.vmi?.status?.phase === VMIPhase.Pending
|
||||
) {
|
||||
) || (this.metadata?.annotations?.[HCI_ANNOTATIONS.CLONE_BACKEND_STORAGE_STATUS] === 'cloning')) {
|
||||
return { status: VMIPhase.Pending };
|
||||
}
|
||||
|
||||
@@ -1180,11 +1201,15 @@ export default class VirtVm extends HarvesterResource {
|
||||
);
|
||||
}
|
||||
|
||||
get stateDescription() {
|
||||
get isRestartRequired() {
|
||||
const conditions = get(this, 'status.conditions');
|
||||
const restartRequired = findBy(conditions, 'type', 'RestartRequired');
|
||||
|
||||
if (restartRequired && restartRequired.status === 'True') {
|
||||
return restartRequired && restartRequired.status === 'True';
|
||||
}
|
||||
|
||||
get stateDescription() {
|
||||
if (this.isRestartRequired) {
|
||||
return this.t('harvester.virtualMachine.hotplug.restartVMMessage');
|
||||
}
|
||||
|
||||
@@ -1263,6 +1288,10 @@ export default class VirtVm extends HarvesterResource {
|
||||
return this.$rootGetters['harvester-common/getFeatureEnabled']('hotplugNic');
|
||||
}
|
||||
|
||||
get hotplugCdRomEnabled() {
|
||||
return this.$rootGetters['harvester-common/getFeatureEnabled']('hotplugCdRom');
|
||||
}
|
||||
|
||||
get isBackupTargetUnavailable() {
|
||||
const allSettings = this.$rootGetters['harvester/all'](HCI.SETTING) || [];
|
||||
const backupTargetSetting = allSettings.find( (O) => O.id === 'backup-target');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "harvester",
|
||||
"description": "Rancher UI Extension for Harvester",
|
||||
"version": "1.8.0-dev",
|
||||
"version": "1.8.0-rc1",
|
||||
"private": false,
|
||||
"rancher": {
|
||||
"annotations": {
|
||||
|
||||
@@ -98,6 +98,11 @@ export default {
|
||||
if (getters['schemaFor'](HCI.UPGRADE)) {
|
||||
hash.upgrades = dispatch('findAll', { type: HCI.UPGRADE });
|
||||
}
|
||||
// Pre-fetch all HCI.UPGRADE_LOG data within loadCluster to ensure HarvesterUpgradeHeader has the necessary data. This is required because the header is dynamically loaded before the user enters the cluster in Rancher integration mode.
|
||||
// See more details in https://github.com/harvester/harvester-ui-extension/pull/715
|
||||
if (getters['schemaFor'](HCI.UPGRADE_LOG)) {
|
||||
hash.upgradeLogs = dispatch('findAll', { type: HCI.UPGRADE_LOG });
|
||||
}
|
||||
|
||||
const res: any = await allHash(hash);
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
@import '@vue-flow/core/dist/style.css';
|
||||
@import '@vue-flow/core/dist/theme-default.css';
|
||||
@import '@vue-flow/controls/dist/style.css';
|
||||
@import '@vue-flow/minimap/dist/style.css';
|
||||
@@ -18,6 +18,7 @@ export const HCI = {
|
||||
CLUSTER_NETWORK: 'network.harvesterhci.io.clusternetwork',
|
||||
SUBNET: 'kubeovn.io.subnet',
|
||||
VPC: 'kubeovn.io.vpc',
|
||||
IP: 'kubeovn.io.ip',
|
||||
VM_IMAGE_DOWNLOADER: 'harvesterhci.io.virtualmachineimagedownloader',
|
||||
SUPPORT_BUNDLE: 'harvesterhci.io.supportbundle',
|
||||
NETWORK_ATTACHMENT: 'harvesterhci.io.networkattachmentdefinition',
|
||||
|
||||
@@ -9,3 +9,5 @@ export function parseVolumeClaimTemplates(data) {
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
export const EMPTY_IMAGE = 'EMPTY_IMAGE';
|
||||
|
||||
@@ -69,7 +69,7 @@ export function vmDisks(spec, getters, errors, validatorArgs, displayKey, value)
|
||||
validName(getters, errors, D.name, diskNames, prefix, type, lowerType, upperType);
|
||||
});
|
||||
|
||||
let requiredVolume = false;
|
||||
let hasBootableVolume = false;
|
||||
|
||||
_volumes.forEach((V, idx) => {
|
||||
const { type, typeValue } = getVolumeType(getters, V, _volumeClaimTemplates, value);
|
||||
@@ -77,7 +77,7 @@ export function vmDisks(spec, getters, errors, validatorArgs, displayKey, value)
|
||||
const prefix = V.name || idx + 1;
|
||||
|
||||
if ([SOURCE_TYPE.IMAGE, SOURCE_TYPE.ATTACH_VOLUME, SOURCE_TYPE.CONTAINER].includes(type)) {
|
||||
requiredVolume = true;
|
||||
hasBootableVolume = true;
|
||||
}
|
||||
|
||||
if (type === SOURCE_TYPE.NEW || type === SOURCE_TYPE.IMAGE) {
|
||||
@@ -137,10 +137,10 @@ export function vmDisks(spec, getters, errors, validatorArgs, displayKey, value)
|
||||
});
|
||||
|
||||
/**
|
||||
* At least one volume must be create. (Verify only when create.)
|
||||
* At least one bootable volume must be provided. (Verify only when create.)
|
||||
*/
|
||||
if ((!requiredVolume || _volumes.length === 0) && !value.links) {
|
||||
errors.push(getters['i18n/t']('harvester.validation.vm.volume.needImageOrExisting'));
|
||||
if (!hasBootableVolume && !value.links) {
|
||||
errors.push(getters['i18n/t']('harvester.validation.vm.volume.needAtLeastOneBootable'));
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
||||
@@ -11,14 +11,6 @@
|
||||
event-pubsub "4.3.0"
|
||||
js-message "1.0.7"
|
||||
|
||||
"@ampproject/remapping@^2.2.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
|
||||
integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.24"
|
||||
|
||||
"@aws-crypto/sha256-browser@5.2.0":
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e"
|
||||
@@ -927,7 +919,7 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.10.4"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.8.3":
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.8.3":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7"
|
||||
integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==
|
||||
@@ -936,38 +928,12 @@
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.1.1"
|
||||
|
||||
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4":
|
||||
version "7.25.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb"
|
||||
integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==
|
||||
|
||||
"@babel/compat-data@^7.28.6":
|
||||
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.4", "@babel/compat-data@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c"
|
||||
integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==
|
||||
|
||||
"@babel/core@^7.1.0", "@babel/core@^7.12.16", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77"
|
||||
integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.2.0"
|
||||
"@babel/code-frame" "^7.24.7"
|
||||
"@babel/generator" "^7.25.0"
|
||||
"@babel/helper-compilation-targets" "^7.25.2"
|
||||
"@babel/helper-module-transforms" "^7.25.2"
|
||||
"@babel/helpers" "^7.25.0"
|
||||
"@babel/parser" "^7.25.0"
|
||||
"@babel/template" "^7.25.0"
|
||||
"@babel/traverse" "^7.25.2"
|
||||
"@babel/types" "^7.25.2"
|
||||
convert-source-map "^2.0.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
json5 "^2.2.3"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/core@^7.23.9":
|
||||
"@babel/core@^7.1.0", "@babel/core@^7.12.16", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f"
|
||||
integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==
|
||||
@@ -988,7 +954,7 @@
|
||||
json5 "^2.2.3"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/generator@^7.25.0", "@babel/generator@^7.28.6", "@babel/generator@^7.7.2":
|
||||
"@babel/generator@^7.28.6", "@babel/generator@^7.7.2":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1"
|
||||
integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==
|
||||
@@ -1014,18 +980,7 @@
|
||||
"@babel/traverse" "^7.24.7"
|
||||
"@babel/types" "^7.24.7"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.12.16", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8", "@babel/helper-compilation-targets@^7.25.2":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c"
|
||||
integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.25.2"
|
||||
"@babel/helper-validator-option" "^7.24.8"
|
||||
browserslist "^4.23.1"
|
||||
lru-cache "^5.1.1"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.28.6":
|
||||
"@babel/helper-compilation-targets@^7.12.16", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8", "@babel/helper-compilation-targets@^7.25.2", "@babel/helper-compilation-targets@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25"
|
||||
integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==
|
||||
@@ -1082,15 +1037,7 @@
|
||||
"@babel/traverse" "^7.28.5"
|
||||
"@babel/types" "^7.28.5"
|
||||
|
||||
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b"
|
||||
integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.24.7"
|
||||
"@babel/types" "^7.24.7"
|
||||
|
||||
"@babel/helper-module-imports@^7.28.6":
|
||||
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.24.7", "@babel/helper-module-imports@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c"
|
||||
integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==
|
||||
@@ -1105,17 +1052,7 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.22.15"
|
||||
|
||||
"@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.25.2":
|
||||
version "7.25.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6"
|
||||
integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.24.7"
|
||||
"@babel/helper-simple-access" "^7.24.7"
|
||||
"@babel/helper-validator-identifier" "^7.24.7"
|
||||
"@babel/traverse" "^7.25.2"
|
||||
|
||||
"@babel/helper-module-transforms@^7.28.6":
|
||||
"@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e"
|
||||
integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==
|
||||
@@ -1180,12 +1117,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4"
|
||||
integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==
|
||||
|
||||
"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.24.8":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d"
|
||||
integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==
|
||||
|
||||
"@babel/helper-validator-option@^7.27.1":
|
||||
"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.24.8", "@babel/helper-validator-option@^7.27.1":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f"
|
||||
integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==
|
||||
@@ -1199,14 +1131,6 @@
|
||||
"@babel/traverse" "^7.25.0"
|
||||
"@babel/types" "^7.25.0"
|
||||
|
||||
"@babel/helpers@^7.25.0":
|
||||
version "7.25.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.6.tgz#57ee60141829ba2e102f30711ffe3afab357cc60"
|
||||
integrity sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==
|
||||
dependencies:
|
||||
"@babel/template" "^7.25.0"
|
||||
"@babel/types" "^7.25.6"
|
||||
|
||||
"@babel/helpers@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7"
|
||||
@@ -1225,7 +1149,7 @@
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.25.0", "@babel/parser@^7.28.0", "@babel/parser@^7.28.6", "@babel/parser@^7.7.0":
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.28.0", "@babel/parser@^7.28.6", "@babel/parser@^7.7.0":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd"
|
||||
integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==
|
||||
@@ -2018,7 +1942,7 @@
|
||||
"@babel/parser" "^7.28.6"
|
||||
"@babel/types" "^7.28.6"
|
||||
|
||||
"@babel/traverse@^7.23.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4", "@babel/traverse@^7.27.1", "@babel/traverse@^7.28.5", "@babel/traverse@^7.28.6", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
|
||||
"@babel/traverse@^7.23.9", "@babel/traverse@^7.24.7", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.4", "@babel/traverse@^7.27.1", "@babel/traverse@^7.28.5", "@babel/traverse@^7.28.6", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e"
|
||||
integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==
|
||||
@@ -2031,7 +1955,7 @@
|
||||
"@babel/types" "^7.28.6"
|
||||
debug "^4.3.1"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.23.9", "@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.6", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.5", "@babel/types@^7.28.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.23.9", "@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.5", "@babel/types@^7.28.6", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df"
|
||||
integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==
|
||||
@@ -2709,15 +2633,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
|
||||
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
|
||||
|
||||
"@rancher/icons@2.0.54":
|
||||
version "2.0.54"
|
||||
resolved "https://registry.yarnpkg.com/@rancher/icons/-/icons-2.0.54.tgz#7e8d4baeac36a483f18f4ce4043809371c4f0117"
|
||||
integrity sha512-Fc5xpT/yuOJJin7ChxAdB6aoG1bREgisktnePUPXpY9nIMHSHYT/Ov8GsC3yLLgoqgpm450nMvPICUO3AYcPdQ==
|
||||
"@rancher/icons@2.0.55":
|
||||
version "2.0.55"
|
||||
resolved "https://registry.yarnpkg.com/@rancher/icons/-/icons-2.0.55.tgz#394159bddbf786c17a12bc38e59b88346b30dcf4"
|
||||
integrity sha512-hPcmsvfYNO36dJ7/lb3JbJC5BOnHbwBylic7HRqhSCSIcFlFaKnRt9aB/hvv3ip0Wo6J5yVEv2o7oXGErXkWFw==
|
||||
|
||||
"@rancher/shell@3.0.9-rc.1":
|
||||
version "3.0.9-rc.1"
|
||||
resolved "https://registry.yarnpkg.com/@rancher/shell/-/shell-3.0.9-rc.1.tgz#6dfe7d8a17663d170ddf5f48bec5c7c525c9da86"
|
||||
integrity sha512-X7HKIhprzzLaeZXLhAnWHDjr9Rk1nLko+pno0rEkcK7F9ENQgVuROzVxEgMlFno4bI7RpHXt5tC90rPkXzcsRQ==
|
||||
"@rancher/shell@3.0.9-rc.6":
|
||||
version "3.0.9-rc.6"
|
||||
resolved "https://registry.yarnpkg.com/@rancher/shell/-/shell-3.0.9-rc.6.tgz#d22add189481368a07df54c61d437f024236f639"
|
||||
integrity sha512-qhTq7Ohsm/pToKRh010KVWLS4gH9g5BP55Ih0T62ZfTMIpO5JjiJkL/EtrRwlll47NKU1GHZ+lqh9yb3HJgDBg==
|
||||
dependencies:
|
||||
"@aws-sdk/client-ec2" "3.863.0"
|
||||
"@aws-sdk/client-eks" "3.879.0"
|
||||
@@ -2729,7 +2653,7 @@
|
||||
"@babel/preset-typescript" "7.16.7"
|
||||
"@novnc/novnc" "1.2.0"
|
||||
"@popperjs/core" "2.11.8"
|
||||
"@rancher/icons" "2.0.54"
|
||||
"@rancher/icons" "2.0.55"
|
||||
"@smithy/fetch-http-handler" "5.1.1"
|
||||
"@types/is-url" "1.2.30"
|
||||
"@types/node" "20.10.8"
|
||||
@@ -2758,7 +2682,7 @@
|
||||
cookie-universal "2.2.2"
|
||||
core-js "3.45.0"
|
||||
cron-validator "1.4.0"
|
||||
cronstrue "2.53.0"
|
||||
cronstrue "3.9.0"
|
||||
cross-env "7.0.3"
|
||||
css-loader "6.7.3"
|
||||
csv-loader "3.0.3"
|
||||
@@ -2767,7 +2691,7 @@
|
||||
d3 "7.3.0"
|
||||
d3-selection "3.0.0"
|
||||
dayjs "1.11.18"
|
||||
defu "5.0.1"
|
||||
defu "6.1.4"
|
||||
diff2html "3.4.24"
|
||||
dompurify "3.2.5"
|
||||
element-matches "^0.1.2"
|
||||
@@ -2802,7 +2726,7 @@
|
||||
jsonpath-plus "10.3.0"
|
||||
jsrsasign "11.0.0"
|
||||
jszip "3.10.1"
|
||||
lodash "4.17.21"
|
||||
lodash "4.17.23"
|
||||
marked "4.0.17"
|
||||
node-polyfill-webpack-plugin "3.0.0"
|
||||
nodemon "2.0.22"
|
||||
@@ -3505,10 +3429,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/lodash@4.17.23":
|
||||
version "4.17.23"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.23.tgz#c1bb06db218acc8fc232da0447473fc2fb9d9841"
|
||||
integrity sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==
|
||||
"@types/lodash@4.17.24":
|
||||
version "4.17.24"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.24.tgz#4ae334fc62c0e915ca8ed8e35dcc6d4eeb29215f"
|
||||
integrity sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.5"
|
||||
@@ -3528,9 +3452,9 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@20.10.8", "@types/node@^14.14.31", "@types/node@~20.19.0":
|
||||
version "20.19.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.30.tgz#84fa87498ade5cd2b6ba8f8eec01d3b138ca60d0"
|
||||
integrity sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==
|
||||
version "20.19.37"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.37.tgz#b4fb4033408dd97becce63ec932c9ec57a9e2919"
|
||||
integrity sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==
|
||||
dependencies:
|
||||
undici-types "~6.21.0"
|
||||
|
||||
@@ -3635,6 +3559,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
|
||||
integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==
|
||||
|
||||
"@types/web-bluetooth@^0.0.20":
|
||||
version "0.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597"
|
||||
integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==
|
||||
|
||||
"@types/webpack-env@^1.15.2":
|
||||
version "1.18.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.5.tgz#eccda0b04fe024bed505881e2e532f9c119169bf"
|
||||
@@ -3796,6 +3725,35 @@
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@vue-flow/background@^1.3.0":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@vue-flow/background/-/background-1.3.2.tgz#0c90cd05e5d60da017bbaf5a1c3eb6af7ed9b778"
|
||||
integrity sha512-eJPhDcLj1wEo45bBoqTXw1uhl0yK2RaQGnEINqvvBsAFKh/camHJd5NPmOdS1w+M9lggc9igUewxaEd3iCQX2w==
|
||||
|
||||
"@vue-flow/controls@^1.1.1":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@vue-flow/controls/-/controls-1.1.3.tgz#40866b553101fbef22d2b9a043965ed76fca4b2c"
|
||||
integrity sha512-XCf+G+jCvaWURdFlZmOjifZGw3XMhN5hHlfMGkWh9xot+9nH9gdTZtn+ldIJKtarg3B21iyHU8JjKDhYcB6JMw==
|
||||
|
||||
"@vue-flow/core@^1.33.5":
|
||||
version "1.48.2"
|
||||
resolved "https://registry.yarnpkg.com/@vue-flow/core/-/core-1.48.2.tgz#cef8641b17f6220c257d4208bdb2082cee882225"
|
||||
integrity sha512-raxhgKWE+G/mcEvXJjGFUDYW9rAI3GOtiHR3ZkNpwBWuIaCC1EYiBmKGwJOoNzVFgwO7COgErnK7i08i287AFA==
|
||||
dependencies:
|
||||
"@vueuse/core" "^10.5.0"
|
||||
d3-drag "^3.0.0"
|
||||
d3-interpolate "^3.0.1"
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
|
||||
"@vue-flow/minimap@^1.4.0":
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@vue-flow/minimap/-/minimap-1.5.4.tgz#c9c3badea49d4166aa9cdc713017397d9df7574c"
|
||||
integrity sha512-l4C+XTAXnRxsRpUdN7cAVFBennC1sVRzq4bDSpVK+ag7tdMczAnhFYGgbLkUw3v3sY6gokyWwMl8CDonp8eB2g==
|
||||
dependencies:
|
||||
d3-selection "^3.0.0"
|
||||
d3-zoom "^3.0.0"
|
||||
|
||||
"@vue/babel-helper-vue-jsx-merge-props@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz#8d53a1e21347db8edbe54d339902583176de09f2"
|
||||
@@ -4191,6 +4149,28 @@
|
||||
resolved "https://registry.yarnpkg.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz#b6b40a7625429d2bd7c2281ddba601ed05dc7f1a"
|
||||
integrity sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==
|
||||
|
||||
"@vueuse/core@^10.5.0":
|
||||
version "10.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.11.1.tgz#15d2c0b6448d2212235b23a7ba29c27173e0c2c6"
|
||||
integrity sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==
|
||||
dependencies:
|
||||
"@types/web-bluetooth" "^0.0.20"
|
||||
"@vueuse/metadata" "10.11.1"
|
||||
"@vueuse/shared" "10.11.1"
|
||||
vue-demi ">=0.14.8"
|
||||
|
||||
"@vueuse/metadata@10.11.1":
|
||||
version "10.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.11.1.tgz#209db7bb5915aa172a87510b6de2ca01cadbd2a7"
|
||||
integrity sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==
|
||||
|
||||
"@vueuse/shared@10.11.1":
|
||||
version "10.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.11.1.tgz#62b84e3118ae6e1f3ff38f4fbe71b0c5d0f10938"
|
||||
integrity sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==
|
||||
dependencies:
|
||||
vue-demi ">=0.14.8"
|
||||
|
||||
"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
|
||||
@@ -4755,7 +4735,7 @@ axios-retry@3.1.9:
|
||||
dependencies:
|
||||
is-retry-allowed "^1.1.0"
|
||||
|
||||
axios@1.13.2:
|
||||
axios@1.13.2, axios@^1.7.9:
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.2.tgz#9ada120b7b5ab24509553ec3e40123521117f687"
|
||||
integrity sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==
|
||||
@@ -4764,15 +4744,6 @@ axios@1.13.2:
|
||||
form-data "^4.0.4"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
axios@^1.7.9:
|
||||
version "1.12.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7"
|
||||
integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.6"
|
||||
form-data "^4.0.4"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
babel-eslint@10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
|
||||
@@ -5160,17 +5131,7 @@ browserify-zlib@^0.2.0:
|
||||
dependencies:
|
||||
pako "~1.0.5"
|
||||
|
||||
browserslist@^4.0.0, browserslist@^4.16.3, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.23.1, browserslist@^4.23.3:
|
||||
version "4.23.3"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800"
|
||||
integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001646"
|
||||
electron-to-chromium "^1.5.4"
|
||||
node-releases "^2.0.18"
|
||||
update-browserslist-db "^1.1.0"
|
||||
|
||||
browserslist@^4.24.0:
|
||||
browserslist@^4.0.0, browserslist@^4.16.3, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.23.3, browserslist@^4.24.0:
|
||||
version "4.28.1"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95"
|
||||
integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==
|
||||
@@ -5337,12 +5298,7 @@ caniuse-api@^3.0.0:
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646:
|
||||
version "1.0.30001655"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz#0ce881f5a19a2dcfda2ecd927df4d5c1684b982f"
|
||||
integrity sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==
|
||||
|
||||
caniuse-lite@^1.0.30001759:
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001759:
|
||||
version "1.0.30001766"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz#b6f6b55cb25a2d888d9393104d14751c6a7d6f7a"
|
||||
integrity sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==
|
||||
@@ -5963,7 +5919,7 @@ cron-validator@1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.4.0.tgz#77ed4277b086c22e74ee65640f8456747afd4885"
|
||||
integrity sha512-wGcJ9FCy65iaU6egSH8b5dZYJF7GU/3Jh06wzaT9lsa5dbqExjljmu+0cJ8cpKn+vUyZa/EM4WAxeLR6SypJXw==
|
||||
|
||||
cronstrue@2.53.0, cronstrue@2.59.0:
|
||||
cronstrue@2.59.0, cronstrue@3.9.0:
|
||||
version "2.59.0"
|
||||
resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-2.59.0.tgz#a250b2b04eebabf35518725018e501ff94370fb1"
|
||||
integrity sha512-YKGmAy84hKH+hHIIER07VCAHf9u0Ldelx1uU6EBxsRPDXIA1m5fsKmJfyC3xBhw6cVC/1i83VdbL4PvepTrt8A==
|
||||
@@ -6273,7 +6229,7 @@ d3-delaunay@6:
|
||||
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
|
||||
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
|
||||
|
||||
"d3-drag@2 - 3", d3-drag@3:
|
||||
"d3-drag@2 - 3", d3-drag@3, d3-drag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
|
||||
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
|
||||
@@ -6328,7 +6284,7 @@ d3-hierarchy@3:
|
||||
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6"
|
||||
integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==
|
||||
|
||||
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3:
|
||||
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3, d3-interpolate@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
|
||||
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
|
||||
@@ -6374,7 +6330,7 @@ d3-scale@4:
|
||||
d3-time "2.1.1 - 3"
|
||||
d3-time-format "2 - 4"
|
||||
|
||||
"d3-selection@2 - 3", d3-selection@3, d3-selection@3.0.0:
|
||||
"d3-selection@2 - 3", d3-selection@3, d3-selection@3.0.0, d3-selection@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
|
||||
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
|
||||
@@ -6416,7 +6372,7 @@ d3-shape@3:
|
||||
d3-interpolate "1 - 3"
|
||||
d3-timer "1 - 3"
|
||||
|
||||
d3-zoom@3:
|
||||
d3-zoom@3, d3-zoom@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
|
||||
integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
|
||||
@@ -6616,10 +6572,10 @@ define-properties@^1.1.3, define-properties@^1.2.1:
|
||||
has-property-descriptors "^1.0.0"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
defu@5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/defu/-/defu-5.0.1.tgz#a034278f9b032bf0845d261aa75e9ad98da878ac"
|
||||
integrity sha512-EPS1carKg+dkEVy3qNTqIdp2qV7mUP08nIsupfwQpz++slCVRw7qbQyWvSTig+kFPwz2XXp5/kIIkH+CwrJKkQ==
|
||||
defu@6.1.4:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
|
||||
integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
|
||||
|
||||
delaunator@5:
|
||||
version "5.0.1"
|
||||
@@ -6878,16 +6834,16 @@ electron-to-chromium@^1.5.263:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.278.tgz#807a5e321f012a41bfd64e653f35993c9af95493"
|
||||
integrity sha512-dQ0tM1svDRQOwxnXxm+twlGTjr9Upvt8UFWAgmLsxEzFQxhbti4VwxmMjsDxVC51Zo84swW7FVCXEV+VAkhuPw==
|
||||
|
||||
electron-to-chromium@^1.5.4:
|
||||
version "1.5.13"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6"
|
||||
integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==
|
||||
|
||||
element-matches@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/element-matches/-/element-matches-0.1.2.tgz#7345cb71e965bd2b12f725e524591c102198361a"
|
||||
integrity sha512-yWh1otcs3OKUWDvu/IxyI36ZI3WNaRZlI0uG/DK6fu0pap0VYZ0J5pEGTk1zakme+hT0OKHwhlHc0N5TJhY6yQ==
|
||||
|
||||
elkjs@^0.11.0:
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.11.1.tgz#d27fcdbbf5a8aeeff80420d17d1666f78cfc8544"
|
||||
integrity sha512-zxxR9k+rx5ktMwT/FwyLdPCrq7xN6e4VGGHH8hA01vVYKjTFik7nHOxBnAYtrgYUB1RpAiLvA1/U2YraWxyKKg==
|
||||
|
||||
elliptic@^6.5.3, elliptic@^6.5.5:
|
||||
version "6.5.7"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b"
|
||||
@@ -7086,7 +7042,7 @@ es6-error@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
|
||||
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
|
||||
|
||||
escalade@^3.1.1, escalade@^3.1.2, escalade@^3.2.0:
|
||||
escalade@^3.1.1, escalade@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||
@@ -9614,7 +9570,7 @@ js-yaml-loader@1.2.2:
|
||||
loader-utils "^1.2.3"
|
||||
un-eval "^1.2.0"
|
||||
|
||||
js-yaml@4.1.1:
|
||||
js-yaml@4.1.1, js-yaml@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
|
||||
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
|
||||
@@ -9629,13 +9585,6 @@ js-yaml@^3.13.1:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jsbn@~0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
@@ -10052,10 +10001,10 @@ lodash.upperfirst@^4.3.1:
|
||||
resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce"
|
||||
integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==
|
||||
|
||||
lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
lodash@4.17.23, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
|
||||
version "4.17.23"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a"
|
||||
integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==
|
||||
|
||||
log-symbols@^4.0.0, log-symbols@^4.1.0:
|
||||
version "4.1.0"
|
||||
@@ -10509,11 +10458,6 @@ node-preload@^0.2.1:
|
||||
dependencies:
|
||||
process-on-spawn "^1.0.0"
|
||||
|
||||
node-releases@^2.0.18:
|
||||
version "2.0.18"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
|
||||
integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
|
||||
|
||||
node-releases@^2.0.27:
|
||||
version "2.0.27"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e"
|
||||
@@ -11544,10 +11488,10 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
qs@6.11.0, qs@6.14.1, qs@6.7.0, qs@^6.12.3, qs@~6.10.3:
|
||||
version "6.14.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.1.tgz#a41d85b9d3902f31d27861790506294881871159"
|
||||
integrity sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==
|
||||
qs@6.11.0, qs@6.15.0, qs@6.7.0, qs@^6.12.3, qs@~6.10.3:
|
||||
version "6.15.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.0.tgz#db8fd5d1b1d2d6b5b33adaf87429805f1909e7b3"
|
||||
integrity sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==
|
||||
dependencies:
|
||||
side-channel "^1.1.0"
|
||||
|
||||
@@ -11826,16 +11770,7 @@ resolve.exports@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999"
|
||||
integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==
|
||||
|
||||
resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.4:
|
||||
version "1.22.8"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
|
||||
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
|
||||
dependencies:
|
||||
is-core-module "^2.13.0"
|
||||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
resolve@^1.22.8:
|
||||
resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.4, resolve@^1.22.8:
|
||||
version "1.22.11"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262"
|
||||
integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==
|
||||
@@ -12043,10 +11978,10 @@ semver-compare@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@7.7.3, semver@^5.5.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@~7.0.0:
|
||||
version "7.7.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946"
|
||||
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
||||
"semver@2 || 3 || 4 || 5", semver@7.7.4, semver@^5.5.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@~7.0.0:
|
||||
version "7.7.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a"
|
||||
integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
|
||||
|
||||
send@0.17.1:
|
||||
version "0.17.1"
|
||||
@@ -13215,14 +13150,6 @@ untildify@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
|
||||
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
|
||||
|
||||
update-browserslist-db@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e"
|
||||
integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==
|
||||
dependencies:
|
||||
escalade "^3.1.2"
|
||||
picocolors "^1.0.1"
|
||||
|
||||
update-browserslist-db@^1.2.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d"
|
||||
@@ -13336,6 +13263,11 @@ vue-component-type-helpers@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/vue-component-type-helpers/-/vue-component-type-helpers-2.2.0.tgz#de5fa802b6beae7125595ec0d3d5195a22691623"
|
||||
integrity sha512-cYrAnv2me7bPDcg9kIcGwjJiSB6Qyi08+jLDo9yuvoFQjzHiPTzML7RnkJB1+3P6KMsX/KbCD4QE3Tv/knEllw==
|
||||
|
||||
vue-demi@>=0.14.8:
|
||||
version "0.14.10"
|
||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
|
||||
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
|
||||
|
||||
vue-draggable-next@^2.2.1:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-draggable-next/-/vue-draggable-next-2.3.0.tgz#ba83154f60b8a3c24059c18b8060b72200a4c673"
|
||||
|
||||
Reference in New Issue
Block a user