Merge branch 'main' into issue-7328

This commit is contained in:
Yi-Ya Chen 2025-02-11 17:51:07 +08:00
commit 2493287334
No known key found for this signature in database
GPG Key ID: 9A2E6FBD33F68EDE
8 changed files with 106 additions and 11 deletions

View File

@ -12,6 +12,9 @@ import { NODE } from '@shell/config/types';
import { HCI } from '../../types'; import { HCI } from '../../types';
import { DOC } from '../../config/doc-links'; import { DOC } from '../../config/doc-links';
import { docLink } from '../../utils/feature-flags'; import { docLink } from '../../utils/feature-flags';
import { NETWORK_TYPE } from '../../config/types';
const { L2VLAN, UNTAGGED } = NETWORK_TYPE;
export default { export default {
name: 'HarvesterEditStorageNetwork', name: 'HarvesterEditStorageNetwork',
@ -57,11 +60,14 @@ export default {
data() { data() {
let parsedDefaultValue = {}; let parsedDefaultValue = {};
let openVlan = false; let openVlan = false;
let networkType = L2VLAN;
try { try {
parsedDefaultValue = JSON.parse(this.value.value); parsedDefaultValue = JSON.parse(this.value.value);
networkType = 'vlan' in parsedDefaultValue ? L2VLAN : UNTAGGED; // backend doesn't provide networkType, so we check if vlan is provided instead
openVlan = true; openVlan = true;
} catch (error) { } catch (error) {
networkType = L2VLAN;
parsedDefaultValue = { parsedDefaultValue = {
vlan: '', vlan: '',
clusterNetwork: '', clusterNetwork: '',
@ -73,6 +79,7 @@ export default {
return { return {
openVlan, openVlan,
networkType,
errors: [], errors: [],
exclude, exclude,
parsedDefaultValue, parsedDefaultValue,
@ -87,16 +94,35 @@ export default {
}, },
computed: { computed: {
showVlan() {
return this.networkType === L2VLAN;
},
networkTypes() {
const types = [L2VLAN];
if (this.untaggedNetworkSettingEnabled) {
types.push(UNTAGGED);
}
return types;
},
storageNetworkExampleLink() { storageNetworkExampleLink() {
const version = this.$store.getters['harvester-common/getServerVersion'](); const version = this.$store.getters['harvester-common/getServerVersion']();
return docLink(DOC.STORAGE_NETWORK_EXAMPLE, version); return docLink(DOC.STORAGE_NETWORK_EXAMPLE, version);
}, },
untaggedNetworkSettingEnabled() {
return this.$store.getters['harvester-common/getFeatureEnabled']('untaggedNetworkSetting');
},
clusterNetworkOptions() { clusterNetworkOptions() {
const inStore = this.$store.getters['currentProduct'].inStore; const inStore = this.$store.getters['currentProduct'].inStore;
const clusterNetworks = this.$store.getters[`${ inStore }/all`](HCI.CLUSTER_NETWORK) || []; const clusterNetworks = this.$store.getters[`${ inStore }/all`](HCI.CLUSTER_NETWORK) || [];
// untaggedNetwork filter out mgmt cluster network
const clusterNetworksOptions = this.networkType === UNTAGGED ? clusterNetworks.filter((net) => net.id !== 'mgmt') : clusterNetworks;
return clusterNetworks.map((n) => { return clusterNetworksOptions.map((n) => {
const disabled = !n.isReadyForStorageNetwork; const disabled = !n.isReadyForStorageNetwork;
return { return {
@ -108,7 +134,50 @@ export default {
}, },
}, },
watch: {
networkType: {
handler(neu) {
this.parsedDefaultValue.clusterNetwork = '';
if (neu === L2VLAN) {
this.parsedDefaultValue.vlan = '';
} else {
delete this.parsedDefaultValue.vlan;
}
},
deep: true
}
},
methods: { methods: {
inputVlan(neu) {
if (neu === '') {
this.parsedDefaultValue.vlan = '';
return;
}
const newValue = Number(neu);
if (newValue > 4094) {
this.parsedDefaultValue.vlan = 4094;
} else if (newValue < 1) {
this.parsedDefaultValue.vlan = 1;
} else {
this.parsedDefaultValue.vlan = newValue;
}
},
useDefault() {
this.openVlan = false;
this.networkType = L2VLAN;
this.parsedDefaultValue = {
vlan: '',
clusterNetwork: '',
range: '',
exclude: []
};
},
update() { update() {
const exclude = this.exclude.filter((ip) => ip); const exclude = this.exclude.filter((ip) => ip);
@ -138,7 +207,7 @@ export default {
errors.push(this.t('harvester.setting.storageNetwork.range.invalid', null, true)); errors.push(this.t('harvester.setting.storageNetwork.range.invalid', null, true));
} }
if (!this.parsedDefaultValue.vlan) { if (this.networkType === L2VLAN && !this.parsedDefaultValue.vlan) {
errors.push(this.t('validation.required', { key: this.t('harvester.setting.storageNetwork.vlan') }, true)); errors.push(this.t('validation.required', { key: this.t('harvester.setting.storageNetwork.vlan') }, true));
} }
@ -191,13 +260,25 @@ export default {
/> />
<div v-if="openVlan"> <div v-if="openVlan">
<LabeledSelect
v-model:value="networkType"
class="mb-20"
:options="networkTypes"
:mode="mode"
:label="t('harvester.fields.type')"
required
/>
<LabeledInput <LabeledInput
v-if="showVlan"
v-model:value.number="parsedDefaultValue.vlan" v-model:value.number="parsedDefaultValue.vlan"
type="number" type="number"
class="mb-20" class="mb-20"
:mode="mode" :mode="mode"
required required
placeholder="e.g. 1 - 4094"
label-key="harvester.setting.storageNetwork.vlan" label-key="harvester.setting.storageNetwork.vlan"
@update:value="inputVlan"
/> />
<LabeledSelect <LabeledSelect

View File

@ -49,6 +49,7 @@ const featuresV142 = [
const featuresV150 = [ const featuresV150 = [
...featuresV142, ...featuresV142,
'tpmPersistentState', 'tpmPersistentState',
'untaggedNetworkSetting',
'skipSingleReplicaDetachedVol' 'skipSingleReplicaDetachedVol'
]; ];

View File

@ -65,7 +65,9 @@ export const HCI_ALLOWED_SETTINGS = {
[HCI_SETTING.SUPPORT_BUNDLE_EXPIRATION]: {}, [HCI_SETTING.SUPPORT_BUNDLE_EXPIRATION]: {},
[HCI_SETTING.SUPPORT_BUNDLE_NODE_COLLECTION_TIMEOUT]: { featureFlag: 'supportBundleNodeCollectionTimeoutSetting' }, [HCI_SETTING.SUPPORT_BUNDLE_NODE_COLLECTION_TIMEOUT]: { featureFlag: 'supportBundleNodeCollectionTimeoutSetting' },
[HCI_SETTING.SUPPORT_BUNDLE_IMAGE]: { kind: 'json', from: 'import' }, [HCI_SETTING.SUPPORT_BUNDLE_IMAGE]: { kind: 'json', from: 'import' },
[HCI_SETTING.STORAGE_NETWORK]: { kind: 'custom', from: 'import' }, [HCI_SETTING.STORAGE_NETWORK]: {
kind: 'custom', from: 'import', canReset: true
},
[HCI_SETTING.VM_FORCE_RESET_POLICY]: { kind: 'json', from: 'import' }, [HCI_SETTING.VM_FORCE_RESET_POLICY]: { kind: 'json', from: 'import' },
[HCI_SETTING.SSL_CERTIFICATES]: { kind: 'json', from: 'import' }, [HCI_SETTING.SSL_CERTIFICATES]: { kind: 'json', from: 'import' },
[HCI_SETTING.SSL_PARAMETERS]: { [HCI_SETTING.SSL_PARAMETERS]: {

View File

@ -2,3 +2,8 @@ export const BACKUP_TYPE = {
BACKUP: 'backup', BACKUP: 'backup',
SNAPSHOT: 'snapshot' SNAPSHOT: 'snapshot'
}; };
export const NETWORK_TYPE = {
L2VLAN: 'L2VlanNetwork',
UNTAGGED: 'UntaggedNetwork'
};

View File

@ -11,6 +11,9 @@ import { HCI as HCI_LABELS_ANNOTATIONS } from '@pkg/harvester/config/labels-anno
import CreateEditView from '@shell/mixins/create-edit-view'; import CreateEditView from '@shell/mixins/create-edit-view';
import { allHash } from '@shell/utils/promise'; import { allHash } from '@shell/utils/promise';
import { HCI } from '../types'; import { HCI } from '../types';
import { NETWORK_TYPE } from '../config/types';
const { L2VLAN, UNTAGGED } = NETWORK_TYPE;
const AUTO = 'auto'; const AUTO = 'auto';
const MANUAL = 'manual'; const MANUAL = 'manual';
@ -48,7 +51,7 @@ export default {
config.bridge = config.bridge.slice(0, -3); config.bridge = config.bridge.slice(0, -3);
} }
const type = this.value.vlanType || 'L2VlanNetwork' ; const type = this.value.vlanType || L2VLAN ;
return { return {
config, config,
@ -101,15 +104,15 @@ export default {
}, },
networkType() { networkType() {
return ['L2VlanNetwork', 'UntaggedNetwork']; return [L2VLAN, UNTAGGED];
}, },
isUntaggedNetwork() { isUntaggedNetwork() {
if (this.isView) { if (this.isView) {
return this.value.vlanType === 'UntaggedNetwork'; return this.value.vlanType === UNTAGGED;
} }
return this.type === 'UntaggedNetwork'; return this.type === UNTAGGED;
} }
}, },

View File

@ -249,7 +249,7 @@ export default {
:searchable="searchable" :searchable="searchable"
:disabled="disabled" :disabled="disabled"
:options="sshOption" :options="sshOption"
@update:value="update" @input="update"
/> />
<ModalWithCard <ModalWithCard

View File

@ -1028,7 +1028,7 @@ harvester:
invalid: '"Exclude list" is invalid.' invalid: '"Exclude list" is invalid.'
addIp: Add Exclude IP addIp: Add Exclude IP
warning: 'WARNING: <br/> Any change to storage-network requires shutting down all virtual machines before applying this setting. <br/> Users have to ensure the cluster network is configured and VLAN Configuration will cover all nodes and ensure the network connectivity is working and expected in all nodes.' warning: 'WARNING: <br/> Any change to storage-network requires shutting down all virtual machines before applying this setting. <br/> Users have to ensure the cluster network is configured and VLAN Configuration will cover all nodes and ensure the network connectivity is working and expected in all nodes.'
tip: 'Specify an IP range in the IPv4 CIDR format. <code>Number of IPs Required = Number of Nodes * 4 + 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>.' 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: vmForceDeletionPolicy:
period: Period period: Period
ratio : Ratio ratio : Ratio

View File

@ -1,5 +1,8 @@
import SteveModel from '@shell/plugins/steve/steve-class'; import SteveModel from '@shell/plugins/steve/steve-class';
import { HCI } from '@shell/config/labels-annotations'; import { HCI } from '@shell/config/labels-annotations';
import { NETWORK_TYPE } from '../config/types';
const { UNTAGGED } = NETWORK_TYPE;
export default class NetworkAttachmentDef extends SteveModel { export default class NetworkAttachmentDef extends SteveModel {
applyDefaults() { applyDefaults() {
@ -42,7 +45,7 @@ export default class NetworkAttachmentDef extends SteveModel {
} }
get vlanId() { get vlanId() {
return this.vlanType === 'UntaggedNetwork' ? 'N/A' : this.parseConfig.vlan; return this.vlanType === UNTAGGED ? 'N/A' : this.parseConfig.vlan;
} }
get customValidationRules() { get customValidationRules() {
@ -65,7 +68,7 @@ export default class NetworkAttachmentDef extends SteveModel {
const route = annotations[HCI.NETWORK_ROUTE]; const route = annotations[HCI.NETWORK_ROUTE];
let config = {}; let config = {};
if (this.vlanType === 'UntaggedNetwork') { if (this.vlanType === UNTAGGED) {
return 'N/A'; return 'N/A';
} }