Skip to content

Commit

Permalink
(WIP) New routing client, and routing_helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
teclator committed Mar 25, 2019
1 parent c67d86c commit fb0838e
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 103 deletions.
96 changes: 96 additions & 0 deletions src/lib/y2network/clients/routing_auto.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Copyright (c) [2019] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "yast"
require "installation/auto_client"
require "y2network/config"
require "y2network/routing_helpers"

Yast.import "NetworkInterfaces"
Yast.import "Lan"

module Y2Network
module Clients
# This class is reponsible of the autoinstallation routing configuration.
class RoutingAuto < ::Installation::AutoClient
include RoutingHelpers
include Yast::I18n
include Yast::Logger

class << self
# @return [Boolean] whether the AutoYaST configuration has been
# modified or not
attr_accessor :changed
end

# Constructor
def initialize
textdomain "network"
end

# Import routing configuration
#
# @param profile [Hash] routing profile section to be imported
# @return [Boolean]
def import(profile = {})
return unless config
ip_forward = profile.fetch("ip_forward", false)
ipv4_forward = profile.fetch("ipv4_forward", ip_forward)
ipv6_forward = profile.fetch("ipv6_forward", ip_forward)

interfaces = find_interfaces
routes = profile.fetch("routes", []).map { |r| build_route(interfaces, r) }
tables = [Y2Network::RoutingTable.new(routes)]
config.routing =
Y2Network::RoutingConfig.new(tables: [routing_table],
forward_v4: ipv4_forward,
forward_v6: ipv6_forward)
end

def export
return {} unless config

config.routing.to_h
end

def reset
self.class.changed = false
end

def change
log.info "Pending implementation"
end

def modified
!!self.class.changed
end

def modified!
self.class.changed = true
end

private

def config
Yast::Lan.configs.find { |c| c.id == "system" }
end
end
end
end

71 changes: 0 additions & 71 deletions src/lib/y2network/config_reader/routing_helpers.rb

This file was deleted.

2 changes: 1 addition & 1 deletion src/lib/y2network/config_reader/sysconfig.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# find current contact information at www.suse.com.
require "y2network/config"
require "y2network/routing_config"
require "y2network/config_reader/routing_helpers"
require "y2network/routing_helpers"

Yast.import "NetworkInterfaces"
Yast.import "Routing"
Expand Down
34 changes: 3 additions & 31 deletions src/lib/y2network/config_writer/sysconfig.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# find current contact information at www.suse.com.

require "yast"
require "y2network/routing_helpers"

Yast.import "Routing"

module Y2Network
Expand All @@ -27,6 +29,7 @@ module ConfigWriter
# Ideally, it should be responsible of writing the changes to the underlying
# system. But, for the time being, it just relies in {Yast::Routing}.
class Sysconfig
include RoutingHelpers
# Writes the configuration into YaST network related modules
#
# @param config [Y2Network::Config] Configuration to write
Expand All @@ -38,37 +41,6 @@ def write(config)
"routes" => routes
)
end

private

# Returns a hash containing the route information to be imported into {Yast::Routing}
#
# @param route [Y2Network::Route]
# @return [Hash]
def route_to_hash(route)
hash =
if route.default?
{ "destination" => "-", "netmask" => "-" }
else
{ "destination" => route.to.to_s, "netmask" => netmask(route.to) }
end
hash.merge(
"gateway" => route.gateway ? route.gateway.to_s : "-",
"device" => route.interface == :any ? "-" : route.interface.name
)
end

IPV4_MASK = "255.255.255.255".freeze
IPV6_MASK = "fffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".freeze

# Returns the netmask
#
# @param ip [IPAddr]
# @return [IPAddr]
def netmask(ip)
mask = ip.ipv4? ? IPV4_MASK : IPV6_MASK
IPAddr.new(mask).mask(ip.prefix).to_s
end
end
end
end
11 changes: 11 additions & 0 deletions src/lib/y2network/routing_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "y2network/routing_helpers"

module Y2Network
# This class stores general routing configuration options, like IP forwarding
# configuration.
Expand All @@ -41,5 +44,13 @@ def initialize(tables: [], forward_v4: false, forward_v6: false)
def routes
tables.flat_map(&:routes)
end

def to_h
{
"ipv4_forward" => forward_v4,
"ipv6_forward" => forward_v6,
"routes" => routes.map { |r| route_to_hash(r) }
}
end
end
end
98 changes: 98 additions & 0 deletions src/lib/y2network/routing_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copyright (c) [2019] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.
require "y2network/interface"
require "y2network/routing_table"
require "y2network/route"

module Y2Network
module RoutingHelpers

private

MISSING_VALUE = "-".freeze
private_constant :MISSING_VALUE

# Find network interfaces
#
# @return [Array<Interface>] Detected interfaces
# @see Yast::NetworkInterfaces.Read
def find_interfaces
Yast::NetworkInterfaces.Read
# TODO: for the time being, we are just relying in the underlying stuff.
Yast::NetworkInterfaces.List("").map do |name|
Y2Network::Interface.new(name)
end
end


# Build a route given a hash from the SCR agent
#
# @param interfaces [Array<Interface>] List of detected interfaces
# @param hash [Hash] Hash from the `.routes` SCR agent
# @return Route
def build_route(interfaces, hash)
iface = interfaces.find { |i| i.name == hash["device"] }
Y2Network::Route.new(
to: build_ip(hash["destination"], hash["netmask"]) || :default,
interface: iface,
gateway: build_ip(hash["gateway"], MISSING_VALUE)
)
end

# Given an IP and a netmask, returns a valid IPAddr object
#
# @param ip_str [String] IP address; {MISSING_VALUE} means that the IP is not defined
# @param netmask_str [String] Netmask; {MISSING_VALUE} means that no netmask was specified
# @return [IPAddr,nil] The IP address or `nil` if the IP is missing
def build_ip(ip_str, netmask_str = MISSING_VALUE)
return nil if ip_str == MISSING_VALUE
ip = IPAddr.new(ip_str)
netmask_str == MISSING_VALUE ? ip : ip.mask(netmask_str)
end

# Returns a hash containing the route information to be imported into {Yast::Routing}
#
# @param route [Y2Network::Route]
# @return [Hash]
def route_to_hash(route)
hash =
if route.default?
{ "destination" => "-", "netmask" => "-" }
else
{ "destination" => route.to.to_s, "netmask" => netmask(route.to) }
end
hash.merge(
"gateway" => route.gateway ? route.gateway.to_s : "-",
"device" => route.interface == :any ? "-" : route.interface.name
)
end

IPV4_MASK = "255.255.255.255".freeze
IPV6_MASK = "fffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".freeze

# Returns the netmask
#
# @param ip [IPAddr]
# @return [IPAddr]
def netmask(ip)
mask = ip.ipv4? ? IPV4_MASK : IPV6_MASK
IPAddr.new(mask).mask(ip.prefix).to_s
end
end
end
3 changes: 3 additions & 0 deletions src/modules/Lan.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ def main
@initialized = false

@backend = nil

# @return [Array<Y2Network::Config>]
@configs = []
end

#------------------
Expand Down

0 comments on commit fb0838e

Please sign in to comment.