blob: fd245a31a73561245fa78a33c870cd8414a465a1 [file] [log] [blame]
Dixsie Wolmersbb81d552020-02-26 19:52:28 -06001<template>
2 <b-container fluid="xl">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -05003 <page-title :description="$t('pageNetworkSettings.pageDescription')" />
4 <page-section :section-title="$t('pageNetworkSettings.interface')">
Dixsie Wolmersbb81d552020-02-26 19:52:28 -06005 <b-row>
6 <b-col lg="3">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -05007 <b-form-group
8 label-for="interface-select"
9 :label="$t('pageNetworkSettings.form.networkInterface')"
10 >
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060011 <b-form-select
12 id="interface-select"
13 v-model="selectedInterfaceIndex"
Dixsie Wolmers55888a12020-07-01 11:21:47 -050014 data-test-id="networkSettings-select-interface"
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060015 :options="interfaceSelectOptions"
16 @change="selectInterface"
17 >
18 </b-form-select>
19 </b-form-group>
20 </b-col>
21 </b-row>
22 </page-section>
23 <b-form novalidate @submit.prevent="submitForm">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050024 <page-section :section-title="$t('pageNetworkSettings.system')">
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060025 <b-row>
26 <b-col lg="3">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050027 <b-form-group
28 :label="$t('pageNetworkSettings.form.defaultGateway')"
29 label-for="default-gateway"
30 >
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060031 <b-form-input
32 id="default-gateway"
33 v-model.trim="form.gateway"
Dixsie Wolmers55888a12020-07-01 11:21:47 -050034 data-test-id="networkSettings-input-gateway"
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060035 type="text"
36 :readonly="dhcpEnabled"
37 :state="getValidationState($v.form.gateway)"
38 @change="$v.form.gateway.$touch()"
39 />
40 <b-form-invalid-feedback role="alert">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050041 <div v-if="!$v.form.gateway.required">
42 {{ $t('global.form.fieldRequired') }}
43 </div>
44 <div v-if="!$v.form.gateway.validateAddress">
45 {{ $t('global.form.invalidFormat') }}
46 </div>
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060047 </b-form-invalid-feedback>
48 </b-form-group>
49 </b-col>
50 <b-col lg="3">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050051 <b-form-group
52 :label="$t('pageNetworkSettings.form.hostname')"
53 label-for="hostname-field"
54 >
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060055 <b-form-input
56 id="hostname-field"
57 v-model.trim="form.hostname"
Dixsie Wolmers55888a12020-07-01 11:21:47 -050058 data-test-id="networkSettings-input-hostname"
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060059 type="text"
60 :state="getValidationState($v.form.hostname)"
61 @change="$v.form.hostname.$touch()"
62 />
63 <b-form-invalid-feedback role="alert">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050064 <div v-if="!$v.form.hostname.required">
65 {{ $t('global.form.fieldRequired') }}
66 </div>
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060067 <div v-if="!$v.form.hostname.validateHostname">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050068 {{
69 $t('global.form.lengthMustBeBetween', { min: 1, max: 64 })
70 }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060071 </div>
72 </b-form-invalid-feedback>
73 </b-form-group>
74 </b-col>
75 <b-col lg="3">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050076 <b-form-group
77 :label="$t('pageNetworkSettings.form.macAddress')"
78 label-for="mac-address"
79 >
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060080 <b-form-input
81 id="mac-address"
82 v-model.trim="form.macAddress"
Dixsie Wolmers55888a12020-07-01 11:21:47 -050083 data-test-id="networkSettings-input-macAddress"
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060084 type="text"
85 :state="getValidationState($v.form.macAddress)"
86 @change="$v.form.macAddress.$touch()"
87 />
88 <b-form-invalid-feedback role="alert">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -050089 <div v-if="!$v.form.macAddress.required">
90 {{ $t('global.form.fieldRequired') }}
91 </div>
92 <div v-if="!$v.form.macAddress.validateMacAddress">
93 {{ $t('global.form.invalidFormat') }}
94 </div>
Dixsie Wolmersbb81d552020-02-26 19:52:28 -060095 </b-form-invalid-feedback>
96 </b-form-group>
97 </b-col>
98 </b-row>
99 </page-section>
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500100 <page-section :section-title="$t('pageNetworkSettings.staticIpv4')">
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600101 <b-row>
102 <b-col lg="9" class="mb-3">
103 <b-table
SurenNeware5e25e282020-07-08 15:57:23 +0530104 responsive="md"
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600105 :fields="ipv4StaticTableFields"
106 :items="form.ipv4StaticTableItems"
107 class="mb-0"
108 >
109 <template v-slot:cell(Address)="{ item, index }">
110 <b-form-input
111 v-model.trim="item.Address"
Dixsie Wolmers55888a12020-07-01 11:21:47 -0500112 :data-test-id="`networkSettings-input-staticIpv4-${index}`"
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500113 :aria-label="
114 $t('pageNetworkSettings.ariaLabel.staticIpv4AddressRow') +
115 ' ' +
116 (index + 1)
117 "
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600118 :readonly="dhcpEnabled"
119 :state="
120 getValidationState(
121 $v.form.ipv4StaticTableItems.$each.$iter[index].Address
122 )
123 "
124 @change="
125 $v.form.ipv4StaticTableItems.$each.$iter[
126 index
127 ].Address.$touch()
128 "
129 />
130 <b-form-invalid-feedback role="alert">
131 <div
132 v-if="
133 !$v.form.ipv4StaticTableItems.$each.$iter[index].Address
134 .required
135 "
136 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500137 {{ $t('global.form.fieldRequired') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600138 </div>
139 <div
140 v-if="
141 !$v.form.ipv4StaticTableItems.$each.$iter[index].Address
142 .validateAddress
143 "
144 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500145 {{ $t('global.form.invalidFormat') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600146 </div>
147 </b-form-invalid-feedback>
148 </template>
149 <template v-slot:cell(SubnetMask)="{ item, index }">
150 <b-form-input
151 v-model.trim="item.SubnetMask"
Dixsie Wolmers55888a12020-07-01 11:21:47 -0500152 :data-test-id="`networkSettings-input-subnetMask-${index}`"
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500153 :aria-label="
154 $t('pageNetworkSettings.ariaLabel.staticIpv4SubnetRow') +
155 ' ' +
156 (index + 1)
157 "
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600158 :readonly="dhcpEnabled"
159 :state="
160 getValidationState(
161 $v.form.ipv4StaticTableItems.$each.$iter[index].SubnetMask
162 )
163 "
164 @change="
165 $v.form.ipv4StaticTableItems.$each.$iter[
166 index
167 ].SubnetMask.$touch()
168 "
169 />
170 <b-form-invalid-feedback role="alert">
171 <div
172 v-if="
173 !$v.form.ipv4StaticTableItems.$each.$iter[index]
174 .SubnetMask.required
175 "
176 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500177 {{ $t('global.form.fieldRequired') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600178 </div>
179 <div
180 v-if="
181 !$v.form.ipv4StaticTableItems.$each.$iter[index]
182 .SubnetMask.validateAddress
183 "
184 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500185 {{ $t('global.form.invalidFormat') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600186 </div>
187 </b-form-invalid-feedback>
188 </template>
189 <template v-slot:cell(actions)="{ item, index }">
190 <table-row-action
191 v-for="(action, actionIndex) in item.actions"
192 :key="actionIndex"
193 :value="action.value"
194 :title="action.title"
195 @click:tableAction="onDeleteIpv4StaticTableRow($event, index)"
196 >
197 <template v-slot:icon>
198 <icon-trashcan v-if="action.value === 'delete'" />
199 </template>
200 </table-row-action>
201 </template>
202 </b-table>
203 <b-button variant="link" @click="addIpv4StaticTableRow">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500204 <icon-add />
205 {{ $t('pageNetworkSettings.table.addStaticIpv4Address') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600206 </b-button>
207 </b-col>
208 </b-row>
209 </page-section>
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500210 <page-section :section-title="$t('pageNetworkSettings.staticDns')">
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600211 <b-row>
212 <b-col lg="4" class="mb-3">
213 <b-table
SurenNeware5e25e282020-07-08 15:57:23 +0530214 responsive
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600215 :fields="dnsTableFields"
216 :items="form.dnsStaticTableItems"
217 class="mb-0"
218 >
219 <template v-slot:cell(address)="{ item, index }">
220 <b-form-input
221 v-model.trim="item.address"
Dixsie Wolmers55888a12020-07-01 11:21:47 -0500222 :data-test-id="`networkSettings-input-dnsAddress-${index}`"
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500223 :aria-label="
224 $t('pageNetworkSettings.ariaLabel.staticDnsRow') +
225 ' ' +
226 (index + 1)
227 "
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600228 :readonly="dhcpEnabled"
229 :state="
230 getValidationState(
231 $v.form.dnsStaticTableItems.$each.$iter[index].address
232 )
233 "
234 @change="
235 $v.form.dnsStaticTableItems.$each.$iter[
236 index
237 ].address.$touch()
238 "
239 />
240 <b-form-invalid-feedback role="alert">
241 <div
242 v-if="
243 !$v.form.dnsStaticTableItems.$each.$iter[index].address
244 .required
245 "
246 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500247 {{ $t('global.form.fieldRequired') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600248 </div>
249 <div
250 v-if="
251 !$v.form.dnsStaticTableItems.$each.$iter[index].address
252 .validateAddress
253 "
254 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500255 {{ $t('global.form.invalidFormat') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600256 </div>
257 </b-form-invalid-feedback>
258 </template>
259 <template v-slot:cell(actions)="{ item, index }">
260 <table-row-action
261 v-for="(action, actionIndex) in item.actions"
262 :key="actionIndex"
263 :value="action.value"
264 :title="action.title"
265 @click:tableAction="onDeleteDnsTableRow($event, index)"
266 >
267 <template v-slot:icon>
268 <icon-trashcan v-if="action.value === 'delete'" />
269 </template>
270 </table-row-action>
271 </template>
272 </b-table>
273 <b-button variant="link" @click="addDnsTableRow">
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500274 <icon-add /> {{ $t('pageNetworkSettings.table.addDns') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600275 </b-button>
276 </b-col>
277 </b-row>
278 </page-section>
279 <b-button
280 variant="primary"
281 type="submit"
Dixsie Wolmers55888a12020-07-01 11:21:47 -0500282 data-test-id="networkSettings-button-saveNetworkSettings"
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600283 :disabled="!$v.form.$anyDirty || $v.form.$invalid"
284 >
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500285 {{ $t('global.action.saveSettings') }}
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600286 </b-button>
287 </b-form>
288 </b-container>
289</template>
290
291<script>
292import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
293import IconAdd from '@carbon/icons-vue/es/add--alt/20';
294import BVToastMixin from '@/components/Mixins/BVToastMixin';
295import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
296import PageSection from '@/components/Global/PageSection';
297import PageTitle from '@/components/Global/PageTitle';
298import TableRowAction from '@/components/Global/TableRowAction';
299import VuelidateMixin from '@/components/Mixins/VuelidateMixin';
300import { mapState } from 'vuex';
301import { required, helpers } from 'vuelidate/lib/validators';
302
303// IP address, gateway and subnet pattern
304const validateAddress = helpers.regex(
305 'validateAddress',
306 /^(?=.*[^.]$)((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.?){4}$/
307);
308// Hostname pattern
309const validateHostname = helpers.regex('validateHostname', /^\S{0,64}$/);
310// MAC address pattern
311const validateMacAddress = helpers.regex(
312 'validateMacAddress',
313 /^(?:[0-9A-Fa-f]{2}([:-]?)[0-9A-Fa-f]{2})(?:(?:\1|\.)(?:[0-9A-Fa-f]{2}([:-]?)[0-9A-Fa-f]{2})){2}$/
314);
315
316export default {
317 name: 'NetworkSettings',
318 components: {
319 PageTitle,
320 PageSection,
321 TableRowAction,
322 IconTrashcan,
323 IconAdd
324 },
325 mixins: [BVToastMixin, VuelidateMixin, LoadingBarMixin],
326 data() {
327 return {
328 dhcpEnabled: null,
329 ipv4Configuration: '',
330 ipv4StaticTableFields: [
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500331 {
332 key: 'Address',
333 label: this.$t('pageNetworkSettings.table.ipAddress')
334 },
335 {
336 key: 'SubnetMask',
337 label: this.$t('pageNetworkSettings.table.subnet')
338 },
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600339 { key: 'actions', label: '', tdClass: 'text-right' }
340 ],
341 dnsTableFields: [
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500342 {
343 key: 'address',
344 label: this.$t('pageNetworkSettings.table.ipAddress')
345 },
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600346 { key: 'actions', label: '', tdClass: 'text-right' }
347 ],
348 selectedInterfaceIndex: 0,
349 selectedInterface: {},
350 form: {
351 gateway: '',
352 hostname: '',
353 macAddress: '',
354 ipv4StaticTableItems: [],
355 dnsStaticTableItems: []
356 }
357 };
358 },
359 validations() {
360 return {
361 form: {
362 gateway: { required, validateAddress },
363 hostname: { required, validateHostname },
364 ipv4StaticTableItems: {
365 $each: {
366 Address: {
367 required,
368 validateAddress
369 },
370 SubnetMask: {
371 required,
372 validateAddress
373 }
374 }
375 },
376 macAddress: { required, validateMacAddress },
377 dnsStaticTableItems: {
378 $each: {
379 address: {
380 required,
381 validateAddress
382 }
383 }
384 }
385 }
386 };
387 },
388 computed: {
389 ...mapState('networkSettings', [
390 'ethernetData',
391 'interfaceOptions',
392 'defaultGateway'
393 ]),
394 interfaceSelectOptions() {
395 return this.interfaceOptions.map((option, index) => {
396 return {
397 text: option,
398 value: index
399 };
400 });
401 }
402 },
403 watch: {
404 ethernetData: function() {
405 this.selectInterface();
406 }
407 },
408 created() {
409 this.startLoader();
410 this.$store
411 .dispatch('networkSettings/getEthernetData')
412 .finally(() => this.endLoader());
413 },
414 beforeRouteLeave(to, from, next) {
415 this.hideLoader();
416 next();
417 },
418 methods: {
419 selectInterface() {
420 this.selectedInterface = this.ethernetData[this.selectedInterfaceIndex];
421 this.getIpv4StaticTableItems();
422 this.getDnsStaticTableItems();
423 this.getInterfaceSettings();
424 },
425 getInterfaceSettings() {
426 this.form.gateway = this.defaultGateway;
427 this.form.hostname = this.selectedInterface.HostName;
428 this.form.macAddress = this.selectedInterface.MACAddress;
429 this.dhcpEnabled = this.selectedInterface.DHCPv4.DHCPEnabled;
430 },
431 getDnsStaticTableItems() {
432 const dns = this.selectedInterface.StaticNameServers || [];
433 this.form.dnsStaticTableItems = dns.map(server => {
434 return {
435 address: server,
436 actions: [
437 {
438 value: 'delete',
439 enabled: this.dhcpEnabled,
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500440 title: this.$t('pageNetworkSettings.table.deleteDns')
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600441 }
442 ]
443 };
444 });
445 },
446 addDnsTableRow() {
447 this.$v.form.dnsStaticTableItems.$touch();
448 this.form.dnsStaticTableItems.push({
449 address: '',
450 actions: [
451 {
452 value: 'delete',
453 enabled: this.dhcpEnabled,
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500454 title: this.$t('pageNetworkSettings.table.deleteDns')
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600455 }
456 ]
457 });
458 },
459 deleteDnsTableRow(index) {
460 this.$v.form.dnsStaticTableItems.$touch();
461 this.form.dnsStaticTableItems.splice(index, 1);
462 },
463 onDeleteDnsTableRow(action, row) {
464 this.deleteDnsTableRow(row);
465 },
466 getIpv4StaticTableItems() {
467 const addresses = this.selectedInterface.IPv4StaticAddresses || [];
468 this.form.ipv4StaticTableItems = addresses.map(ipv4 => {
469 return {
470 Address: ipv4.Address,
471 SubnetMask: ipv4.SubnetMask,
472 actions: [
473 {
474 value: 'delete',
475 enabled: this.dhcpEnabled,
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500476 title: this.$t('pageNetworkSettings.table.deleteStaticIpv4')
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600477 }
478 ]
479 };
480 });
481 },
482 addIpv4StaticTableRow() {
483 this.$v.form.ipv4StaticTableItems.$touch();
484 this.form.ipv4StaticTableItems.push({
485 Address: '',
486 SubnetMask: '',
487 actions: [
488 {
489 value: 'delete',
490 enabled: this.dhcpEnabled,
Dixsie Wolmerse3c9c092020-05-20 23:27:56 -0500491 title: this.$t('pageNetworkSettings.table.deleteStaticIpv4')
Dixsie Wolmersbb81d552020-02-26 19:52:28 -0600492 }
493 ]
494 });
495 },
496 deleteIpv4StaticTableRow(index) {
497 this.$v.form.ipv4StaticTableItems.$touch();
498 this.form.ipv4StaticTableItems.splice(index, 1);
499 },
500 onDeleteIpv4StaticTableRow(action, row) {
501 this.deleteIpv4StaticTableRow(row);
502 },
503 submitForm() {
504 this.startLoader();
505 let networkInterfaceSelected = this.selectedInterface;
506 let selectedInterfaceIndex = this.selectedInterfaceIndex;
507 let interfaceId = networkInterfaceSelected.Id;
508 let isDhcpEnabled = networkInterfaceSelected.DHCPv4.DHCPEnabled;
509 let macAddress = this.form.macAddress;
510 let hostname = this.form.hostname;
511 let networkSettingsForm = {
512 interfaceId,
513 hostname,
514 macAddress,
515 selectedInterfaceIndex,
516 isDhcpEnabled
517 };
518 networkSettingsForm.staticIpv4 = this.form.ipv4StaticTableItems.map(
519 updateIpv4 => {
520 delete updateIpv4.actions;
521 updateIpv4.Gateway = this.form.gateway;
522 return updateIpv4;
523 }
524 );
525 networkSettingsForm.staticNameServers = this.form.dnsStaticTableItems.map(
526 updateDns => {
527 return updateDns.address;
528 }
529 );
530 this.$store
531 .dispatch(
532 'networkSettings/updateInterfaceSettings',
533 networkSettingsForm
534 )
535 .then(success => {
536 this.successToast(success);
537 })
538 .catch(({ message }) => this.errorToast(message))
539 .finally(() => {
540 this.$v.form.$reset();
541 this.endLoader();
542 });
543 }
544 }
545};
546</script>