Hello community, here is the log from the commit of package yast2-network for openSUSE:Factory checked in at 2017-04-12 17:10:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yast2-network (Old) and /work/SRC/openSUSE:Factory/.yast2-network.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-network" Wed Apr 12 17:10:39 2017 rev:371 rq:487401 version:3.2.24 Changes: -------- --- /work/SRC/openSUSE:Factory/yast2-network/yast2-network.changes 2017-03-29 13:22:21.867179933 +0200 +++ /work/SRC/openSUSE:Factory/.yast2-network.new/yast2-network.changes 2017-04-12 17:10:40.734293297 +0200 @@ -1,0 +2,23 @@ +Tue Apr 4 11:48:24 WEST 2017 - [email protected] + +- bsc#956755 + - Don't propose wlan interfaces for the virtualization bridge. +- 3.2.24 + +------------------------------------------------------------------- +Mon Apr 3 08:27:26 UTC 2017 - [email protected] + +- bnc#927629 + - improved adding routes. Accepts netmask or prefix length. + - fixed column name in add route dialog from Genmask to more + common Netmask +- 3.2.23 + +------------------------------------------------------------------- +Thu Mar 30 13:52:36 WEST 2017 - [email protected] + +- Fix typo in edit_nic_name dialog using bus_id instead of busid + (bsc#1031120) +- 3.2.22 + +------------------------------------------------------------------- Old: ---- yast2-network-3.2.21.tar.bz2 New: ---- yast2-network-3.2.24.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-network.spec ++++++ --- /var/tmp/diff_new_pack.OFqmzi/_old 2017-04-12 17:10:41.822139301 +0200 +++ /var/tmp/diff_new_pack.OFqmzi/_new 2017-04-12 17:10:41.826138735 +0200 @@ -17,7 +17,7 @@ Name: yast2-network -Version: 3.2.21 +Version: 3.2.24 Release: 0 BuildArch: noarch ++++++ yast2-network-3.2.21.tar.bz2 -> yast2-network-3.2.24.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/package/yast2-network.changes new/yast2-network-3.2.24/package/yast2-network.changes --- old/yast2-network-3.2.21/package/yast2-network.changes 2017-03-22 13:09:17.716003918 +0100 +++ new/yast2-network-3.2.24/package/yast2-network.changes 2017-04-11 16:51:32.229154641 +0200 @@ -1,4 +1,27 @@ ------------------------------------------------------------------- +Tue Apr 4 11:48:24 WEST 2017 - [email protected] + +- bsc#956755 + - Don't propose wlan interfaces for the virtualization bridge. +- 3.2.24 + +------------------------------------------------------------------- +Mon Apr 3 08:27:26 UTC 2017 - [email protected] + +- bnc#927629 + - improved adding routes. Accepts netmask or prefix length. + - fixed column name in add route dialog from Genmask to more + common Netmask +- 3.2.23 + +------------------------------------------------------------------- +Thu Mar 30 13:52:36 WEST 2017 - [email protected] + +- Fix typo in edit_nic_name dialog using bus_id instead of busid + (bsc#1031120) +- 3.2.22 + +------------------------------------------------------------------- Tue Mar 21 09:24:29 UTC 2017 - [email protected] - adapt to new version of cfa (new cfa needed for bsc#1023204) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/package/yast2-network.spec new/yast2-network-3.2.24/package/yast2-network.spec --- old/yast2-network-3.2.21/package/yast2-network.spec 2017-03-22 13:09:17.716003918 +0100 +++ new/yast2-network-3.2.24/package/yast2-network.spec 2017-04-11 16:51:32.229154641 +0200 @@ -17,7 +17,7 @@ Name: yast2-network -Version: 3.2.21 +Version: 3.2.24 Release: 0 BuildArch: noarch diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/src/include/network/lan/help.rb new/yast2-network-3.2.24/src/include/network/lan/help.rb --- old/yast2-network-3.2.21/src/include/network/lan/help.rb 2017-03-22 13:09:17.932003918 +0100 +++ new/yast2-network-3.2.24/src/include/network/lan/help.rb 2017-04-11 16:51:32.233154641 +0200 @@ -98,8 +98,12 @@ ) + _( "<p>For each route, enter destination network IP address, gateway address,\n" \ - "and netmask. To omit any of these values, use a dash sign \"-\". Select\n" \ - "the device through which the traffic to the defined network will be routed.\"-\" is an alias for any interface.</p>\n" + "and netmask. You can use either IPv4 netmask or prefix length when defining\n" \ + "network part of route. Prefix length has to be prefixed using '/'.\n" \ + "To omit any of these values, use a dash sign \"-\". Select\n" \ + "the device through which the traffic to the defined network will be routed.\"-\" is an alias for any interface.\n" \ + "Please note that in case of IPv6 networks only prefix length is accepted\n" \ + "for netmask definition.</p>\n" ) + # Routing dialog help 2/2 _( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/src/include/network/services/routing.rb new/yast2-network-3.2.24/src/include/network/services/routing.rb --- old/yast2-network-3.2.21/src/include/network/services/routing.rb 2017-03-22 13:09:17.968003918 +0100 +++ new/yast2-network-3.2.24/src/include/network/services/routing.rb 2017-04-11 16:51:32.237154641 +0200 @@ -86,7 +86,7 @@ # Table header 2/4 _("Gateway"), # Table header 3/4 - _("Genmask"), + _("Netmask"), # Table header 4/4 _("Device"), # Table header 5/4 @@ -140,6 +140,24 @@ } end + # Validates user's input obtained from Netmask field + # + # It currently allows to use netmask for IPv4 (e.g. 255.0.0.0) or + # prefix length. If prefix length is used it has to start with '/'. + # For IPv6 network, only prefix length is allowed. + # + # @param [String] netmask or /<prefix length> + def valid_netmask?(netmask) + return false if netmask.nil? || netmask.empty? + return true if Netmask.Check4(netmask) + + if netmask.start_with?("/") + return true if netmask[1..-1].to_i.between?(1, 128) + end + + false + end + # Route edit dialog # @param [Fixnum] id id of the edited route # @param [Yast::Term] entry edited entry @@ -168,7 +186,7 @@ InputField( Id(:genmask), Opt(:hstretch), - _("Ge&nmask"), + _("&Netmask"), Ops.get_string(entry, 3, "-") )) ), @@ -218,11 +236,8 @@ Ops.add(Ops.add(IP.ValidChars, "default"), "/-") ) UI.ChangeWidget(Id(:gateway), :ValidChars, Ops.add(IP.ValidChars, "-")) - UI.ChangeWidget( - Id(:genmask), - :ValidChars, - Ops.add(Netmask.ValidChars, "-") - ) + # user can enter IPv4 netmask or prefix length (has to start with '/') + UI.ChangeWidget(Id(:genmask), :ValidChars, Netmask.ValidChars + "-/") if entry == term(:empty) UI.SetFocus(Id(:destination)) @@ -234,7 +249,6 @@ route = nil loop do - route = nil ret = UI.UserInput break if ret != :ok @@ -258,7 +272,7 @@ end route = Builtins.add(route, val) val = Convert.to_string(UI.QueryWidget(Id(:genmask), :Value)) - if val != "-" && val != "0.0.0.0" && !Netmask.Check(val) + if val != "-" && val != "0.0.0.0" && !valid_netmask?(val) # Popup::Error text Popup.Error(_("Subnetmask is invalid.")) UI.SetFocus(Id(:genmask)) @@ -424,15 +438,44 @@ false end + # Converts route definition for storing in routes file + # + # Basically netmask field is obsolete, so it converts + # the record to use CIDR notation if netmask is defined. + # + # @param route [Hash] see {RoutingClass#Routes} + # @return [Hash] where netmask is "-" (CIDR flavor) + def convert_route_conf(route) + return route if route["netmask"] == "-" + + dest = route["destination"] + netmask = route["netmask"] + + if Netmask.Check4(netmask) + cidr = Netmask.ToBits(netmask) + elsif netmask.start_with?("/") + cidr = netmask[1..-1] + else + # if it is netmask then long netmask is not supported for IPv6 + # if it is prefix length (CIDR), then prefix it has to be prefixed by '/' + raise ArgumentError, "Invalid netmask or prefix length: #{netmask}" + end + + route["destination"] = "#{dest}/#{cidr}" + route["netmask"] = "-" + + route + end + def storeRouting(_key, _event) - route_conf = Builtins.maplist(@r_items) do |e| - { - "destination" => Ops.get_string(e, 1, ""), - "gateway" => Ops.get_string(e, 2, ""), - "netmask" => Ops.get_string(e, 3, ""), - "device" => Ops.get_string(e, 4, ""), - "extrapara" => Ops.get_string(e, 5, "") - } + route_conf = @r_items.map do |route| + convert_route_conf( + "destination" => route[1].to_s, + "gateway" => route[2].to_s, + "netmask" => route[3].to_s, + "device" => route[4].to_s, + "extrapara" => route[5].to_s + ) end @defgw = UI.QueryWidget(Id(:gw), :Value) @@ -440,27 +483,21 @@ @defgw6 = UI.QueryWidget(Id(:gw6), :Value) @defgwdev6 = UI.QueryWidget(Id(:gw6dev), :Value) - if @defgw != "" - route_conf = Builtins.add( - route_conf, - "destination" => "default", - "gateway" => @defgw, - "netmask" => "-", - "device" => @defgwdev - ) - end - - if @defgw6 != "" - route_conf = Builtins.add( - route_conf, - "destination" => "default", - "gateway" => @defgw6, - "netmask" => "-", - "device" => @defgwdev6 - ) - end + route_conf << { + "destination" => "default", + "gateway" => @defgw, + "netmask" => "-", + "device" => @defgwdev + } if [email protected]? + + route_conf << { + "destination" => "default", + "gateway" => @defgw6, + "netmask" => "-", + "device" => @defgwdev6 + } if [email protected]? - Routing.Routes = deep_copy(route_conf) + Routing.Routes = route_conf Routing.Forward_v4 = UI.QueryWidget(Id(:forward_v4), :Value) Routing.Forward_v6 = UI.QueryWidget(Id(:forward_v6), :Value) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/src/lib/network/edit_nic_name.rb new/yast2-network-3.2.24/src/lib/network/edit_nic_name.rb --- old/yast2-network-3.2.21/src/lib/network/edit_nic_name.rb 2017-03-22 13:09:17.992003918 +0100 +++ new/yast2-network-3.2.24/src/lib/network/edit_nic_name.rb 2017-04-11 16:51:32.241154641 +0200 @@ -103,7 +103,7 @@ ), Left( RadioButton( - Id(:busid), + Id(:bus_id), _("BusID: %s") % @bus_id ) ) @@ -122,7 +122,7 @@ when MAC_UDEV_ATTR UI.ChangeWidget(Id(:udev_type), :CurrentButton, :mac) when BUSID_UDEV_ATTR - UI.ChangeWidget(Id(:udev_type), :CurrentButton, :busid) + UI.ChangeWidget(Id(:udev_type), :CurrentButton, :bus_id) else Builtins.y2error("Unknown udev rule.") end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/src/modules/Lan.rb new/yast2-network-3.2.24/src/modules/Lan.rb --- old/yast2-network-3.2.21/src/modules/Lan.rb 2017-03-22 13:09:18.008003918 +0100 +++ new/yast2-network-3.2.24/src/modules/Lan.rb 2017-04-11 16:51:32.241154641 +0200 @@ -818,155 +818,64 @@ def IfcfgsToSkipVirtualizedProposal skipped = [] - Builtins.foreach(LanItems.Items) do |current, _config| - ifcfg = Ops.get_string(LanItems.Items, [current, "ifcfg"], "") - if NetworkInterfaces.GetType(ifcfg) == "br" - NetworkInterfaces.Edit(ifcfg) - Builtins.y2milestone( - "Bridge %1 with ports (%2) found", - ifcfg, - Ops.get_string(NetworkInterfaces.Current, "BRIDGE_PORTS", "") - ) - skipped = Builtins.add(skipped, ifcfg) - Builtins.foreach( - Builtins.splitstring( - Ops.get_string(NetworkInterfaces.Current, "BRIDGE_PORTS", ""), - " " - ) - ) { |port| skipped = Builtins.add(skipped, port) } - end - if NetworkInterfaces.GetType(ifcfg) == "bond" - NetworkInterfaces.Edit(ifcfg) - Builtins.foreach(LanItems.GetBondSlaves(ifcfg)) do |slave| - Builtins.y2milestone( - "For interface %1 found slave %2", - ifcfg, - slave - ) - skipped = Builtins.add(skipped, slave) + LanItems.Items.each do |_current, config| + ifcfg = config["ifcfg"] + ifcfg_type = NetworkInterfaces.GetType(ifcfg) + + case ifcfg_type + when "br" + skipped << ifcfg + + bridge_ports = NetworkInterfaces.GetValue(ifcfg, "BRIDGE_PORTS").to_s + + bridge_ports.split.each { |port| skipped << port } + when "bond" + LanItems.GetBondSlaves(ifcfg).each do |slave| + log.info("For interface #{ifcfg} found slave #{slave}") + skipped << slave end + + # Skip also usb and wlan devices as they are not good for bridge proposal (bnc#710098) + when "usb", "wlan" + log.info("#{ifcfg_type} device #{ifcfg} skipped from bridge proposal") + skipped << ifcfg end - # Skip also usb device as it is not good for bridge proposal (bnc#710098) - if NetworkInterfaces.GetType(ifcfg) == "usb" - NetworkInterfaces.Edit(ifcfg) - Builtins.y2milestone( - "Usb device %1 skipped from bridge proposal", - ifcfg - ) - skipped = Builtins.add(skipped, ifcfg) - end - if NetworkInterfaces.GetValue(ifcfg, "STARTMODE") == "nfsroot" - Builtins.y2milestone( - "Skipped %1 interface from bridge slaves because of nfsroot.", - ifcfg - ) - skipped = Builtins.add(skipped, ifcfg) - end - end - Builtins.y2milestone("Skipped interfaces : %1", skipped) - deep_copy(skipped) - end - def ProposeVirtualized - # in case of virtualization use special proposal - # collect all interfaces that will be skipped from bridged proposal - skipped = IfcfgsToSkipVirtualizedProposal() + next unless NetworkInterfaces.GetValue(ifcfg, "STARTMODE") == "nfsroot" - # first configure all connected unconfigured devices with dhcp (with default parameters) - Builtins.foreach(LanItems.Items) do |number, lanitem| - if IsNotEmpty( - Ops.get_string(Convert.to_map(lanitem), ["hwinfo", "dev_name"], "") - ) - LanItems.current = number - valid = Ops.get_boolean( - LanItems.getCurrentItem, - ["hwinfo", "link"], - false - ) == true - if !valid - Builtins.y2warning("item number %1 has link:false detected", number) - elsif Ops.get_string(LanItems.getCurrentItem, ["hwinfo", "type"], "") == "wlan" - Builtins.y2warning("not proposing WLAN interface") - valid = false - end - if !LanItems.IsCurrentConfigured && valid && - !Builtins.contains( - skipped, - Ops.get_string( - LanItems.getCurrentItem, - ["hwinfo", "dev_name"], - "" - ) - ) - Builtins.y2milestone("Not configured - start proposing") - LanItems.ProposeItem - end - end + log.info("Skipped #{ifcfg} interface from bridge slaves because of nfsroot.") + + skipped << ifcfg end + log.info("Skipped interfaces : #{skipped}") + skipped + end + + def ProposeVirtualized # then each configuration (except bridges) move to the bridge # and add old device name into bridge_ports - Builtins.foreach(LanItems.Items) do |current, _config| - ifcfg = Ops.get_string(LanItems.Items, [current, "ifcfg"], "") - if Builtins.contains(skipped, ifcfg) - Builtins.y2milestone("Skipping interface %1", ifcfg) + LanItems.Items.each do |current, config| + ifcfg = config["ifcfg"].to_s + + bridge_name = format("br%s", NetworkInterfaces.GetFreeDevice("br")) + + if !LanItems.IsBridgeable(bridge_name, current) + log.info "The interface #{ifcfg} is not bridgeable." next - elsif Ops.greater_than(Builtins.size(ifcfg), 0) - NetworkInterfaces.Edit(ifcfg) - old_config = deep_copy(NetworkInterfaces.Current) - Builtins.y2debug("Old Config %1\n%2", ifcfg, old_config) - new_ifcfg = Builtins.sformat( - "br%1", - NetworkInterfaces.GetFreeDevice("br") - ) - Builtins.y2milestone( - "old configuration %1, bridge %2", - ifcfg, - new_ifcfg - ) - NetworkInterfaces.Name = new_ifcfg - # from bridge interface remove all bonding-related stuff - Builtins.foreach(NetworkInterfaces.Current) do |key, _value| - if Builtins.issubstring(key, "BONDING") - Ops.set(NetworkInterfaces.Current, key, nil) - end - end - Ops.set(NetworkInterfaces.Current, "BRIDGE", "yes") - Ops.set(NetworkInterfaces.Current, "BRIDGE_PORTS", ifcfg) - Ops.set(NetworkInterfaces.Current, "BRIDGE_STP", "off") - Ops.set(NetworkInterfaces.Current, "BRIDGE_FORWARDDELAY", "0") - # hardcode startmode (bnc#450670), it can't be ifplugd! - Ops.set(NetworkInterfaces.Current, "STARTMODE", "auto") - # remove description - will be replaced by new (real) one - NetworkInterfaces.Current = Builtins.remove( - NetworkInterfaces.Current, - "NAME" - ) - # remove ETHTOOLS_OPTIONS as it is useful only for real hardware - NetworkInterfaces.Current = Builtins.remove( - NetworkInterfaces.Current, - "ETHTOOLS_OPTIONS" - ) - if NetworkInterfaces.Commit - # reconfigure existing device as newly created bridge's port - configure_as_bridge_port(ifcfg) - - Ops.set(LanItems.Items, [current, "ifcfg"], new_ifcfg) - LanItems.force_restart = true - Builtins.y2internal("List %1", NetworkInterfaces.List("")) - # re-read configuration to see new items in UI - LanItems.Read - - # note: LanItems.Read resets modification flag - # the Read is used as a trick how to update LanItems' internal - # cache according NetworkInterfaces' one. As NetworkInterfaces' - # cache was edited directly, LanItems is not aware of changes. - LanItems.SetModified - end - else - Builtins.y2warning("empty ifcfg") end + + LanItems.current = current + + propose_current_item!(config) if !LanItems.IsCurrentConfigured + + next unless configure_as_bridge!(ifcfg, bridge_name) + + # reconfigure existing device as newly created bridge's port + configure_as_bridge_port(ifcfg) + + refresh_lan_items end nil @@ -1088,6 +997,68 @@ LanItems.reload_config(ifaces) end end + + def configure_as_bridge!(ifcfg, bridge_name) + return false if !NetworkInterfaces.Edit(ifcfg) + + old_config = deep_copy(NetworkInterfaces.Current) + log.debug("Old Config #{ifcfg}\n#{old_config}") + + log.info("old configuration #{ifcfg}, bridge #{bridge_name}") + + NetworkInterfaces.Name = bridge_name + + # from bridge interface remove all bonding-related stuff + NetworkInterfaces.Current.each do |key, _value| + NetworkInterfaces.Current[key] = nil if key.include? "BONDING" + end + + NetworkInterfaces.Current["BRIDGE"] = "yes" + NetworkInterfaces.Current["BRIDGE_PORTS"] = ifcfg + NetworkInterfaces.Current["BRIDGE_STP"] = "off" + NetworkInterfaces.Current["BRIDGE_FORWARDDELAY"] = "0" + + # hardcode startmode (bnc#450670), it can't be ifplugd! + NetworkInterfaces.Current["STARTMODE"] = "auto" + # remove description - will be replaced by new (real) one + NetworkInterfaces.Current.delete("NAME") + # remove ETHTOOLS_OPTIONS as it is useful only for real hardware + NetworkInterfaces.Current.delete("ETHTOOLS_OPTIONS") + + NetworkInterfaces.Commit + end + + def propose_current_item!(config) + # first configure all connected unconfigured devices with dhcp (with default parameters) + hwinfo = config.fetch("hwinfo", {}) + + if hwinfo.fetch("link", false) == true + log.warn("item number #{LanItems.current} has link:false detected") + + return false + end + + if hwinfo.fetch("type", "") == "wlan" + log.warn("not proposing WLAN interface") + + return false + end + + LanItems.ProposeItem + end + + def refresh_lan_items + LanItems.force_restart = true + log.info("List #{NetworkInterfaces.List("")}") + # re-read configuration to see new items in UI + LanItems.Read + + # note: LanItems.Read resets modification flag + # the Read is used as a trick how to update LanItems' internal + # cache according NetworkInterfaces' one. As NetworkInterfaces' + # cache was edited directly, LanItems is not aware of changes. + LanItems.SetModified + end end Lan = LanClass.new diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/src/modules/LanItems.rb new/yast2-network-3.2.24/src/modules/LanItems.rb --- old/yast2-network-3.2.21/src/modules/LanItems.rb 2017-03-22 13:09:18.016003918 +0100 +++ new/yast2-network-3.2.24/src/modules/LanItems.rb 2017-04-11 16:51:32.241154641 +0200 @@ -304,13 +304,12 @@ return nil if !IsItemConfigured(itemId) devname = GetDeviceName(itemId) - devtype = NetworkInterfaces.GetType(devname) - Convert.convert( - Ops.get(NetworkInterfaces.FilterDevices("netcard"), [devtype, devname]), - from: "any", - to: "map <string, any>" - ) + NetworkInterfaces.FilterDevices("netcard").each do |_dev_type, conf| + return conf[devname] if conf[devname] + end + + nil end def GetCurrentMap @@ -824,9 +823,8 @@ when "br" log.debug("Excluding lan item (#{itemId}: #{devname}) - is bridge") return false - - when "tun" - log.debug("Excluding lan item (#{itemId}: #{devname}) - is tun") + when "tun", "usb", "wlan" + log.debug("Excluding lan item (#{itemId}: #{devname}) - is #{devtype}") return false end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/src/modules/Routing.rb new/yast2-network-3.2.24/src/modules/Routing.rb --- old/yast2-network-3.2.21/src/modules/Routing.rb 2017-03-22 13:09:18.016003918 +0100 +++ new/yast2-network-3.2.24/src/modules/Routing.rb 2017-04-11 16:51:32.245154641 +0200 @@ -38,6 +38,26 @@ include Logger + # @attribute Routes + # Entries of a routes(5) style routing table. + # + # An array of hashes whose keys are + # + # - "destination" + # May be "default", "10.20.0.0/16" (then netmask is "-") + # or "10.20.0.0" (then netmask must be a quad) + # - "gateway" + # - "netmask" + # - "device" + # - "extrapara" + # + # but the values depend on which flavor of RoutingHash this is: + # - the quad flavor: netmask has the form "255.255.0.0" + # - the CIDR flavor: netmask must be "-" (and destination is 1.1.1.1/16) + # - the slash flavor (only for the UI): netmask has the form "/16" + # + # @return [Array<Hash>] routing table entries + # @Orig_Routes [Array] array of hashes. Caches known routes # # @Orig_Forward_v4 [Boolean] current status of ipv4 forwarding @@ -161,7 +181,7 @@ # Configures system for IPv4 forwarding # - # @param [Boolean] true when forwarding should be enabled + # @param forward_ipv4 [Boolean] true when forwarding should be enabled def write_ipv4_forwarding(forward_ipv4) sysctl_val = forward_ipv4 ? "1" : "0" @@ -182,7 +202,7 @@ # Configures system for IPv6 forwarding # - # @param [Boolean] true when forwarding should be enabled + # @param forward_ipv6 [Boolean] true when forwarding should be enabled def write_ipv6_forwarding(forward_ipv6) sysctl_val = forward_ipv6 ? "1" : "0" @@ -205,6 +225,32 @@ write_ipv6_forwarding(@Forward_v6) end + # Converts routes config as read from system into well-defined format + # + # Expects list of hashes as param. Hash should contain keys "destination", + # "gateway", "netmask", "device", "extrapara" + # + # Currently it converts "destination" in CIDR format (<ip>/<prefix_len>) + # and keeps just <ip> part in "destination" and puts "/<prefix_len>" into + # "netmask" + # + # @param routes [Array<Hash>] in quad or CIDR flavors (see {#Routes}) + # @return [Array<Hash>] in quad or slash flavor + def normalize_routes(routes) + return routes if routes.nil? || routes.empty? + + deep_copy(routes).map do |route| + subnet, prefix = route["destination"].split("/") + + if !prefix.nil? + route["destination"] = subnet + route["netmask"] = "/#{prefix}" + end + + route + end + end + # Read routing settings # If no routes, sets a default gateway from Detection # @return true if success @@ -234,6 +280,8 @@ end @Routes.uniq! + + @Routes = normalize_routes(@Routes) log.info("Routes=#{@Routes}") ReadIPForwarding() @@ -439,7 +487,7 @@ end # Create routing text summary - # @returns [String] summary text + # @return [String] summary text def Summary return "" if @Routes.nil? || @Routes.empty? diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/test/Makefile.am new/yast2-network-3.2.24/test/Makefile.am --- old/yast2-network-3.2.21/test/Makefile.am 2017-03-22 13:09:18.028003918 +0100 +++ new/yast2-network-3.2.24/test/Makefile.am 2017-04-11 16:51:32.245154641 +0200 @@ -29,6 +29,7 @@ remote_test.rb \ routines_test.rb \ routing_test.rb \ + routing_helpers_test.rb \ s390_helpers_test.rb \ suse_firewall_4_network_test.rb \ udev_test.rb \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/test/lan_test.rb new/yast2-network-3.2.24/test/lan_test.rb --- old/yast2-network-3.2.21/test/lan_test.rb 2017-03-22 13:09:18.100003918 +0100 +++ new/yast2-network-3.2.24/test/lan_test.rb 2017-04-11 16:51:32.249154641 +0200 @@ -224,3 +224,168 @@ expect(Yast::Lan.readIPv6).to be true end end + +describe "LanClass#IfcfgsToSkipVirtualizedProposal" do + let(:items) do + { + "0" => { "ifcfg" => "bond0" }, + "1" => { "ifcfg" => "br0" }, + "2" => { "ifcfg" => "eth0" }, + "3" => { "ifcfg" => "eth1" }, + "4" => { "ifcfg" => "wlan0" }, + "5" => { "ifcfg" => "wlan1" } + } + end + + let(:current_interface) do + { + "ONBOOT" => "yes", + "BOOTPROTO" => "dhcp", + "DEVICE" => "br1", + "BRIDGE" => "yes", + "BRIDGE_PORTS" => "eth1", + "BRIDGE_STP" => "off", + "IPADDR" => "10.0.0.1", + "NETMASK" => "255.255.255.0" + } + end + + context "when various interfaces are present in the system" do + before do + allow(Yast::NetworkInterfaces).to receive(:GetType).with("br0").and_return("br") + allow(Yast::NetworkInterfaces).to receive(:GetType).with("bond0").and_return("bond") + allow(Yast::NetworkInterfaces).to receive(:GetType).with("eth0").and_return("eth") + allow(Yast::NetworkInterfaces).to receive(:GetType).with("eth1").and_return("eth") + allow(Yast::NetworkInterfaces).to receive(:GetType).with("wlan0").and_return("usb") + allow(Yast::NetworkInterfaces).to receive(:GetType).with("wlan1").and_return("wlan") + allow(Yast::NetworkInterfaces).to receive(:Current).and_return(current_interface) + allow(Yast::NetworkInterfaces).to receive(:GetValue).and_return(nil) + allow(Yast::LanItems).to receive(:Items).and_return(items) + end + + context "and one of them is a bridge" do + it "returns an array containining the bridge interface" do + (expect Yast::Lan.IfcfgsToSkipVirtualizedProposal).to include("br0") + end + + it "returns an array containing the bridged interfaces" do + allow(Yast::NetworkInterfaces).to receive(:GetValue) + .with("br0", "BRIDGE_PORTS").and_return("eth1") + + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).to include("eth1") + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).to_not include("eth0") + end + end + + context "and one of them is a bond" do + let(:current_interface) do + { + "BOOTPROTO" => "static", + "BONDING_MASTER" => "yes", + "DEVICE" => "bond0", + "BONDING_SLAVE" => "eth0" + } + end + + it "returns an array containing the bonded interfaces" do + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).not_to include("bond0") + end + end + + context "and one of them is an usb or a wlan interface" do + it "returns an array containing the interface" do + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).to include("wlan0", "wlan1") + end + end + + context "and the interface startmode is 'nfsroot'" do + it "returns an array containing the interface" do + allow(Yast::NetworkInterfaces).to receive(:GetValue) + .with("eth0", "STARTMODE").and_return("nfsroot") + + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).to include("eth0") + end + end + + context "and all the interfaces are bridgeable" do + let(:current_item) do + { + "BOOTPROTO" => "dhcp", + "STARTMODE" => "auto" + } + end + it "returns an empty array" do + allow(Yast::NetworkInterfaces).to receive(:GetType).and_return("eth") + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).to eql([]) + end + end + end + + context "there is no interfaces in the system" do + let(:items) { {} } + it "returns an empty array" do + expect(Yast::Lan.IfcfgsToSkipVirtualizedProposal).to eql([]) + end + end +end + +describe "LanClass#ProposeVirtualized" do + + before do + allow(Yast::NetworkInterfaces).to receive(:GetFreeDevice).with("br").and_return("1") + allow(Yast::LanItems).to receive(:IsCurrentConfigured).and_return(true) + allow(Yast::Lan).to receive(:configure_as_bridge!) + allow(Yast::Lan).to receive(:configure_as_bridge_port) + + allow(Yast::LanItems).to receive(:Items) + .and_return( + 0 => { "ifcfg" => "eth0" }, 1 => { "ifcfg" => "wlan0", 2 => { "ifcfg" => "br0" } } + ) + end + + context "when an interface is not bridgeable" do + it "doest not propose the interface" do + allow(Yast::LanItems).to receive(:IsBridgeable).with(anything, anything).and_return(false) + allow(Yast::LanItems).to receive(:IsCurrentConfigured).and_return(false) + expect(Yast::Lan).not_to receive(:propose_current_item!).with("ifcfg" => "wlan0") + + Yast::Lan.ProposeVirtualized + end + end + + context "when an interface is bridgeable" do + before do + allow(Yast::LanItems).to receive(:IsBridgeable).with(anything, 0).and_return(true) + allow(Yast::LanItems).to receive(:IsBridgeable).with(anything, 1).and_return(false) + allow(Yast::LanItems).to receive(:IsBridgeable).with(anything, 2).and_return(false) + end + + it "configures the interface with defaults before anything if not configured" do + allow(Yast::LanItems).to receive(:IsCurrentConfigured).and_return(false) + expect(Yast::Lan).to receive(:propose_current_item!).with("ifcfg" => "eth0") + + Yast::Lan.ProposeVirtualized + end + + it "configures a new bridge with the given interface as a bridge port" do + expect(Yast::Lan).to receive(:configure_as_bridge!).with("eth0", "br1") + + Yast::Lan.ProposeVirtualized + end + + it "configures the given interface as a bridge port" do + expect(Yast::Lan).to receive(:configure_as_bridge!).with("eth0", "br1").and_return(true) + expect(Yast::Lan).to receive(:configure_as_bridge_port).with("eth0") + + Yast::Lan.ProposeVirtualized + end + + it "refreshes lan items with the new interfaces" do + expect(Yast::Lan).to receive(:configure_as_bridge!).with("eth0", "br1").and_return(true) + expect(Yast::Lan).to receive(:configure_as_bridge_port).with("eth0") + expect(Yast::Lan).to receive(:refresh_lan_items) + + Yast::Lan.ProposeVirtualized + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/test/routing_helpers_test.rb new/yast2-network-3.2.24/test/routing_helpers_test.rb --- old/yast2-network-3.2.21/test/routing_helpers_test.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/yast2-network-3.2.24/test/routing_helpers_test.rb 2017-04-11 16:51:32.253154641 +0200 @@ -0,0 +1,81 @@ +#!/usr/bin/env rspec + +require_relative "test_helper" + +require "yast" + +class RoutingHelpers + def initialize + Yast.include self, "network/services/routing.rb" + end +end + +describe "RoutingHelpers" do + subject(:routing) { RoutingHelpers.new } + + describe "#convert_route_conf" do + let(:common_route_conf_part) do + { + "gateway" => "1.1.1.1", + "device" => "-", + "extrapara" => "" + } + end + let(:correct_route_conf) do + { + "destination" => "1.1.1.0/24", + "netmask" => "-" + }.merge(common_route_conf_part) + end + let(:obsolete_route_conf) do + { + "destination" => "1.1.1.0", + "netmask" => "255.255.255.0" + }.merge(common_route_conf_part) + end + + it "does nothing when route conf uses CIDR notation" do + expect(routing.convert_route_conf(correct_route_conf)).to eql correct_route_conf + end + + it "converts obsolete route conf to use CIDR notation" do + expect(routing.convert_route_conf(obsolete_route_conf)).to eql correct_route_conf + end + end + + describe "#valid_netmask?" do + it "accepts IPv4 netmask" do + expect(routing.valid_netmask?("255.0.0.0")).to be true + end + + it "accepts IPv4 prefix" do + expect(routing.valid_netmask?("/24")).to be true + end + + it "accepts IPv6 prefix" do + expect(routing.valid_netmask?("/128")).to be true + end + + it "declines IPv6 netmask" do + expect(routing.valid_netmask?("fe00::")).to be false + end + + it "declines nil or empty input" do + expect(routing.valid_netmask?("")).to be false + expect(routing.valid_netmask?(nil)).to be false + end + + it "declines malformed prefix" do + expect(routing.valid_netmask?("/255/")).to be false + expect(routing.valid_netmask?("/255")).to be false + expect(routing.valid_netmask?("/-255")).to be false + expect(routing.valid_netmask?("/0")).to be false + end + + it "declines malformed IPv4 netmask" do + expect(routing.valid_netmask?("/255.0.0.0")).to be false + expect(routing.valid_netmask?("255.0.255.0")).to be false + expect(routing.valid_netmask?("0.0.0.0")).to be false + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/test/routing_test.rb new/yast2-network-3.2.24/test/routing_test.rb --- old/yast2-network-3.2.21/test/routing_test.rb 2017-03-22 13:09:18.112003918 +0100 +++ new/yast2-network-3.2.24/test/routing_test.rb 2017-04-11 16:51:32.253154641 +0200 @@ -228,7 +228,10 @@ { ip_forward_v4: "1", ip_forward_v6: "0" } ].freeze - MOCKED_ROUTES = [{ "1" => "r1" }, { "2" => "r2" }].freeze + MOCKED_ROUTES = [ + { "destination" => "r1" }, + { "destination" => "r2" } + ].freeze CONFIGS_OS.each do |config| ipv4 = config[:ip_forward_v4] @@ -265,4 +268,30 @@ end end end + + describe "#normalize_routes" do + it "puts prefix length into netmask field when destination is in CIDR format" do + input_routes = [ + { + "destination" => "1.1.1.1/24" + } + ] + + result = Yast::Routing.normalize_routes(input_routes) + + expect(result.first["destination"]).to eql "1.1.1.1" + expect(result.first["netmask"]).to eql "/24" + end + + it "does nothing when netmask is used" do + input_routes = [ + { + "destination" => "1.1.1.1", + "netmask" => "255.0.0.0" + } + ] + + expect(Yast::Routing.normalize_routes(input_routes)).to eql input_routes + end + end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-network-3.2.21/test/test_helper.rb new/yast2-network-3.2.24/test/test_helper.rb --- old/yast2-network-3.2.21/test/test_helper.rb 2017-03-22 13:09:18.112003918 +0100 +++ new/yast2-network-3.2.24/test/test_helper.rb 2017-04-11 16:51:32.253154641 +0200 @@ -53,11 +53,8 @@ add_filter "/test/" end - # For coverage we need to load all ruby files - # Note that clients/ are excluded because they run too eagerly by design - Dir["#{srcdir}/{include,modules}/**/*.rb"].each do |f| - require_relative f - end + # track all ruby files under src + SimpleCov.track_files("#{srcdir}/**/*.rb") # use coveralls for on-line code coverage reporting at Travis CI if ENV["TRAVIS"]
