Add support for IPv6 network setting
Add IPv6 setting in network setting page.
- Add IPv6 domain name, DNS servers, NTP servers enable/disable
- Add DHCPv6 enable/disable
- Add IPv6 default gateway
- Add IPv6 addresses
- Add IPv6 static addresses
- Add IPv6 static addresses adding and deleting
Tested:
- IPv6 domain name, DNS servers, NTP servers enable/disable function
- DHCPv6 enable/disable function
- Verified the IPv6 default gateway
- IPv6 addresses adding and deleting
- Verified the IPv6 addresses in IPv6 table
Change-Id: I9eebf6ef5f7de748f79779d8168b8dcfcdda2495
Signed-off-by: Sean Zhang <xiazhang@nvidia.com>
diff --git a/src/views/Settings/Network/TableIpv6.vue b/src/views/Settings/Network/TableIpv6.vue
new file mode 100644
index 0000000..5a16e9d
--- /dev/null
+++ b/src/views/Settings/Network/TableIpv6.vue
@@ -0,0 +1,289 @@
+<template>
+ <page-section :section-title="$t('pageNetwork.ipv6')">
+ <b-row class="mb-4">
+ <b-col lg="2" md="6">
+ <dl>
+ <dt>{{ $t('pageNetwork.dhcp6') }}</dt>
+ <dd>
+ <b-form-checkbox
+ id="dhcp6Switch"
+ v-model="dhcp6EnabledState"
+ data-test-id="networkSettings-switch-dhcp6Enabled"
+ switch
+ @change="changeDhcp6EnabledState"
+ >
+ <span v-if="dhcp6EnabledState">
+ {{ $t('global.status.enabled') }}
+ </span>
+ <span v-else>{{ $t('global.status.disabled') }}</span>
+ </b-form-checkbox>
+ </dd>
+ </dl>
+ </b-col>
+ <b-col lg="2" md="6">
+ <dl class="text-nowrap">
+ <dt>
+ {{ $t('pageNetwork.ipv6DefaultGateway') }}
+ <b-button
+ v-if="defaultGatewayEditable"
+ variant="link"
+ class="p-1"
+ @click="initDefaultGatewayModal()"
+ >
+ <icon-edit
+ :title="$t('pageNetwork.modal.editIPv6DefaultGatewayTitle')"
+ />
+ </b-button>
+ </dt>
+ <dd>
+ {{ dataFormatter(defaultGateway) }}
+ </dd>
+ </dl>
+ </b-col>
+ </b-row>
+ <b-row>
+ <b-col>
+ <h3 class="h5">
+ {{ $t('pageNetwork.ipv6Addresses') }}
+ </h3>
+ </b-col>
+ <b-col class="text-right">
+ <b-button variant="primary" @click="initAddIpv6Address()">
+ <icon-add />
+ {{ $t('pageNetwork.table.addIpv6Address') }}
+ </b-button>
+ </b-col>
+ </b-row>
+ <b-table
+ responsive="md"
+ hover
+ :fields="ipv6TableFields"
+ :items="form.ipv6TableItems"
+ :empty-text="$t('global.table.emptyMessage')"
+ class="mb-0"
+ show-empty
+ >
+ <template #cell(actions)="{ item, index }">
+ <table-row-action
+ v-for="(action, actionIndex) in filteredActions(item)"
+ :key="actionIndex"
+ :value="action.value"
+ :title="action.title"
+ :enabled="action.enabled"
+ @click-table-action="onIpv6TableAction(action, $event, index)"
+ >
+ <template #icon>
+ <icon-edit v-if="action.value === 'edit'" />
+ <icon-trashcan v-if="action.value === 'delete'" />
+ </template>
+ </table-row-action>
+ </template>
+ </b-table>
+ </page-section>
+</template>
+
+<script>
+import BVToastMixin from '@/components/Mixins/BVToastMixin';
+import IconAdd from '@carbon/icons-vue/es/add--alt/20';
+import IconEdit from '@carbon/icons-vue/es/edit/20';
+import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
+import PageSection from '@/components/Global/PageSection';
+import TableRowAction from '@/components/Global/TableRowAction';
+import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
+import { mapState } from 'vuex';
+
+export default {
+ name: 'Ipv6Table',
+ components: {
+ IconAdd,
+ IconEdit,
+ IconTrashcan,
+ PageSection,
+ TableRowAction,
+ },
+ mixins: [BVToastMixin, LoadingBarMixin, DataFormatterMixin],
+ props: {
+ tabIndex: {
+ type: Number,
+ default: 0,
+ },
+ },
+ data() {
+ return {
+ form: {
+ ipv6TableItems: [],
+ },
+ actions: [
+ {
+ value: 'edit',
+ title: this.$t('global.action.edit'),
+ },
+ {
+ value: 'delete',
+ title: this.$t('global.action.delete'),
+ },
+ ],
+ ipv6TableFields: [
+ {
+ key: 'Address',
+ label: this.$t('pageNetwork.table.ipAddress'),
+ },
+ {
+ key: 'PrefixLength',
+ label: this.$t('pageNetwork.table.prefixLength'),
+ },
+ {
+ key: 'AddressOrigin',
+ label: this.$t('pageNetwork.table.addressOrigin'),
+ },
+ { key: 'actions', label: '', tdClass: 'text-right' },
+ ],
+ defaultGateway: '',
+ defaultGatewayEditable:
+ process.env.VUE_APP_ENV_NAME !== 'nvidia-bluefield',
+ };
+ },
+ computed: {
+ ...mapState('network', ['ethernetData']),
+ selectedInterface() {
+ return this.$store.getters['network/selectedInterfaceIndex'];
+ },
+ dhcp6EnabledState: {
+ get() {
+ return (
+ this.$store.getters['network/globalNetworkSettings'][
+ this.selectedInterface
+ ].dhcp6Enabled === 'Enabled'
+ );
+ },
+ set(newValue) {
+ return newValue;
+ },
+ },
+ filteredActions() {
+ return (item) => {
+ if (item.AddressOrigin === 'DHCPv6' || item.AddressOrigin === 'SLAAC') {
+ return item.actions.filter((action) => action.value !== 'delete');
+ } else {
+ return item.actions;
+ }
+ };
+ },
+ },
+ watch: {
+ // Watch for change in tab index
+ tabIndex() {
+ this.getIpv6TableItems();
+ this.getDefaultGateway();
+ },
+ ethernetData() {
+ this.getIpv6TableItems();
+ this.getDefaultGateway();
+ },
+ },
+ created() {
+ this.getIpv6TableItems();
+ this.getDefaultGateway();
+ this.$store.dispatch('network/getEthernetData').finally(() => {
+ // Emit initial data fetch complete to parent component
+ this.$root.$emit('network-table-ipv6-complete');
+ });
+ },
+ methods: {
+ getDefaultGateway() {
+ this.defaultGateway = this.ethernetData[this.tabIndex].IPv6DefaultGateway;
+ },
+ getIpv6TableItems() {
+ const index = this.tabIndex;
+ const addresses =
+ this.ethernetData[index].IPv6Addresses.filter(
+ (ipv6) =>
+ ipv6.AddressOrigin === 'LinkLocal' ||
+ ipv6.AddressOrigin === 'Static' ||
+ ipv6.AddressOrigin === 'SLAAC' ||
+ ipv6.AddressOrigin === 'DHCPv6',
+ ) || [];
+ this.form.ipv6TableItems = addresses.map((ipv6) => {
+ return {
+ Address: ipv6.Address,
+ PrefixLength: ipv6.PrefixLength,
+ AddressOrigin: ipv6.AddressOrigin,
+ actions: [
+ {
+ value: 'delete',
+ title: this.$t('pageNetwork.table.deleteIpv6'),
+ },
+ ],
+ };
+ });
+ },
+ onIpv6TableAction(action, $event, index) {
+ if ($event === 'delete') {
+ this.deleteIpv6TableRow(index);
+ }
+ },
+ deleteIpv6TableRow(index) {
+ const AddressOrigin = this.form.ipv6TableItems[index].AddressOrigin;
+ this.form.ipv6TableItems.splice(index, 1);
+ const newIpv6Array = this.form.ipv6TableItems.map((ipv6) => {
+ const { Address, PrefixLength } = ipv6;
+ return {
+ Address,
+ PrefixLength,
+ };
+ });
+ if (
+ newIpv6Array.length == 0 &&
+ (AddressOrigin === 'Static' || AddressOrigin === 'LinkLocal')
+ ) {
+ this.$store
+ .dispatch('network/saveDhcp6EnabledState', true)
+ .then((message) => this.successToast(message))
+ .catch(({ message }) => this.errorToast(message));
+ }
+ this.$store
+ .dispatch('network/editIpv6Address', newIpv6Array)
+ .then((message) => this.successToast(message))
+ .catch(({ message }) => this.errorToast(message));
+ },
+ initAddIpv6Address() {
+ this.$bvModal.show('modal-add-ipv6');
+ },
+ changeDhcp6EnabledState(state) {
+ this.$bvModal
+ .msgBoxConfirm(
+ state
+ ? this.$t('pageNetwork.modal.confirmEnableDhcp')
+ : this.$t('pageNetwork.modal.confirmDisableDhcp'),
+ {
+ title: this.$t('pageNetwork.modal.dhcpConfirmTitle', {
+ dhcpState: state
+ ? this.$t('global.action.enable')
+ : this.$t('global.action.disable'),
+ }),
+ okTitle: state
+ ? this.$t('global.action.enable')
+ : this.$t('global.action.disable'),
+ okVariant: 'danger',
+ cancelTitle: this.$t('global.action.cancel'),
+ },
+ )
+ .then((dhcpEnableConfirmed) => {
+ if (dhcpEnableConfirmed) {
+ this.$store
+ .dispatch('network/saveDhcp6EnabledState', state)
+ .then((message) => this.successToast(message))
+ .catch(({ message }) => this.errorToast(message));
+ } else {
+ let onDhcpCancel = document.getElementById('dhcp6Switch');
+ onDhcpCancel.checked = !state;
+ }
+ });
+ },
+ initDefaultGatewayModal() {
+ this.$bvModal.show('modal-default-gateway');
+ },
+ },
+};
+</script>