Skip to content
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

Closed
wants to merge 19 commits into from

Conversation

teclator
Copy link
Contributor

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

enslavedbond

Bridge overview

enslavedbridge

Old bridge configuration

old_bridge

New bridge configuration

new_bridge

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.721% when pulling d04b8df on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.721% when pulling d04b8df on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@@ -1039,7 +1042,6 @@ def Packages
# for wlan require iw instead of wireless-tools (bnc#539669)
"wlan" => "iw",
"vlan" => "vlan",
"br" => "bridge-utils",
Copy link
Contributor Author

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.

@teclator teclator changed the title Bridge handling improved (bsc#962824) [WIP] Bridge handling improved (bsc#962824) Sep 21, 2016
@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.721% when pulling 2acf172 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.729% when pulling f8c614f on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@@ -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", "")
Copy link
Contributor Author

@teclator teclator Sep 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this line to StoreBridge avoid current ports to be removed in case that the bridge ports tab is not visited.

Previously

bridge_ports_removed

After the fix

bridge_tab_fix

Copy link
Member

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 :-/

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.694% when pulling 2437213 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 46.63% when pulling 0084525 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

"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) }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are just adapting it when the bridge is edited as we can see in this gif:

ask_for_adapt

We could also ask for adapt the configuration when the enslaved interface is edited.

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mvidner

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.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.72% when pulling 0c4c35a on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@teclator teclator changed the title [WIP] Bridge handling improved (bsc#962824) Bridge handling improved (bsc#962824) Sep 23, 2016
@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.735% when pulling 38a91f2 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@teclator teclator changed the title Bridge handling improved (bsc#962824) [WIP] Bridge handling improved (bsc#962824) Sep 23, 2016
@teclator teclator added blog and removed blog labels Sep 23, 2016
- "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
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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"]
Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true .. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Member

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
Copy link
Member

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

Copy link
Contributor Author

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(" ")
Copy link
Member

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.

Copy link
Contributor Author

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

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 46.776% when pulling b48eba9 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

# 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"
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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)
Copy link
Member

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 ;-)

Copy link
Contributor Author

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

Copy link
Member

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)
Copy link
Contributor Author

@teclator teclator Sep 27, 2016

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?

Copy link
Member

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? ;-)

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 46.715% when pulling b15ccbc on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 46.796% when pulling dd91db4 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 46.796% when pulling 6f3fab4 on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

NetworkInterfaces.Edit(device)
unless NetworkInterfaces.Edit(device)
Lan.autoconf_slaves += [device] unless Lan.autoconf_slaves.include? device
return false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inconsistent return value

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@teclator what is this method supposed to return in this case, and in the normal case? Add a @return tag?

Copy link
Contributor Author

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.

https://github.com/teclator/yast-network/blob/bridge_overview_improvement/src/include/network/lan/bridge.rb#L92

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

https://github.com/teclator/yast-network/blob/bridge_overview_improvement/src/include/network/lan/bridge.rb#L113

@@ -60,6 +87,21 @@ def configure_as_bridge_port(device)

NetworkInterfaces.Commit
NetworkInterfaces.Add

NetworkInterfaces.Current = selected_interface
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 46.789% when pulling 95a7ced on teclator:bridge_overview_improvement into 825b7af on yast:SLE-12-SP2.

"eth12",
"tap0"
]
describe "#old_bridge_port_config?" do
Copy link
Member

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(" ")
Copy link
Member

@mvidner mvidner Oct 4, 2016

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"]
Copy link
Member

@mvidner mvidner Oct 4, 2016

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?

Copy link
Contributor Author

@teclator teclator Oct 4, 2016

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

Copy link
Member

@mvidner mvidner left a 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
Copy link
Member

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

@teclator
Copy link
Contributor Author

teclator commented Oct 4, 2016

@mchf @mvidner
I have doubts about what to do with the Popup and also about refreshing all the interfaces that were added to the bridge, as currently just the interfaces configuration was written but the interface was not updated, and you could see them as not configured and things like that.

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)
Copy link
Member

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.
@teclator
Copy link
Contributor Author

teclator commented Oct 14, 2016

Has been replaced by #448

@teclator teclator closed this Oct 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants