From 1becccffbc405684e6977c7c2b56c979f3ca914a Mon Sep 17 00:00:00 2001 From: mathieuRA Date: Tue, 26 Dec 2023 10:10:07 +0100 Subject: [PATCH] feat(xo-web/host/network): display and edit the IPv6 PIF field --- CHANGELOG.unreleased.md | 3 + packages/xo-web/src/common/intl/locales/es.js | 3 - packages/xo-web/src/common/intl/locales/fr.js | 3 - packages/xo-web/src/common/intl/locales/he.js | 3 - packages/xo-web/src/common/intl/locales/hu.js | 3 - packages/xo-web/src/common/intl/locales/it.js | 3 - packages/xo-web/src/common/intl/locales/pl.js | 3 - packages/xo-web/src/common/intl/locales/pt.js | 3 - packages/xo-web/src/common/intl/locales/ru.js | 3 - packages/xo-web/src/common/intl/locales/tr.js | 3 - packages/xo-web/src/common/intl/messages.js | 4 +- packages/xo-web/src/common/xo/index.js | 6 +- .../xo-web/src/xo-app/host/tab-network.js | 57 ++++++++++++++----- 13 files changed, 55 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 1f340d753..4d9600697 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -7,6 +7,8 @@ > Users must be able to say: “Nice enhancement, I'm eager to test it” +- [Host/Network/PIF] Display and ability to edit IPv6 field [#5400](https://github.com/vatesfr/xen-orchestra/issues/5400) (PR [#7218](https://github.com/vatesfr/xen-orchestra/pull/7218)) + ### Bug fixes > Users must be able to say: “I had this issue, happy to know it's fixed” @@ -28,5 +30,6 @@ - xo-server minor +- xo-web minor diff --git a/packages/xo-web/src/common/intl/locales/es.js b/packages/xo-web/src/common/intl/locales/es.js index 5a1c050a6..b0238d673 100644 --- a/packages/xo-web/src/common/intl/locales/es.js +++ b/packages/xo-web/src/common/intl/locales/es.js @@ -1541,9 +1541,6 @@ export default { // Original text: 'Invalid parameters' configIpErrorTitle: undefined, - // Original text: 'IP address and netmask required' - configIpErrorMessage: undefined, - // Original text: 'Static IP address' staticIp: undefined, diff --git a/packages/xo-web/src/common/intl/locales/fr.js b/packages/xo-web/src/common/intl/locales/fr.js index b4bf3e54c..03057ff34 100644 --- a/packages/xo-web/src/common/intl/locales/fr.js +++ b/packages/xo-web/src/common/intl/locales/fr.js @@ -1596,9 +1596,6 @@ export default { // Original text: "Invalid parameters" configIpErrorTitle: 'Paramètres invalides', - // Original text: "IP address and netmask required" - configIpErrorMessage: 'Adresse IP et masque de réseau requis', - // Original text: "Static IP address" staticIp: 'Adresse IP statique', diff --git a/packages/xo-web/src/common/intl/locales/he.js b/packages/xo-web/src/common/intl/locales/he.js index 55aead526..d68cc5496 100644 --- a/packages/xo-web/src/common/intl/locales/he.js +++ b/packages/xo-web/src/common/intl/locales/he.js @@ -1295,9 +1295,6 @@ export default { // Original text: 'Invalid parameters' configIpErrorTitle: undefined, - // Original text: 'IP address and netmask required' - configIpErrorMessage: undefined, - // Original text: 'Static IP address' staticIp: undefined, diff --git a/packages/xo-web/src/common/intl/locales/hu.js b/packages/xo-web/src/common/intl/locales/hu.js index 94e4e6a1e..9a13583c1 100644 --- a/packages/xo-web/src/common/intl/locales/hu.js +++ b/packages/xo-web/src/common/intl/locales/hu.js @@ -1491,9 +1491,6 @@ export default { // Original text: "Invalid parameters" configIpErrorTitle: 'Invalid parameters', - // Original text: "IP address and netmask required" - configIpErrorMessage: 'IP cím and netmask required', - // Original text: "Static IP address" staticIp: 'Static IP cím', diff --git a/packages/xo-web/src/common/intl/locales/it.js b/packages/xo-web/src/common/intl/locales/it.js index 2e586ceb6..6c9bf8cdb 100644 --- a/packages/xo-web/src/common/intl/locales/it.js +++ b/packages/xo-web/src/common/intl/locales/it.js @@ -2387,9 +2387,6 @@ export default { // Original text: 'Invalid parameters' configIpErrorTitle: 'Parametri non validi', - // Original text: 'IP address and netmask required' - configIpErrorMessage: 'Indirizzo IP e maschera di rete richiesti', - // Original text: 'Static IP address' staticIp: 'Indirizzo IP statico', diff --git a/packages/xo-web/src/common/intl/locales/pl.js b/packages/xo-web/src/common/intl/locales/pl.js index b1180c63e..f318a24b6 100644 --- a/packages/xo-web/src/common/intl/locales/pl.js +++ b/packages/xo-web/src/common/intl/locales/pl.js @@ -1298,9 +1298,6 @@ export default { // Original text: 'Invalid parameters' configIpErrorTitle: undefined, - // Original text: 'IP address and netmask required' - configIpErrorMessage: undefined, - // Original text: 'Static IP address' staticIp: undefined, diff --git a/packages/xo-web/src/common/intl/locales/pt.js b/packages/xo-web/src/common/intl/locales/pt.js index 508637307..e1bc70fbf 100644 --- a/packages/xo-web/src/common/intl/locales/pt.js +++ b/packages/xo-web/src/common/intl/locales/pt.js @@ -1296,9 +1296,6 @@ export default { // Original text: 'Invalid parameters' configIpErrorTitle: undefined, - // Original text: 'IP address and netmask required' - configIpErrorMessage: undefined, - // Original text: 'Static IP address' staticIp: undefined, diff --git a/packages/xo-web/src/common/intl/locales/ru.js b/packages/xo-web/src/common/intl/locales/ru.js index e094c1ffb..f63a72617 100644 --- a/packages/xo-web/src/common/intl/locales/ru.js +++ b/packages/xo-web/src/common/intl/locales/ru.js @@ -1542,9 +1542,6 @@ export default { // Original text: 'Invalid parameters' configIpErrorTitle: undefined, - // Original text: 'IP address and netmask required' - configIpErrorMessage: undefined, - // Original text: 'Static IP address' staticIp: undefined, diff --git a/packages/xo-web/src/common/intl/locales/tr.js b/packages/xo-web/src/common/intl/locales/tr.js index 00170b992..2d0a14e85 100644 --- a/packages/xo-web/src/common/intl/locales/tr.js +++ b/packages/xo-web/src/common/intl/locales/tr.js @@ -1990,9 +1990,6 @@ export default { // Original text: "Invalid parameters" configIpErrorTitle: 'Geçersiz parametre', - // Original text: "IP address and netmask required" - configIpErrorMessage: 'IP adresi ve ağ maskesi gerekli', - // Original text: "Static IP address" staticIp: 'Statik IP adresi', diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js index 204a98bf6..9535616db 100644 --- a/packages/xo-web/src/common/intl/messages.js +++ b/packages/xo-web/src/common/intl/messages.js @@ -1072,11 +1072,13 @@ const messages = { defaultLockingMode: 'Default locking mode', pifConfigureIp: 'Configure IP address', configIpErrorTitle: 'Invalid parameters', - configIpErrorMessage: 'IP address and netmask required', staticIp: 'Static IP address', + staticIpv6: 'Static IPv6 address', netmask: 'Netmask', dns: 'DNS', gateway: 'Gateway', + ipRequired: 'An IP address is required', + netmaskRequired: 'Netmask required', // ----- Host storage tabs ----- addSrDeviceButton: 'Add a storage', srType: 'Type', diff --git a/packages/xo-web/src/common/xo/index.js b/packages/xo-web/src/common/xo/index.js index 544347e0d..a67bf784d 100644 --- a/packages/xo-web/src/common/xo/index.js +++ b/packages/xo-web/src/common/xo/index.js @@ -2244,11 +2244,13 @@ export const deletePifs = pifs => body: _('deletePifsConfirm', { nPifs: pifs.length }), }).then(() => Promise.all(map(pifs, pif => _call('pif.delete', { pif: resolveId(pif) }))), noop) -export const reconfigurePifIp = (pif, { mode, ip, netmask, gateway, dns }) => +export const reconfigurePifIp = (pif, { mode, ip, ipv6, ipv6Mode, netmask, gateway, dns }) => _call('pif.reconfigureIp', { pif: resolveId(pif), mode, ip, + ipv6, + ipv6Mode, netmask, gateway, dns, @@ -2256,6 +2258,8 @@ export const reconfigurePifIp = (pif, { mode, ip, netmask, gateway, dns }) => export const getIpv4ConfigModes = () => _call('pif.getIpv4ConfigurationModes') +export const getIpv6ConfigModes = () => _call('pif.getIpv6ConfigurationModes') + export const editPif = (pif, { vlan }) => _call('pif.editPif', { pif: resolveId(pif), vlan }) export const scanHostPifs = hostId => _call('host.scanPifs', { host: hostId }) diff --git a/packages/xo-web/src/xo-app/host/tab-network.js b/packages/xo-web/src/xo-app/host/tab-network.js index 15449c738..688be09c5 100644 --- a/packages/xo-web/src/xo-app/host/tab-network.js +++ b/packages/xo-web/src/xo-app/host/tab-network.js @@ -26,6 +26,7 @@ import { editNetwork, editPif, getIpv4ConfigModes, + getIpv6ConfigModes, reconfigurePifIp, scanHostPifs, } from 'xo' @@ -41,7 +42,10 @@ class ConfigureIpModal extends Component { const { pif } = props if (pif) { - this.state = pick(pif, ['ip', 'netmask', 'dns', 'gateway']) + this.state = { + ...pick(pif, ['ip', 'netmask', 'dns', 'gateway']), + ipv6: pif.ipv6?.[0], + } } } @@ -50,7 +54,7 @@ class ConfigureIpModal extends Component { } render() { - const { ip, netmask, dns, gateway } = this.state + const { ip, ipv6, netmask, dns, gateway } = this.state return (
@@ -61,6 +65,13 @@ class ConfigureIpModal extends Component {   + + {_('staticIpv6')} + + + + +   {_('netmask')} @@ -111,14 +122,19 @@ const reconfigureIp = (pif, mode) => { title: _('pifConfigureIp'), body: , }).then(params => { - if (!params.ip || !params.netmask) { - error(_('configIpErrorTitle'), _('configIpErrorMessage')) - return + if (params.ip === undefined && params.ipv6 === undefined) { + return error(_('configIpErrorTitle'), _('ipRequired')) + } + if (params.ip !== undefined && params.netmask === undefined) { + return error(_('configIpErrorTitle'), _('netmaskRequired')) + } + if (params.ipv6 !== undefined) { + params.ipv6Mode = mode } return reconfigurePifIp(pif, { mode, ...params }) }, noop) } - return reconfigurePifIp(pif, { mode }) + return reconfigurePifIp(pif, { [pif.primaryAddressType === 'IPv6' ? 'ipv6Mode' : 'mode']: mode }) } class PifItemIp extends Component { @@ -126,7 +142,7 @@ class PifItemIp extends Component { render() { const { pif } = this.props - const pifIp = pif.ip + const pifIp = pif.primaryAddressType === 'IPv6' ? pif.ipv6?.[0] : pif.ip return (
{pifIp}{' '} @@ -143,26 +159,41 @@ class PifItemIp extends Component { class PifItemMode extends Component { state = { configModes: [] } - componentDidMount() { - getIpv4ConfigModes().then(configModes => this.setState({ configModes })) + async componentDidMount() { + const [ipv4ConfigModes, ipv6ConfigModes] = await Promise.all([getIpv4ConfigModes(), getIpv6ConfigModes()]) + this.setState({ ipv4ConfigModes, ipv6ConfigModes }) } _configIp = mode => mode != null && reconfigureIp(this.props.pif, mode.value) + _isIpv6 = createSelector( + () => this.props.pif.primaryAddressType, + primaryAddressType => primaryAddressType === 'IPv6' + ) + _getOptions = createSelector( - () => this.state.configModes, - configModes => configModes.map(mode => ({ label: mode, value: mode })) + this._isIpv6, + () => this.state.ipv4ConfigModes, + () => this.state.ipv6ConfigModes, + (isIpv6, ipv4ConfigModes, ipv6ConfigModes) => + (isIpv6 ? ipv6ConfigModes : ipv4ConfigModes).map(mode => ({ label: mode, value: mode })) ) _getValue = createSelector( + this._isIpv6, () => this.props.pif.mode, - mode => ({ label: mode, value: mode }) + () => this.props.pif.ipv6Mode, + (isIpv6, mode, ipv6Mode) => { + mode = isIpv6 ? ipv6Mode : mode + return { label: mode, value: mode } + } ) render() { + const isIpv6 = this._isIpv6() return ( ) }