mirror of https://github.com/rancher/ui.git
support multi nic
This commit is contained in:
parent
9d02902073
commit
5f59400e9e
|
|
@ -0,0 +1,40 @@
|
||||||
|
import Component from '@ember/component';
|
||||||
|
import layout from './template';
|
||||||
|
import { inject as service } from '@ember/service'
|
||||||
|
import { get, computed } from '@ember/object';
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
scope: service(),
|
||||||
|
session: service(),
|
||||||
|
|
||||||
|
layout,
|
||||||
|
model: null,
|
||||||
|
idx: '',
|
||||||
|
disk: {},
|
||||||
|
disks: [],
|
||||||
|
|
||||||
|
bootOrderContent: computed('disk.bootOrder', 'disks.@each.bootOrder', 'idx', function() {
|
||||||
|
let bootOrderContent = [];
|
||||||
|
const bootOrder = get(this, 'disk').bootOrder;
|
||||||
|
const bootOrders = get(this, 'disks').map((disk) => {
|
||||||
|
return disk.bootOrder;
|
||||||
|
})
|
||||||
|
|
||||||
|
const disks = get(this, 'disks') || [];
|
||||||
|
const idx = get(this, 'idx');
|
||||||
|
|
||||||
|
for (let i = 0; i < disks.length + 1; i++) {
|
||||||
|
if (!bootOrders.includes(i) || i === 0 || i === bootOrder) {
|
||||||
|
if (!(idx === 0 && i === 0)) {
|
||||||
|
bootOrderContent.push({
|
||||||
|
label: i === 0 ? 'N/A' : `${ i }`,
|
||||||
|
value: i
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return bootOrderContent
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<SearchableSelect
|
||||||
|
@class="form-control"
|
||||||
|
@content={{bootOrderContent}}
|
||||||
|
@value={{disk.bootOrder}}
|
||||||
|
@placeholder={{t "nodeDriver.harvester.storageClass.placeholder"}}
|
||||||
|
/>
|
||||||
|
|
@ -48,22 +48,26 @@ export default Component.extend(NodeDriver, {
|
||||||
driverName: DRIVER,
|
driverName: DRIVER,
|
||||||
model: {},
|
model: {},
|
||||||
|
|
||||||
currentCluster: null,
|
currentCluster: null,
|
||||||
clusters: [],
|
clusters: [],
|
||||||
clusterContent: [],
|
clusterContent: [],
|
||||||
imageContent: [],
|
imageContent: [],
|
||||||
networkContent: [],
|
networkContent: [],
|
||||||
namespaceContent: [],
|
namespaceContent: [],
|
||||||
nodes: [],
|
nodes: [],
|
||||||
namespaces: [],
|
namespaces: [],
|
||||||
nodeSchedulings: [],
|
nodeSchedulings: [],
|
||||||
podSchedulings: [],
|
podSchedulings: [],
|
||||||
networkDataContent: [],
|
networkDataContent: [],
|
||||||
userDataContent: [],
|
storageClassContent: [],
|
||||||
controller: null,
|
defaultStorageClass: '',
|
||||||
signal: '',
|
userDataContent: [],
|
||||||
isImportMode: true,
|
controller: null,
|
||||||
loading: false,
|
signal: '',
|
||||||
|
isImportMode: true,
|
||||||
|
loading: false,
|
||||||
|
disks: [],
|
||||||
|
interfaces: [],
|
||||||
|
|
||||||
config: alias(`model.${ CONFIG }`),
|
config: alias(`model.${ CONFIG }`),
|
||||||
|
|
||||||
|
|
@ -78,6 +82,10 @@ export default Component.extend(NodeDriver, {
|
||||||
if (!!get(this, 'config.vmAffinity')) {
|
if (!!get(this, 'config.vmAffinity')) {
|
||||||
this.initSchedulings();
|
this.initSchedulings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.initDisks()
|
||||||
|
|
||||||
|
this.initInterfaces()
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
@ -99,10 +107,47 @@ export default Component.extend(NodeDriver, {
|
||||||
this.get('nodeSchedulings').pushObject(neu);
|
this.get('nodeSchedulings').pushObject(neu);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addVolume(type) {
|
||||||
|
let neu = {}
|
||||||
|
|
||||||
|
if (type === 'volume') {
|
||||||
|
neu = {
|
||||||
|
storageClassName: get(this, 'defaultStorageClass'),
|
||||||
|
size: 10,
|
||||||
|
bootOrder: 0
|
||||||
|
};
|
||||||
|
} else if (type === 'image') {
|
||||||
|
neu = {
|
||||||
|
imageName: '',
|
||||||
|
size: 40,
|
||||||
|
bootOrder: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get('disks').pushObject(neu);
|
||||||
|
},
|
||||||
|
|
||||||
|
addNetwork() {
|
||||||
|
const neu = {
|
||||||
|
networkName: '',
|
||||||
|
macAddress: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get('interfaces').pushObject(neu);
|
||||||
|
},
|
||||||
|
|
||||||
removeNodeScheduling(scheduling) {
|
removeNodeScheduling(scheduling) {
|
||||||
this.get('nodeSchedulings').removeObject(scheduling);
|
this.get('nodeSchedulings').removeObject(scheduling);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeDisk(disk) {
|
||||||
|
this.get('disks').removeObject(disk);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeNetwork(network) {
|
||||||
|
this.get('interfaces').removeObject(network);
|
||||||
|
},
|
||||||
|
|
||||||
updateNodeScheduling() {
|
updateNodeScheduling() {
|
||||||
this.parseNodeScheduling();
|
this.parseNodeScheduling();
|
||||||
},
|
},
|
||||||
|
|
@ -124,7 +169,7 @@ export default Component.extend(NodeDriver, {
|
||||||
|
|
||||||
updatePodScheduling() {
|
updatePodScheduling() {
|
||||||
this.parsePodScheduling();
|
this.parsePodScheduling();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
clearData: observer('currentCredential.id', function() {
|
clearData: observer('currentCredential.id', function() {
|
||||||
|
|
@ -135,6 +180,31 @@ export default Component.extend(NodeDriver, {
|
||||||
set(this, 'podSchedulings', []);
|
set(this, 'podSchedulings', []);
|
||||||
set(this, 'vmAffinity', {});
|
set(this, 'vmAffinity', {});
|
||||||
set(this, 'config.vmAffinity', '');
|
set(this, 'config.vmAffinity', '');
|
||||||
|
set(this, 'config.diskInfo', '');
|
||||||
|
set(this, 'config.networkInfo', '');
|
||||||
|
|
||||||
|
this.initDisks()
|
||||||
|
|
||||||
|
this.initInterfaces()
|
||||||
|
}),
|
||||||
|
|
||||||
|
setDiskInfo: observer('disks.@each.{imageName,bootOrder,storageClassName,size}', function() {
|
||||||
|
const diskInfo = {
|
||||||
|
disks: get(this, 'disks').map((disk) => {
|
||||||
|
return {
|
||||||
|
...disk,
|
||||||
|
size: Number(disk.size),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
set(this, 'config.diskInfo', JSON.stringify(diskInfo));
|
||||||
|
}),
|
||||||
|
|
||||||
|
setNetworkInfo: observer('interfaces.@each.{networkName,macAddress}', function() {
|
||||||
|
const networkInfo = { interfaces: get(this, 'interfaces') };
|
||||||
|
|
||||||
|
set(this, 'config.networkInfo', JSON.stringify(networkInfo))
|
||||||
}),
|
}),
|
||||||
|
|
||||||
nodeSchedulingsChanged: observer('nodeSchedulings.[]', function() {
|
nodeSchedulingsChanged: observer('nodeSchedulings.[]', function() {
|
||||||
|
|
@ -256,10 +326,15 @@ export default Component.extend(NodeDriver, {
|
||||||
})
|
})
|
||||||
|
|
||||||
const storageClass = resp.storageClass.body.data || [];
|
const storageClass = resp.storageClass.body.data || [];
|
||||||
const storageClassContent = storageClass.map((s) => {
|
let defaultStorageClass = '';
|
||||||
|
const storageClassContent = storageClass.filter((s) => !s.parameters?.backingImage).map((s) => {
|
||||||
const isDefault = s.metadata?.annotations?.['storageclass.kubernetes.io/is-default-class'] === 'true';
|
const isDefault = s.metadata?.annotations?.['storageclass.kubernetes.io/is-default-class'] === 'true';
|
||||||
const label = isDefault ? `${ s.metadata.name } (${ this.intl.t('generic.default') })` : s.metadata.name;
|
const label = isDefault ? `${ s.metadata.name } (${ this.intl.t('generic.default') })` : s.metadata.name;
|
||||||
|
|
||||||
|
if (isDefault) {
|
||||||
|
defaultStorageClass = s.metadata.name;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label,
|
label,
|
||||||
value: s.metadata.name,
|
value: s.metadata.name,
|
||||||
|
|
@ -272,7 +347,8 @@ export default Component.extend(NodeDriver, {
|
||||||
namespaceContent,
|
namespaceContent,
|
||||||
userDataContent,
|
userDataContent,
|
||||||
networkDataContent,
|
networkDataContent,
|
||||||
storageClassContent
|
storageClassContent,
|
||||||
|
defaultStorageClass
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
setProperties(this, {
|
setProperties(this, {
|
||||||
|
|
@ -339,7 +415,9 @@ export default Component.extend(NodeDriver, {
|
||||||
networkData: '',
|
networkData: '',
|
||||||
vmNamespace: '',
|
vmNamespace: '',
|
||||||
userData: '',
|
userData: '',
|
||||||
vmAffinity: ''
|
vmAffinity: '',
|
||||||
|
diskInfo: '',
|
||||||
|
networkInfo: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
set(this, `model.${ CONFIG }`, config);
|
set(this, `model.${ CONFIG }`, config);
|
||||||
|
|
@ -357,24 +435,14 @@ export default Component.extend(NodeDriver, {
|
||||||
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.namespace.label') }));
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.namespace.label') }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get(this, 'config.diskBus')) {
|
|
||||||
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.diskBus.label') }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get(this, 'config.imageName')) {
|
|
||||||
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.imageName.label') }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get(this, 'config.networkName')) {
|
|
||||||
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.networkName.label') }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get(this, 'config.sshUser')) {
|
if (!get(this, 'config.sshUser')) {
|
||||||
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.sshUser.label') }));
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.sshUser.label') }));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.validateScheduling(errors);
|
this.validateScheduling(errors);
|
||||||
|
|
||||||
|
this.validateDiskAndNetwork(errors);
|
||||||
|
|
||||||
// Set the array of errors for display,
|
// Set the array of errors for display,
|
||||||
// and return true if saving should continue.
|
// and return true if saving should continue.
|
||||||
|
|
||||||
|
|
@ -411,6 +479,10 @@ export default Component.extend(NodeDriver, {
|
||||||
&& Object.getPrototypeOf(obj) === Object.prototype;
|
&& Object.getPrototypeOf(obj) === Object.prototype;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isImageVolume(volume) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(volume, 'imageName');
|
||||||
|
},
|
||||||
|
|
||||||
initSchedulings() {
|
initSchedulings() {
|
||||||
const nodeSchedulings = [];
|
const nodeSchedulings = [];
|
||||||
const podSchedulings = [];
|
const podSchedulings = [];
|
||||||
|
|
@ -496,6 +568,59 @@ export default Component.extend(NodeDriver, {
|
||||||
set(this, 'podSchedulings', podSchedulings);
|
set(this, 'podSchedulings', podSchedulings);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initDisks() {
|
||||||
|
let disks = [];
|
||||||
|
|
||||||
|
if (!get(this, 'config.diskInfo')) {
|
||||||
|
const imageName = get(this, 'config.imageName') || '';
|
||||||
|
|
||||||
|
disks = [{
|
||||||
|
imageName,
|
||||||
|
bootOrder: 1,
|
||||||
|
size: 40,
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (get(this, 'config.diskBus')) {
|
||||||
|
disks[0].bus = get(this, 'config.diskBus');
|
||||||
|
}
|
||||||
|
|
||||||
|
const diskInfo = JSON.stringify({ disks });
|
||||||
|
|
||||||
|
set(this, 'config.diskInfo', diskInfo);
|
||||||
|
} else {
|
||||||
|
const diskInfo = get(this, 'config.diskInfo');
|
||||||
|
|
||||||
|
disks = JSON.parse(diskInfo).disks || [];
|
||||||
|
}
|
||||||
|
set(this, 'disks', disks);
|
||||||
|
},
|
||||||
|
|
||||||
|
initInterfaces() {
|
||||||
|
let _interfaces = [];
|
||||||
|
|
||||||
|
if (!get(this, 'config.networkInfo')) {
|
||||||
|
const networkName = get(this, 'config.networkName') || '';
|
||||||
|
|
||||||
|
_interfaces = [{
|
||||||
|
networkName,
|
||||||
|
macAddress: '',
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (get(this, 'config.networkModel')) {
|
||||||
|
_interfaces[0].model = get(this, 'config.networkModel');
|
||||||
|
}
|
||||||
|
|
||||||
|
const networkInfo = JSON.stringify({ interfaces: _interfaces });
|
||||||
|
|
||||||
|
set(this, 'config.networkInfo', networkInfo);
|
||||||
|
} else {
|
||||||
|
const networkInfo = get(this, 'config.networkInfo');
|
||||||
|
|
||||||
|
_interfaces = JSON.parse(networkInfo).interfaces || [];
|
||||||
|
}
|
||||||
|
set(this, 'interfaces', _interfaces);
|
||||||
|
},
|
||||||
|
|
||||||
parseNodeScheduling() {
|
parseNodeScheduling() {
|
||||||
const arr = this.nodeSchedulings;
|
const arr = this.nodeSchedulings;
|
||||||
const out = {};
|
const out = {};
|
||||||
|
|
@ -633,6 +758,43 @@ export default Component.extend(NodeDriver, {
|
||||||
if (nodeHasMissingKey || podHasMissingKey) {
|
if (nodeHasMissingKey || podHasMissingKey) {
|
||||||
errors.push(this.intl.t('generic.required', { key: this.intl.t('formNodeRequirement.key.label') }));
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('formNodeRequirement.key.label') }));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
isValidMac(value) {
|
||||||
|
return /^[A-Fa-f0-9]{2}(-[A-Fa-f0-9]{2}){5}$|^[A-Fa-f0-9]{2}(:[A-Fa-f0-9]{2}){5}$/.test(value);
|
||||||
|
},
|
||||||
|
|
||||||
|
validateDiskAndNetwork(errors) {
|
||||||
|
const disks = get(this, 'disks');
|
||||||
|
|
||||||
|
disks.forEach((disk) => {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(disk, 'imageName') && !disk.imageName) {
|
||||||
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.imageName.label') }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(disk, 'storageClassName') && !disk.storageClassName) {
|
||||||
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.storageClass.label') }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!disk.size) {
|
||||||
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.diskSize.label') }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!disk.size) {
|
||||||
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.diskSize.label') }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const interfaces = get(this, 'interfaces');
|
||||||
|
|
||||||
|
interfaces.forEach((_interface) => {
|
||||||
|
if (!_interface.networkName) {
|
||||||
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.networkName.label') }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_interface.macAddress && !this.isValidMac(_interface.macAddress)) {
|
||||||
|
errors.push(this.intl.t('generic.required', { key: this.intl.t('nodeDriver.harvester.network.macFormat') }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -114,49 +114,159 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<label class="acc-label">
|
||||||
<label class="acc-label">
|
{{t "nodeDriver.harvester.disks.title"}}
|
||||||
{{t "nodeDriver.harvester.imageName.label"}}{{field-required}}
|
</label>
|
||||||
</label>
|
</div>
|
||||||
<SearchableSelect
|
{{#each disks as |disk idx|}}
|
||||||
@class="form-control"
|
<div class="box mb-10">
|
||||||
@content={{imageContent}}
|
<div class="row">
|
||||||
@value={{config.imageName}}
|
<div class="pull-left">
|
||||||
@placeholder={{t "nodeDriver.harvester.imageName.placeholder"}}
|
{{#if (has-property disk 'imageName') }}
|
||||||
/>
|
<h4>{{t 'nodeDriver.harvester.disks.diskType.imageVolume'}}</h4>
|
||||||
</div>
|
{{else}}
|
||||||
|
<h4>{{t 'nodeDriver.harvester.disks.diskType.volume'}}</h4>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<button class="btn bg-link icon-btn" type="button" disabled={{eq idx 0}} {{action "removeDisk" disk}}>
|
||||||
|
<i class="icon icon-minus text-small" />
|
||||||
|
<span>{{t "generic.remove" }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col span-6">
|
<div class="row">
|
||||||
<label class="acc-label">
|
<div class="col mt-0 span-6">
|
||||||
{{t "nodeDriver.harvester.diskSize.label"}}{{field-required}}
|
{{#if (has-property disk 'imageName') }}
|
||||||
</label>
|
<label class="acc-label">
|
||||||
<div class="input-group">
|
{{t "nodeDriver.harvester.imageName.label"}}{{field-required}}
|
||||||
{{input-integer
|
</label>
|
||||||
min=1
|
<SearchableSelect
|
||||||
value=config.diskSize
|
@class="form-control"
|
||||||
classNames="form-control"
|
@content={{imageContent}}
|
||||||
placeholder=(t "nodeDriver.harvester.diskSize.placeholder")
|
@value={{disk.imageName}}
|
||||||
}}
|
@placeholder={{t "nodeDriver.harvester.imageName.placeholder"}}
|
||||||
<div class="input-group-addon bg-default">
|
/>
|
||||||
{{t "nodeDriver.harvester.diskSize.unit"}}
|
{{else}}
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.harvester.storageClass.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
<SearchableSelect
|
||||||
|
@class="form-control"
|
||||||
|
@content={{storageClassContent}}
|
||||||
|
@value={{disk.storageClassName}}
|
||||||
|
@placeholder={{t "nodeDriver.harvester.storageClass.placeholder"}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col mt-0 span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.harvester.disks.bootOrder.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{{boot-order-select disk=disk disks=disks idx=idx}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.harvester.diskSize.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
<div class="input-group">
|
||||||
|
{{input-integer
|
||||||
|
min=1
|
||||||
|
value=disk.size
|
||||||
|
classNames="form-control"
|
||||||
|
placeholder=(t "nodeDriver.harvester.diskSize.placeholder")
|
||||||
|
}}
|
||||||
|
<div class="input-group-addon bg-default">
|
||||||
|
{{t "nodeDriver.harvester.diskSize.unit"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/each}}
|
||||||
|
|
||||||
|
<button class="btn bg-link icon-btn" type="button" {{action "addVolume" "volume" }}>
|
||||||
|
<i class="icon icon-plus text-small" />
|
||||||
|
<span>{{t "nodeDriver.harvester.disks.addVolume.volume"}}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn bg-link icon-btn" type="button" {{action "addVolume" "image"}}>
|
||||||
|
<i class="icon icon-plus text-small" />
|
||||||
|
<span>{{t "nodeDriver.harvester.disks.addVolume.imageVolume"}}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<hr class="mb-20 mt-20">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-6">
|
<label class="acc-label">
|
||||||
<label class="acc-label">
|
{{t "nodeDriver.harvester.network.title"}}
|
||||||
{{t "nodeDriver.harvester.networkName.label"}}{{field-required}}
|
</label>
|
||||||
</label>
|
|
||||||
<SearchableSelect
|
|
||||||
@class="form-control"
|
|
||||||
@content={{networkContent}}
|
|
||||||
@value={{config.networkName}}
|
|
||||||
@placeholder={{t "nodeDriver.harvester.networkName.placeholder"}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
{{#each interfaces as |network idx|}}
|
||||||
|
<div class="box mb-10">
|
||||||
|
<div class="row">
|
||||||
|
<div class="pull-left">
|
||||||
|
<h4>{{t "nodeDriver.harvester.network.label"}}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pull-right">
|
||||||
|
<button class="btn bg-link icon-btn" type="button" disabled={{eq idx 0}} {{action "removeNetwork" network}}>
|
||||||
|
<i class="icon icon-minus text-small" />
|
||||||
|
<span>{{t "generic.remove" }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col mt-0 span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.harvester.networkName.label"}}{{field-required}}
|
||||||
|
</label>
|
||||||
|
<SearchableSelect
|
||||||
|
@class="form-control"
|
||||||
|
@content={{networkContent}}
|
||||||
|
@value={{network.networkName}}
|
||||||
|
@placeholder={{t "nodeDriver.harvester.networkName.placeholder"}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col mt-0 span-6">
|
||||||
|
<label class="acc-label">
|
||||||
|
{{t "nodeDriver.harvester.macAddress.label"}}
|
||||||
|
<span class="inline-block">
|
||||||
|
{{#tooltip-element
|
||||||
|
type="tooltip-basic"
|
||||||
|
model=(t "nodeDriver.harvester.macAddress.toolTip" htmlSafe=true)
|
||||||
|
tooltipTemplate="tooltip-static"
|
||||||
|
aria-describedby="tooltip-base"
|
||||||
|
tooltipFor="tooltipPoolCreateAfter"
|
||||||
|
placement="top"
|
||||||
|
tagName="div"
|
||||||
|
}}
|
||||||
|
<i class="icon icon-help icon-blue"></i>
|
||||||
|
{{/tooltip-element}}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
{{input
|
||||||
|
type="text"
|
||||||
|
value=network.macAddress
|
||||||
|
classNames="form-control"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
<button class="btn bg-link icon-btn" type="button" {{action "addNetwork" }}>
|
||||||
|
<i class="icon icon-plus text-small" />
|
||||||
|
<span>{{ t "nodeDriver.harvester.network.addNetwork.network" }}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/accordion-list-item}}
|
{{/accordion-list-item}}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'nodes/components/boot-order-select/component';
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { helper } from '@ember/component/helper';
|
||||||
|
|
||||||
|
export function hasProperty(params) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(params[0], params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default helper(hasProperty);
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from 'shared/helpers/has-property';
|
||||||
|
|
@ -9773,6 +9773,9 @@ nodeDriver:
|
||||||
imageName:
|
imageName:
|
||||||
label: Image
|
label: Image
|
||||||
placeholder: Please select a image
|
placeholder: Please select a image
|
||||||
|
storageClass:
|
||||||
|
label: Storage Class
|
||||||
|
placeholder: Please select a storageClass
|
||||||
diskBus:
|
diskBus:
|
||||||
label: Bus
|
label: Bus
|
||||||
access:
|
access:
|
||||||
|
|
@ -9796,6 +9799,9 @@ nodeDriver:
|
||||||
label: SSH User
|
label: SSH User
|
||||||
placeholder: e.g. ubuntu
|
placeholder: e.g. ubuntu
|
||||||
toolTip: SSH user to login with the selected OS image.
|
toolTip: SSH user to login with the selected OS image.
|
||||||
|
macAddress:
|
||||||
|
label: Mac Address
|
||||||
|
toolTip: MAC address as seen inside the guest system.
|
||||||
networkName:
|
networkName:
|
||||||
label: Network Name
|
label: Network Name
|
||||||
placeholder: Please select a network
|
placeholder: Please select a network
|
||||||
|
|
@ -9812,6 +9818,22 @@ nodeDriver:
|
||||||
namespace:
|
namespace:
|
||||||
label: Namespace
|
label: Namespace
|
||||||
placeholder: e.g. default
|
placeholder: e.g. default
|
||||||
|
disks:
|
||||||
|
title: Volumes
|
||||||
|
diskType:
|
||||||
|
volume: Volume
|
||||||
|
imageVolume: Image Volume
|
||||||
|
bootOrder:
|
||||||
|
label: bootOrder
|
||||||
|
addVolume:
|
||||||
|
volume: Add Volume
|
||||||
|
imageVolume: Add Image Volume
|
||||||
|
network:
|
||||||
|
title: Networks
|
||||||
|
label: Network
|
||||||
|
macFormat: 'Invalid MAC address format.'
|
||||||
|
addNetwork:
|
||||||
|
network: Add Network
|
||||||
diskSize:
|
diskSize:
|
||||||
label: Disk
|
label: Disk
|
||||||
unit: GiB
|
unit: GiB
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue