Skip to content

Commit

Permalink
Merge pull request #735 from yast/routing_cwm
Browse files Browse the repository at this point in the history
add initial object proposal for dialog routes and gateway cwm widget
  • Loading branch information
jreidinger committed Mar 22, 2019
2 parents fc694b8 + be16c36 commit a3f3a1a
Show file tree
Hide file tree
Showing 15 changed files with 603 additions and 202 deletions.
170 changes: 10 additions & 160 deletions src/include/network/services/routing.rb
Expand Up @@ -28,10 +28,14 @@
#
#
# Routing configuration dialogs

require "y2network/dialogs/route"

module Yast
module NetworkServicesRoutingInclude
include Yast::I18n
include Yast::UIShortcuts
include Yast::Logger

def initialize_network_services_routing(include_target)
Yast.import "UI"
Expand Down Expand Up @@ -93,158 +97,6 @@ def initialize_network_services_routing(include_target)
}
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
# @param [Array] devs available devices
# @return route or nil, if canceled
def RoutingEditDialog(id, entry, devs)
entry = deep_copy(entry)
devs = deep_copy(devs)

UI.OpenDialog(
Opt(:decorated),
MinWidth(60,
VBox(
HSpacing(1),
VBox(
HBox(
HWeight(70,
InputField(
Id(:destination),
Opt(:hstretch),
_("&Destination"),
Ops.get_string(entry, 1, "")
)),
HSpacing(1),
HWeight(30,
InputField(
Id(:genmask),
Opt(:hstretch),
_("&Netmask"),
Ops.get_string(entry, 3, "-")
))
),
HBox(
HWeight(70,
InputField(
Id(:gateway),
Opt(:hstretch),
_("&Gateway"),
Ops.get_string(entry, 2, "-")
)),
HSpacing(1),
HWeight(30,
ComboBox(
Id(:device),
Opt(:editable, :hstretch),
_("De&vice"),
devs
))
),
# ComboBox label
InputField(
Id(:options),
Opt(:hstretch),
Label.Options,
Ops.get_string(entry, 5, "")
)
),
HSpacing(1),
HBox(
PushButton(Id(:ok), Opt(:default), Label.OKButton),
PushButton(Id(:cancel), Label.CancelButton)
)
))
)

# Allow declaring route without iface (for gateway) #93996
# if empty, use '-' which stands for any
if Ops.get_string(entry, 4, "") != ""
UI.ChangeWidget(Id(:device), :Value, Ops.get_string(entry, 4, ""))
else
UI.ChangeWidget(Id(:device), :Items, devs)
end
UI.ChangeWidget(
Id(:destination),
:ValidChars,
Ops.add(Ops.add(IP.ValidChars, "default"), "/-")
)
UI.ChangeWidget(Id(:gateway), :ValidChars, Ops.add(IP.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))
else
UI.SetFocus(Id(:gateway))
end

ret = nil
route = nil

loop do
ret = UI.UserInput
break if ret != :ok

route = Item(Id(id))
val = Convert.to_string(UI.QueryWidget(Id(:destination), :Value))
slash = Builtins.search(val, "/")
noprefix = slash.nil? ? val : Builtins.substring(val, 0, slash)
if val != "default" && !IP.Check(noprefix)
# Popup::Error text
Popup.Error(_("Destination is invalid."))
UI.SetFocus(Id(:destination))
next
end
route = Builtins.add(route, val)
val = Convert.to_string(UI.QueryWidget(Id(:gateway), :Value))
if val != "-" && !IP.Check(val)
# Popup::Error text
Popup.Error(_("Gateway IP address is invalid."))
UI.SetFocus(Id(:gateway))
next
end
route = Builtins.add(route, val)
val = Convert.to_string(UI.QueryWidget(Id(:genmask), :Value))
if val != "-" && !valid_netmask?(val)
# Popup::Error text
Popup.Error(_("Subnetmask is invalid."))
UI.SetFocus(Id(:genmask))
next
end
route = Builtins.add(route, val)
val = Convert.to_string(UI.QueryWidget(Id(:device), :Value))
route = Builtins.add(route, val)
val = Convert.to_string(UI.QueryWidget(Id(:options), :Value))
route = Builtins.add(route, val)
break
end

UI.CloseDialog
return nil if ret != :ok
Builtins.y2debug("route=%1", route)
deep_copy(route)
end

def initRouting(_key)
route_conf = deep_copy(Routing.Routes)

Expand Down Expand Up @@ -330,14 +182,12 @@ def handleRouting(_key, event)
Ops.get_string(event, "EventReason", "") == "ValueChanged"
case Ops.get_symbol(event, "ID", :nil)
when :add
item = RoutingEditDialog(
Builtins.size(@r_items),
term(:empty),
devs
)
term = Item(Id(@r_items.size))
term = Y2Network::Dialogs::Route.run(term, devs)
log.info "route dialog term #{term.inspect}"

if !item.nil?
@r_items = Builtins.add(@r_items, item)
if !term.nil?
@r_items << term
UI.ChangeWidget(Id(:table), :Items, @r_items)
end
when :delete
Expand All @@ -357,7 +207,7 @@ def handleRouting(_key, event)
end
devs = Builtins.sort(devs)

item = RoutingEditDialog(cur, item, devs)
item = Y2Network::Dialogs::Route.run(item, devs)
if !item.nil?
@r_items = Builtins.maplist(@r_items) do |e|
next deep_copy(item) if cur == Ops.get_integer(e, [0, 0], -1)
Expand Down
79 changes: 79 additions & 0 deletions src/lib/y2network/dialogs/route.rb
@@ -0,0 +1,79 @@
require "ipaddr"

require "cwm/popup"
require "y2network/route"
require "y2network/widgets/destination"
require "y2network/widgets/devices"
require "y2network/widgets/gateway"
require "y2network/widgets/route_options"

Yast.import "Label"

module Y2Network
module Dialogs
# Dialog to create or edit route.
class Route < CWM::Popup
# @param route is now term from table, but it should be object for single route
def initialize(route, available_devices)
log.info "route dialog with route: #{route.inspect} " \
"and devices #{available_devices.inspect}"
params = route.params
@route_id = params[0]
# TODO: netmask
@route = ::Y2Network::Route.new(
to: (params[1] || "-") == "-" ? :default : IPAddr.new(params[1]),
interface: (params[4].nil? || params[4].empty?) ? :any : params[4],
gateway: (params[2] || "-") == "-" ? nil : IPAddr.new(params[2]),
options: params[5] || ""
)

@available_devices = available_devices
end

def run
res = super
log.info "route dialog result #{res.inspect}"
return nil if res != :ok

Yast::Term.new(
:item,
@route_id,
@route.to == :default ? "-" : @route.to.to_s,
@route.gateway.nil? ? "-" : @route.gateway.to_s,
"-", # TODO: netmask
@route.interface == :any ? "" : @route.interface,
@route.options
)
end

def contents
MinWidth(
60,
VBox(
HBox(
HWeight(100, Widgets::Destination.new(@route))
),
HBox(
HWeight(70, Widgets::Gateway.new(@route)),
HSpacing(1),
HWeight(30, Widgets::Devices.new(@route, @available_devices))
),
Widgets::RouteOptions.new(@route)
)
)
end
end

def next_button
Yast::Label.OKButton
end

def back_button
Yast::Label.CancelButton
end

def abort_button
""
end
end
end
10 changes: 5 additions & 5 deletions src/lib/y2network/route.rb
Expand Up @@ -20,15 +20,15 @@ module Y2Network
# This class represents a network route
class Route
# @return [IPAddr,:default] Destination; :default if it is the default route
attr_reader :to
attr_accessor :to
# @return [Interface,:any] Interface to associate the route to; :any if no interface is given
attr_reader :interface
attr_accessor :interface
# @return [IPAddr,nil] Source IP address ('src' in ip route)
attr_reader :source
attr_accessor :source
# @return [IPAddr,nil] Gateway IP address ('via' in ip route)
attr_reader :gateway
attr_accessor :gateway
# @return [String] Additional options
attr_reader :options
attr_accessor :options

# @param to [IPAddr,:default] Destination
# @param interface [Interface,:any] Interface to associate the root to
Expand Down
61 changes: 61 additions & 0 deletions src/lib/y2network/widgets/destination.rb
@@ -0,0 +1,61 @@
Yast.import "IP"
Yast.import "Popup"

require "ipaddr"

require "cwm/common_widgets"

module Y2Network
module Widgets
class Destination < CWM::InputField
# @param route [Y2Network::Route] route to modify by widget
def initialize(route)
textdomain "network"

@route = route
end

def label
_("&Destination")
end

def help
# TODO: original also does not have help, so write new one
""
end

def opt
[:hstretch]
end

def init
Yast::UI.ChangeWidget(Id(widget_id), :ValidChars, Yast::IP.ValidChars + "-/")
val = @route.to
self.value = val == :default ? "-" : (val.to_s + "/" + val.prefix.to_s)
end

def validate
return true if valid_destination?

Yast::Popup.Error(_("Destination is invalid."))
focus
false
end

def store
@route.to = value == "-" ? :default : IPAddr.new(value)
end

private

# Validates user's input obtained from destination field
def valid_destination?
destination = value
return true if destination == "-"

ip = destination[/^[^\/]+/]
Yast::IP.Check(ip)
end
end
end
end

0 comments on commit a3f3a1a

Please sign in to comment.