-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bridge handling improved (bsc#962824) #441
Conversation
@@ -1039,7 +1042,6 @@ def Packages | |||
# for wlan require iw instead of wireless-tools (bnc#539669) | |||
"wlan" => "iw", | |||
"vlan" => "vlan", | |||
"br" => "bridge-utils", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we are using iptools2 and wicked, this dependency should be removed as this way of configure bridges is currently deprecated.
@@ -1553,8 +1555,6 @@ def AddressDialog | |||
LanItems.vlan_id = Builtins.tostring( | |||
Ops.get_integer(@settings, "VLAN_ID", 0) | |||
) | |||
elsif LanItems.type == "br" | |||
LanItems.bridge_ports = Ops.get_string(@settings, "BRIDGE_PORTS", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice ;-) Very common pattern in network code :-/
"Bridge ports: %s\n\n" \ | ||
"Do you want to adapt them now?"), ports.join(", ")) | ||
if Popup.YesNoHeadline(Label.WarningMsg, message) | ||
ports.each { |p| configure_as_bridge_port(p) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is there for the user to decide? IMHO this pop-up is harmful, burdening the user with a decision they cannot understand ("old way, new way"?)
I propose that we simply adapt the config and just log the action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was a doubt I have at the beginning of the PBI as it was also commented in the card. After discussing it with @mchf the conclusion was that automatic conversion does not means not ask the user about it.
We could do it automatically, in that case when? when the interface is edited and saved or also do it although the user press cancel in the edition. If should be converted so why not just have a method that checks current interface configuration when the client is called and adapt old config style?
We just decided to prompt the user just to verify he really wanted to adapt the current configuration and also being a litle conservative taking in account that if something change in current workflow the network is restarted and should not restarted if not (so maybe the user does not expect changes when OK
pressed but then he realized that the network was restarted and some files changed magically.
- "NONE" is shown instead of 0.0.0.0 for old bridge configuration | ||
- The bridge master is shown in the enslaved interface. | ||
- The interfaces overview is updated after a bridge is modified | ||
- 3.1.170.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if I remember correctly, SP3 didn't diverged so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change #440 was the reason I choose that version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, i didn't remember well ;-)
bootproto = devmap["BOOTPROTO"] || "static" | ||
|
||
if bootproto.empty? || bootproto == "static" | ||
devmap["IPADDR"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add || ""
as old implementation doesn't count with nil
. I know it is kind of edge case .... but
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case of nil
bootproto
is set to "static"
as you can see in line 408. Now we have a unit test for DeviceProtocol
method and we can see that for nil
, ""
and "static"
we return the IP address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've addressed devmap["IPADDR"]
here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true .. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx
@@ -1596,6 +1593,10 @@ def AddressDialog | |||
|
|||
private | |||
|
|||
def get_selected_bridges |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing documentation for new method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added documentation
key, | ||
Ops.get_string(@settings, "BRIDGE_PORTS", "") | ||
) | ||
@settings["BRIDGE_PORTS"] = get_selected_bridges.join(" ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
misleading function name. Something like selected_bridge_ports
would be better in my POV.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed and also renamed get_selected_slaves
5d50cc4
to
b48eba9
Compare
# of a bridge. In case that some configuration is not correct then adapt it | ||
# if the user accepts. | ||
def check_bridge_ports_config | ||
return false unless LanItems.type == "br" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I try to drop dependency on these "global" status variables I prefer to have new functions stateless (e.g. checking device type on-the-fly as you never know who forgot to reset or set it somewhere to something reasonable). It should also ease "big bang" refactoring of LanItems
one day.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was exactly the reason I proposed the new method for adapt the config, because the other ones depends on the NetworkInterfaces instance, and it also changed the Current to the last port edited what could produce some unexpected issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just thinking ...
... using NetworkInterfaces.GetType
makes no sense when creating new bridge until new configuration is commited into NetworkInterfaces
... so you can just move the type check out of this method.
ports = LanItems.bridge_ports.split(" ").select { |p| old_bridge_port_config?(p) } | ||
|
||
unless ports.empty? | ||
ports.each { |p| configure_as_bridge_port(p) } if fix_bridge_port_config?(ports) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you really want to raise a popup for every old fashioned bridge port? Poor SLE-11 user with 10 ports bridge ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is only raised once with all the ports in the question
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, my fault.
|
||
# Asks the user about adapt the current bridge port config in case that it | ||
# is configured in the old way (BOOTPROTO == static) & (IPADDR == 0.0.0.0). | ||
def fix_bridge_port_config?(ports) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe adapt_bridge_port_config?
could be a better name for this method, and then instead of configure_as_bridge_port define this method as it is an adaption and not a new configuration at all:
def adapt_bridge_port_config?(ports)
...
end
def adapt_bridge_port_config!(ifcfg_name)
item_id = LanItems.get_configured(ifcfg_name)
devmap = LanItems.GetDeviceMap(item_id)
return false unless devmap
devmap["IPADDR"] = ""
devmap["NETMASK"] = ""
devmap["BOOTPROTO"] = "none"
# take out PREFIXLEN from old configuration (BNC#735109)
devmap["PREFIXLEN"] = ""
LanItems.SetDeviceMap(item_id, devmap)
true
end
@mchf what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well it better describes current use case, but i don't see any benefit in having such one purpose method. So do you have any other pros? ;-)
NetworkInterfaces.Edit(device) | ||
unless NetworkInterfaces.Edit(device) | ||
Lan.autoconf_slaves += [device] unless Lan.autoconf_slaves.include? device | ||
return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inconsistent return value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the end i decided to just let it as it was, and it always returns true and just add the changes if NetworkInterfaces.Edit(device)
success and also remember the previous Interfaces selected by NetworkInterface to avoid let it in a different one what could produce not desired results.
As an alternative I added the adapt_old_port_config method which avoid to work over NetworkInterfaces and where we could also add the logic to write the config to the files without restarting the network
@@ -60,6 +87,21 @@ def configure_as_bridge_port(device) | |||
|
|||
NetworkInterfaces.Commit | |||
NetworkInterfaces.Add | |||
|
|||
NetworkInterfaces.Current = selected_interface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why to return original Current
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is not returned anymore, i let it as it was returning true again
log.info("Adapt device #{device} as bridge port") | ||
|
||
# when using wicked every device which can be bridged | ||
# can be set to BOOTPROTO=none. No workaround with | ||
# BOOTPROTO=static required anymore | ||
NetworkInterfaces.Edit(device) | ||
unless NetworkInterfaces.Edit(device) | ||
Lan.autoconf_slaves += [device] unless Lan.autoconf_slaves.include? device |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well this autoconf stuff is part of a fate request for bonding devices where it was requested to do an udev update for slaves. As it was not requested for bridges, it shouldn't be implemented for bridges in my POV.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, as we was talking some time ago about unifying bonding and bridge management as much as possible was what I tried but this is going too further and some changes should not be necessary and also invalid, so taking this in account I'm going to modify the PR in concordance.
"eth12", | ||
"tap0" | ||
] | ||
describe "#old_bridge_port_config?" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a test for the "eth1" case , which has { "BOOTPROTO" => "none" }
and so should return false
key, | ||
Ops.get_string(@settings, "BRIDGE_PORTS", "") | ||
) | ||
@settings["BRIDGE_PORTS"] = selected_bridge_ports.join(" ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP: selected_bridge_ports
is only used once, from here, and it is a one line method hiding 1000 lines away.
Readability suffers.
) | ||
@settings["BRIDGE_PORTS"] = selected_bridge_ports.join(" ") | ||
|
||
LanItems.bridge_ports = @settings["BRIDGE_PORTS"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP: So @settings["BRIDGE_PORTS"]
is a String but @settings["SLAVES"]
is an Array. WTF. I know this is a bit out of focus, but could we at least document it and add a FIXME to unify it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, and is how differs also in configuration per interface. As bonding master is configured as:
BONDING_SLAVE0='eth0'
BONDING_SLAVE1='eth1'
while bridge_ports are configured as
BRIDGE_PORTS='eth0 eth1'
and more or less it are documented in LanItems also them are published variables so it means changed them we would be changing public interface, isn't it?
https://github.com/yast/yast-network/blob/master/src/modules/LanItems.rb#L2617
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me the biggest problem is the new pop-up which I think should not be introduced. The rest is implementation details.
@mchf what is your overall comment on this PR?
@@ -732,7 +732,7 @@ def IsBondable(bondMaster, itemId) | |||
# @param [Fixnum] itemId index into LanItems::Items | |||
# TODO: bridgeMaster is not used yet bcs detection of bridge master |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This TODO is no longer valid
@mchf @mvidner So i was in doubt if just duplicate current behavior or try to unify it with bonding. |
# @param [String] ip | ||
# @return [String] empty string if given ip is 0.0.0.0; given ip | ||
# otherwise | ||
def bridge_ip(ip) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be bridge_port_ip
Otherwise SetDeviceVars overwrites default empty string in LanItems#bridge_ports (hardcoded in the code) by nil when creating new bridge.
Has been replaced by #448 |
I have unified the configuration overview with bridges involved with the bonding one as you can see in the screenshots. There have been fixed also some small issue.
Bond overview
Bridge overview
Old bridge configuration
New bridge configuration