Line data Source code
1 : /*
2 : * Copyright (C) 2021 Red Hat, Inc.
3 : * SPDX-License-Identifier: LGPL-2.1-or-later
4 : */
5 :
6 35 : import React, { useState, useContext } from 'react';
7 35 : import cockpit from 'cockpit';
8 : import { Checkbox } from "@patternfly/react-core/dist/esm/components/Checkbox/index.js";
9 : import { FormGroup } from "@patternfly/react-core/dist/esm/components/Form/index.js";
10 : import { TextInput } from "@patternfly/react-core/dist/esm/components/TextInput/index.js";
11 :
12 : import { MemberInterfaceChoices, NetworkModal, Name, dialogSave } from './dialogs-common.jsx';
13 : import { ModelContext } from './model-context.jsx';
14 : import { useDialogs } from "dialogs.jsx";
15 :
16 : import { v4 as uuidv4 } from 'uuid';
17 : import {
18 : member_connection_for_interface,
19 : member_interface_choices,
20 : } from './interfaces.js';
21 :
22 35 : const _ = cockpit.gettext;
23 :
24 2 : export const BridgeDialog = ({ connection, dev, settings }) => {
25 2 : const Dialogs = useDialogs();
26 2 : const idPrefix = "network-bridge-settings";
27 2 : const model = useContext(ModelContext);
28 2 : const memberChoicesInit = {};
29 :
30 2 : member_interface_choices(model, connection).forEach((iface) => {
31 2 : memberChoicesInit[iface.Name] = !!member_connection_for_interface(connection, iface);
32 2 : });
33 :
34 2 : const [dialogError, setDialogError] = useState(undefined);
35 2 : const [iface, setIface] = useState(settings.connection.interface_name);
36 2 : const [stp, setStp] = useState(!!settings.bridge.stp);
37 0 : const [priority, setPriority] = useState(settings.bridge.priority || 10);
38 0 : const [forwardDelay, setForwardDelay] = useState(settings.bridge.forward_delay || 10);
39 0 : const [helloTime, setHelloTime] = useState(settings.bridge.hello_time || 10);
40 0 : const [maxAge, setMaxAge] = useState(settings.bridge.max_age || 10);
41 2 : const [memberChoices, setMemberChoices] = useState(memberChoicesInit);
42 :
43 2 : const onSubmit = (ev) => {
44 2 : const createSettingsObj = () => ({
45 2 : ...settings,
46 2 : connection: {
47 2 : ...settings.connection,
48 2 : id: iface,
49 2 : interface_name: iface,
50 2 : },
51 2 : bridge: {
52 2 : ...settings.bridge,
53 2 : stp,
54 1 : ...(stp && { priority, forward_delay: forwardDelay, hello_time: helloTime, max_age: maxAge }),
55 2 : interface_name: iface,
56 2 : }
57 2 : });
58 :
59 2 : dialogSave({
60 2 : model,
61 2 : dev,
62 2 : connection,
63 2 : members: memberChoices,
64 2 : membersInit: memberChoicesInit,
65 2 : settings: createSettingsObj(),
66 2 : setDialogError,
67 2 : onClose: Dialogs.close,
68 2 : });
69 :
70 : // Prevent dialog from closing because of <form> onsubmit event
71 2 : if (ev)
72 2 : ev.preventDefault();
73 :
74 2 : return false;
75 2 : };
76 :
77 2 : return (
78 2 : <NetworkModal dialogError={dialogError}
79 2 : idPrefix="network-bridge-settings"
80 2 : onSubmit={onSubmit}
81 1 : title={!connection ? _("Add bridge") : _("Edit bridge settings")}
82 2 : isCreateDialog={!connection}
83 : >
84 2 : <>
85 2 : <Name idPrefix={idPrefix} iface={iface} setIface={setIface} />
86 2 : <FormGroup label={_("Ports")} fieldId={idPrefix + "-interface-members-list"} hasNoPaddingTop>
87 2 : <MemberInterfaceChoices idPrefix={idPrefix} memberChoices={memberChoices} setMemberChoices={setMemberChoices} model={model} group={connection} />
88 2 : </FormGroup>
89 2 : <FormGroup label={_("Options")} fieldId={idPrefix + "-stp-enabled-input"} hasNoPaddingTop>
90 1 : <Checkbox id={idPrefix + "-stp-enabled-input"} isChecked={stp} onChange={(_, s) => setStp(s)} label={_("Spanning tree protocol (STP)")} />
91 1 : {stp && <>
92 1 : <FormGroup fieldId="network-bridge-stp-settings-priority-input" label={_("STP priority")}>
93 1 : <TextInput id="network-bridge-stp-settings-priority-input" className="network-number-field" value={priority} onChange={(_event, value) => setPriority(Number.parseInt(value))} />
94 1 : </FormGroup>
95 1 : <FormGroup fieldId="network-bridge-stp-settings-forward-delay-input" label={_("STP forward delay")}>
96 0 : <TextInput id="network-bridge-stp-settings-forward-delay-input" className="network-number-field" value={forwardDelay} onChange={(_event, value) => setForwardDelay(Number.parseInt(value))} />
97 1 : </FormGroup>
98 1 : <FormGroup fieldId="network-bridge-stp-settings-hello-time-input" label={_("STP hello time")}>
99 1 : <TextInput id="network-bridge-stp-settings-hello-time-input" className="network-number-field" value={helloTime} onChange={(_event, value) => setHelloTime(Number.parseInt(value))} />
100 1 : </FormGroup>
101 1 : <FormGroup fieldId="network-bridge-stp-settings-max-age-input" label={_("STP maximum message age")}>
102 0 : <TextInput id="network-bridge-stp-settings-max-age-input" className="network-number-field" value={maxAge} onChange={(_event, value) => setMaxAge(Number.parseInt(value))} />
103 1 : </FormGroup>
104 1 : </>}
105 2 : </FormGroup>
106 2 : </>
107 2 : </NetworkModal>
108 : );
109 2 : };
110 :
111 33 : export const getGhostSettings = ({ newIfaceName }) => {
112 33 : return (
113 33 : {
114 33 : connection: {
115 33 : id: newIfaceName,
116 33 : autoconnect: true,
117 33 : type: "bridge",
118 33 : uuid: uuidv4(),
119 33 : interface_name: newIfaceName
120 33 : },
121 33 : bridge: {
122 33 : interface_name: newIfaceName,
123 33 : stp: false,
124 33 : priority: 32768,
125 33 : forward_delay: 15,
126 33 : hello_time: 2,
127 33 : max_age: 20,
128 33 : ageing_time: 300
129 33 : }
130 33 : }
131 : );
132 33 : };
|