From e4d018a18e8fa6e93553b8aab5690560ccec286d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Mon, 22 Jul 2019 21:51:47 +0100 Subject: [PATCH 01/11] Remove portname --- src/autoyast-rnc/networking.rnc | 1 + src/include/network/lan/hardware.rb | 27 ++++++--------------------- src/include/network/lan/s390.rb | 4 ---- src/modules/LanItems.rb | 9 --------- 4 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/autoyast-rnc/networking.rnc b/src/autoyast-rnc/networking.rnc index 7ab804e53..c3f19bfb0 100644 --- a/src/autoyast-rnc/networking.rnc +++ b/src/autoyast-rnc/networking.rnc @@ -100,6 +100,7 @@ device = element type { text }? & element layer2 { BOOLEAN}? & element chanids { text }? & + # ignored, present for backward compatibility element portname { text }? & element protocol { text }? & element router { text }? diff --git a/src/include/network/lan/hardware.rb b/src/include/network/lan/hardware.rb index 6e1bc00b9..f797a04f4 100644 --- a/src/include/network/lan/hardware.rb +++ b/src/include/network/lan/hardware.rb @@ -97,19 +97,10 @@ def S390Dialog(builder:) HSpacing(2), VBox( VSpacing(1), - HBox( - # TextEntry label - InputField( - Id(:qeth_portname), - Opt(:hstretch), - _("&Port Name"), - LanItems.qeth_portname - ), - ComboBox( - Id(:qeth_portnumber), - _("Port Number"), - [Item(Id("0"), "0", true), Item(Id("1"), "1")] - ) + ComboBox( + Id(:qeth_portnumber), + _("Port Number"), + [Item(Id("0"), "0", true), Item(Id("1"), "1")] ), VSpacing(1), # TextEntry label @@ -165,12 +156,8 @@ def S390Dialog(builder:) ), HSpacing(6) ) - # S/390 dialog help: QETH Port name + # S/390 dialog help: QETH Options helptext = _( - "

Enter the Port Name for this interface (case-sensitive).

" - ) + - # S/390 dialog help: QETH Options - _( "

Enter any additional Options for this interface (separated by spaces).

" ) + _( @@ -352,7 +339,7 @@ def S390Dialog(builder:) id = case builder.type.short_name when "hsi" then :qeth_options - when "qeth" then :qeth_portname + when "qeth" then :qeth_options when "iucv" then :iucv_user else :chan_mode end @@ -414,8 +401,6 @@ def S390Dialog(builder:) LanItems.qeth_portnumber = Convert.to_string( UI.QueryWidget(Id(:qeth_portnumber), :Value) ) - LanItems.qeth_portname = Convert.to_string( - UI.QueryWidget(Id(:qeth_portname), :Value) ) end read = Convert.to_string(UI.QueryWidget(Id(:qeth_chan_read), :Value)) diff --git a/src/include/network/lan/s390.rb b/src/include/network/lan/s390.rb index c20edc579..2c90ebb1f 100644 --- a/src/include/network/lan/s390.rb +++ b/src/include/network/lan/s390.rb @@ -58,7 +58,6 @@ def s390_ReadQethAttribute(devname, attrib) # # Currently loaded attributes are: # QETH_LAYER2 yes/no string. - # QETH_PORTNAME portname or empty string # QETH_PORTNUMBER portnumber or empty string # QETH_CHANIDS read/write/control channel ids separated by space (compatibility requirement) # @@ -74,9 +73,6 @@ def s390_ReadQethConfig(devname) qeth_layer2 = s390_ReadQethAttribute(devname, "layer2") == "1" ? "yes" : "no" result = Builtins.add(result, "QETH_LAYER2", qeth_layer2) - qeth_portname = s390_ReadQethAttribute(devname, "portname") - result = Builtins.add(result, "QETH_PORTNAME", qeth_portname) - qeth_portno = s390_ReadQethAttribute(devname, "portno") result = Builtins.add(result, "QETH_PORTNUMBER", qeth_portno) diff --git a/src/modules/LanItems.rb b/src/modules/LanItems.rb index bcba086ee..71076d406 100644 --- a/src/modules/LanItems.rb +++ b/src/modules/LanItems.rb @@ -98,7 +98,6 @@ def main @Requires = [] # s390 options - @qeth_portname = "" @qeth_portnumber = "" # * ctc as PROTOCOL (or ctc mode, number in { 0, 1, .., 4 }, default: 0) @chan_mode = "0" @@ -961,7 +960,6 @@ def createS390Device(dev_attrs = {}) @type = dev_attrs["type"] || "" @qeth_chanids = dev_attrs["chanids"] || "" @qeth_layer2 = dev_attrs.fetch("layer2", false) - @qeth_portname = dev_attrs["portname"] || "" @chan_mode = dev_attrs["protocol"] || "" @iucv_user = dev_attrs["router"] || "" end @@ -978,11 +976,6 @@ def createS390Device(dev_attrs = {}) else "" end - @portname_param = if Ops.greater_than(Builtins.size(@qeth_portname), 0) - Builtins.sformat("-p %1", @qeth_portname.shellescape) - else - "" - end @options_param = if Ops.greater_than(Builtins.size(@qeth_options), 0) Builtins.sformat("-o %1", @qeth_options.shellescape) else @@ -992,7 +985,6 @@ def createS390Device(dev_attrs = {}) "/sbin/qeth_configure %1 %2 %3 %4 %5 1", @options_param, @qeth_layer2 ? "-l" : "", - @portname_param, @portnumber_param, @qeth_chanids ) @@ -1386,7 +1378,6 @@ def yast_config # @attribute Requires publish_variable :Requires, "list " publish_variable :set_default_route, "boolean" - publish_variable :qeth_portname, "string" publish_variable :qeth_portnumber, "string" publish_variable :chan_mode, "string" publish_variable :qeth_options, "string" From 2cdbe49d5188df2ca9c8c5a028c0df8cc726b57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Thu, 22 Aug 2019 14:40:04 +0100 Subject: [PATCH 02/11] Added s390 activation dialog and qeth builder. --- src/include/network/lan/hardware.rb | 369 +----------------- src/lib/y2network/connection_config/qeth.rb | 5 + .../dialogs/s390_device_activation.rb | 74 ++++ src/lib/y2network/interface_config_builder.rb | 2 +- .../interface_config_builders/qeth.rb | 68 ++++ src/lib/y2network/widgets/s390_channels.rb | 96 +++++ src/lib/y2network/widgets/s390_common.rb | 180 +++++++++ 7 files changed, 436 insertions(+), 358 deletions(-) create mode 100644 src/lib/y2network/dialogs/s390_device_activation.rb create mode 100644 src/lib/y2network/interface_config_builders/qeth.rb create mode 100644 src/lib/y2network/widgets/s390_channels.rb create mode 100644 src/lib/y2network/widgets/s390_common.rb diff --git a/src/include/network/lan/hardware.rb b/src/include/network/lan/hardware.rb index f797a04f4..cdff99d4e 100644 --- a/src/include/network/lan/hardware.rb +++ b/src/include/network/lan/hardware.rb @@ -29,6 +29,8 @@ include Yast::UIShortcuts +require "y2network/dialogs/s390_device_activation" + module Yast module NetworkLanHardwareInclude def initialize_network_lan_hardware(include_target) @@ -72,369 +74,22 @@ def initHelp # S/390 devices configuration dialog # @return dialog result def S390Dialog(builder:) - # S/390 dialog caption - caption = _("S/390 Network Card Configuration") - - drvtype = DriverType(builder.type.short_name) - - helptext = "" - contents = Empty() - - if Builtins.contains(["qeth", "hsi"], builder.type.short_name) - # CHANIDS - tmp_list = Builtins.splitstring(LanItems.qeth_chanids, " ") - chanids_map = { - "read" => Ops.get(tmp_list, 0, ""), - "write" => Ops.get(tmp_list, 1, ""), - "control" => Ops.get(tmp_list, 2, "") - } - contents = HBox( - HSpacing(6), - # Frame label - Frame( - _("S/390 Device Settings"), - HBox( - HSpacing(2), - VBox( - VSpacing(1), - ComboBox( - Id(:qeth_portnumber), - _("Port Number"), - [Item(Id("0"), "0", true), Item(Id("1"), "1")] - ), - VSpacing(1), - # TextEntry label - InputField( - Id(:qeth_options), - Opt(:hstretch), - Label.Options, - LanItems.qeth_options - ), - VSpacing(1), - # CheckBox label - Left(CheckBox(Id(:ipa_takeover), _("&Enable IPA Takeover"))), - VSpacing(1), - # CheckBox label - Left( - CheckBox( - Id(:qeth_layer2), - Opt(:notify), - _("Enable &Layer 2 Support") - ) - ), - # TextEntry label - InputField( - Id(:qeth_macaddress), - Opt(:hstretch), - _("Layer2 &MAC Address"), - LanItems.qeth_macaddress - ), - VSpacing(1), - HBox( - InputField( - Id(:qeth_chan_read), - Opt(:hstretch), - _("Read Channel"), - Ops.get_string(chanids_map, "read", "") - ), - InputField( - Id(:qeth_chan_write), - Opt(:hstretch), - _("Write Channel"), - Ops.get_string(chanids_map, "write", "") - ), - InputField( - Id(:qeth_chan_control), - Opt(:hstretch), - _("Control Channel"), - Ops.get_string(chanids_map, "control", "") - ) - ) - ), - HSpacing(2) + ret = Y2Network::Dialogs::S390DeviceActivation.run(builder) + if ret == :next + configured = builder.configure + builder.name = builder.configured_interface if configured + if !configured || builder.name.empty? + Popup.Error( + _( + "An error occurred while creating device.\nSee YaST log for details." ) - ), - HSpacing(6) - ) - # S/390 dialog help: QETH Options - helptext = _( - "

Enter any additional Options for this interface (separated by spaces).

" - ) + - _( - "

Select Enable IPA Takeover if IP address takeover should be enabled for this interface.

" - ) + - _( - "

Select Enable Layer 2 Support if this card has been configured with layer 2 support.

" - ) + - _( - "

Enter the Layer 2 MAC Address if this card has been configured with layer 2 support.

" ) - end - - if drvtype == "lcs" - tmp_list = Builtins.splitstring(LanItems.qeth_chanids, " ") - chanids_map = { - "read" => Ops.get(tmp_list, 0, ""), - "write" => Ops.get(tmp_list, 1, "") - } - contents = HBox( - HSpacing(6), - # Frame label - Frame( - _("S/390 Device Settings"), - HBox( - HSpacing(2), - VBox( - VSpacing(1), - # TextEntry label - InputField( - Id(:chan_mode), - Opt(:hstretch), - _("&Port Number"), - LanItems.chan_mode - ), - VSpacing(1), - # TextEntry label - InputField( - Id(:lcs_timeout), - Opt(:hstretch), - _("&LANCMD Time-Out"), - LanItems.lcs_timeout - ), - VSpacing(1), - HBox( - InputField( - Id(:qeth_chan_read), - Opt(:hstretch), - _("Read Channel"), - Ops.get_string(chanids_map, "read", "") - ), - InputField( - Id(:qeth_chan_write), - Opt(:hstretch), - _("Write Channel"), - Ops.get_string(chanids_map, "write", "") - ) - ) - ), - HSpacing(2) - ) - ), - HSpacing(6) - ) - # S/390 dialog help: LCS - helptext = _("

Choose the Port Number for this interface.

") + - _("

Specify the LANCMD Time-Out for this interface.

") - end - - ctcitems = [ - # ComboBox item: CTC device protocol - Item(Id("0"), _("Compatibility Mode")), - # ComboBox item: CTC device protocol - Item(Id("1"), _("Extended Mode")), - # ComboBox item: CTC device protocol - Item(Id("2"), _("CTC-Based tty (Linux to Linux Connections)")), - # ComboBox item: CTC device protocol - Item(Id("3"), _("Compatibility Mode with OS/390 and z/OS")) - ] - if drvtype == "ctc" - tmp_list = Builtins.splitstring(LanItems.qeth_chanids, " ") - chanids_map = { - "read" => Ops.get(tmp_list, 0, ""), - "write" => Ops.get(tmp_list, 1, "") - } - contents = HBox( - HSpacing(6), - # Frame label - Frame( - _("S/390 Device Settings"), - HBox( - HSpacing(2), - VBox( - VSpacing(1), - # TextEntry label - ComboBox(Id(:chan_mode), _("&Protocol"), ctcitems), - VSpacing(1), - HBox( - InputField( - Id(:qeth_chan_read), - Opt(:hstretch), - _("Read Channel"), - Ops.get_string(chanids_map, "read", "") - ), - InputField( - Id(:qeth_chan_write), - Opt(:hstretch), - _("Write Channel"), - Ops.get_string(chanids_map, "write", "") - ) - ) - ), - HSpacing(2) - ) - ), - HSpacing(6) - ) - # S/390 dialog help: CTC - helptext = _("

Choose the Protocol for this interface.

") - end - - if drvtype == "iucv" - contents = HBox( - HSpacing(6), - # Frame label - Frame( - _("S/390 Device Settings"), - HBox( - HSpacing(2), - VBox( - VSpacing(1), - # TextEntry label, #42789 - InputField( - Id(:iucv_user), - Opt(:hstretch), - _("&Peer Name"), - LanItems.iucv_user - ), - VSpacing(1) - ), - HSpacing(2) - ) - ), - HSpacing(6) - ) - # S/390 dialog help: IUCV, #42789 - helptext = _( - "

Enter the name of the IUCV peer,\nfor example, the z/VM user name with which to connect (case-sensitive).

\n" - ) - end - - Wizard.SetContentsButtons( - caption, - contents, - helptext, - Label.BackButton, - Label.NextButton - ) - - if drvtype == "ctc" - UI.ChangeWidget(Id(:chan_mode), :Value, LanItems.chan_mode) - end - - if drvtype == "lcs" - UI.ChangeWidget(Id(:chan_mode), :Value, LanItems.chan_mode) - UI.ChangeWidget(Id(:lcs_timeout), :Value, LanItems.lcs_timeout) - end - - if drvtype == "qeth" - UI.ChangeWidget(Id(:ipa_takeover), :Value, LanItems.ipa_takeover) - UI.ChangeWidget(Id(:qeth_layer2), :Value, LanItems.qeth_layer2) - UI.ChangeWidget( - Id(:qeth_macaddress), - :ValidChars, - ":0123456789abcdefABCDEF" - ) - end - - id = case builder.type.short_name - when "hsi" then :qeth_options - when "qeth" then :qeth_options - when "iucv" then :iucv_user - else :chan_mode - end - UI.SetFocus(Id(id)) - - ret = nil - loop do - if drvtype == "qeth" - mac_enabled = Convert.to_boolean( - UI.QueryWidget(Id(:qeth_layer2), :Value) - ) - UI.ChangeWidget(Id(:qeth_macaddress), :Enabled, mac_enabled) - end - - ret = UI.UserInput - - case ret - when :abort, :cancel - ReallyAbort() ? break : next - when :back - break - when :next - if builder.type.short_name == "iucv" - LanItems.device = Ops.add( - "id-", - Convert.to_string(UI.QueryWidget(Id(:iucv_user), :Value)) - ) - LanItems.iucv_user = Convert.to_string( - UI.QueryWidget(Id(:iucv_user), :Value) - ) - end - - if builder.type.short_name == "ctc" - LanItems.chan_mode = Convert.to_string( - UI.QueryWidget(Id(:chan_mode), :Value) - ) - end - if builder.type.short_name == "lcs" - LanItems.lcs_timeout = Convert.to_string( - UI.QueryWidget(Id(:lcs_timeout), :Value) - ) - LanItems.chan_mode = Convert.to_string( - UI.QueryWidget(Id(:chan_mode), :Value) - ) - end - if builder.type.short_name == "qeth" || builder.type.short_name == "hsi" - LanItems.qeth_options = Convert.to_string( - UI.QueryWidget(Id(:qeth_options), :Value) - ) - LanItems.ipa_takeover = Convert.to_boolean( - UI.QueryWidget(Id(:ipa_takeover), :Value) - ) - LanItems.qeth_layer2 = Convert.to_boolean( - UI.QueryWidget(Id(:qeth_layer2), :Value) - ) - LanItems.qeth_macaddress = Convert.to_string( - UI.QueryWidget(Id(:qeth_macaddress), :Value) - ) - LanItems.qeth_portnumber = Convert.to_string( - UI.QueryWidget(Id(:qeth_portnumber), :Value) - ) - ) - end - read = Convert.to_string(UI.QueryWidget(Id(:qeth_chan_read), :Value)) - write = Convert.to_string( - UI.QueryWidget(Id(:qeth_chan_write), :Value) - ) - control = Convert.to_string( - UI.QueryWidget(Id(:qeth_chan_control), :Value) - ) - control = "" if control.nil? - LanItems.qeth_chanids = String.CutBlanks( - Builtins.sformat("%1 %2 %3", read, write, control) - ) - if LanItems.createS390Device - builder.name = LanItems.GetCurrentName - else - Popup.Error( - _( - "An error occurred while creating device.\nSee YaST log for details." - ) - ) - ret = nil - next - end - break - when :qeth_layer2 - next - else - Builtins.y2error("Unexpected return code: %1", ret) - next + ret = nil end end - deep_copy(ret) + ret end end end diff --git a/src/lib/y2network/connection_config/qeth.rb b/src/lib/y2network/connection_config/qeth.rb index c8004482a..c4b698f24 100644 --- a/src/lib/y2network/connection_config/qeth.rb +++ b/src/lib/y2network/connection_config/qeth.rb @@ -47,14 +47,19 @@ class Qeth < Base attr_accessor :data_channel # @return [Boolean] whether layer2 is enabled or not attr_accessor :layer2 + # @return [Boolean] whether ipa takeover is enabled or not + attr_accessor :ipa_takeover # @return [Integer] port number (0 or 1) attr_accessor :port_number + # @return [String] configuration extra attributes + attr_accessor :attributes # Constructor def initialize super() @layer2 = false @port_number = 0 + @ipa_takeover = false end def ==(other) diff --git a/src/lib/y2network/dialogs/s390_device_activation.rb b/src/lib/y2network/dialogs/s390_device_activation.rb new file mode 100644 index 000000000..6764cffdc --- /dev/null +++ b/src/lib/y2network/dialogs/s390_device_activation.rb @@ -0,0 +1,74 @@ +require "cwm/dialog" +require "y2network/widgets/s390_common" +require "y2network/widgets/s390_channels" + +module Y2Network + module Dialogs + class S390DeviceActivation < CWM::Dialog + def initialize(settings) + textdomain "network" + + @settings = settings + @settings.proposal + end + + def title + _("S/390 Network Card Configuration") + end + + def contents + HBox( + HSpacing(6), + Frame( + _("S/390 Device Settings"), + HBox( + HSpacing(2), + VBox( + VSpacing(1), + HBox( + s390_port_number, + HSpacing(1), + s390_options + ), + VSpacing(1), + Left(s390_ip_takeover), + VSpacing(1), + Left(s390_layer2), + VSpacing(1), + s390_channels + ), + HSpacing(2) + ) + ), + HSpacing(6) + ) + end + + def abort_handler + Yast::Popup.YesNo("Really abort?") + end + + private + + def s390_port_number + Y2Network::Widgets::S390PortNumber.new(@settings) + end + + def s390_options + Y2Network::Widgets::S390QethOptions.new(@settings) + end + + def s390_ip_takeover + Y2Network::Widgets::S390IPAddressTakeover.new(@settings) + end + + def s390_channels + Y2Network::Widgets::S390Channels.new(@settings) + end + + def s390_layer2 + Y2Network::Widgets::S390Layer2.new(@settings) + end + end + end +end diff --git a/src/lib/y2network/interface_config_builder.rb b/src/lib/y2network/interface_config_builder.rb index d907a8aac..2d55b55da 100644 --- a/src/lib/y2network/interface_config_builder.rb +++ b/src/lib/y2network/interface_config_builder.rb @@ -395,7 +395,7 @@ def ip_config_default def connection_config_klass(type) ConnectionConfig.const_get(type.class_name) rescue NameError - log.error "Could not find a class to handle '#{type.name}' connections" + log.error "Could not find a class to handle '#{type.class_name}' connections" ConnectionConfig::Base end diff --git a/src/lib/y2network/interface_config_builders/qeth.rb b/src/lib/y2network/interface_config_builders/qeth.rb new file mode 100644 index 000000000..72c614de9 --- /dev/null +++ b/src/lib/y2network/interface_config_builders/qeth.rb @@ -0,0 +1,68 @@ +require "yast" +require "y2network/interface_config_builder" + +Yast.import "LanItems" +Yast.import "NetworkInterfaces" + +module Y2Network + module InterfaceConfigBuilders + class Qeth < InterfaceConfigBuilder + extend Forwardable + + def initialize(config: nil) + super(type: InterfaceType::QETH, config: config) + end + + def_delegators :@connection_config, + :read_channel, :read_channel=, + :write_channel, :write_channel=, + :data_channel, :data_channel=, + :layer2, :layer2=, + :port_number, :port_number=, + :lladdress, :lladdress=, + :ipa_takeover, :ipa_takeover=, + :attributes, :attributes= + + # @return [String] + def configure_attributes + @connection_config.attributes.split(" ") + end + + def device_id + return if read_channel.to_s.empty? + + [read_channel, write_channel, data_channel].join(":") + end + + def device_id_from(busid) + cmd = "/sbin/lszdev qeth -c id -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| + d.include? busid + end + end + + def configure + cmd = "/sbin/chzdev -e qeth #{device_id}".split(" ").concat(configure_attributes) + + Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? + end + + def configured_interface + cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ").concat(configure_attributes) + + Yast::Execute.stdout.on_target!(cmd).chomp + end + + def propose_channels + id = device_id_from(hwinfo.busid) + return unless id + self.read_channel, self.write_channel, self.data_channel = id.split(":") + end + + def proposal + propose_channels unless device_id + end + end + end +end diff --git a/src/lib/y2network/widgets/s390_channels.rb b/src/lib/y2network/widgets/s390_channels.rb new file mode 100644 index 000000000..9de983bdc --- /dev/null +++ b/src/lib/y2network/widgets/s390_channels.rb @@ -0,0 +1,96 @@ +require "cwm/custom_widget" +require "cwm/common_widgets" + +module Y2Network + module Widgets + class S390Channels < CWM::CustomWidget + def initialize(settings) + textdomain "network" + @settings = settings + end + + def label + "" + end + + def contents + HBox( + S390ReadChannel.new(@settings), + HSpacing(1), + S390WriteChannel.new(@settings), + HSpacing(1), + S390DataChannel.new(@settings) + ) + end + end + + class S390ReadChannel < CWM::InputField + def initialize(settings) + textdomain "network" + @settings = settings + end + + def init + self.value = @settings.read_channel + end + + def opt + [:hstretch] + end + + def label + _("&Read Channel") + end + + def store + @settings.read_channel = value + end + end + + class S390WriteChannel < CWM::InputField + def initialize(settings) + textdomain "network" + @settings = settings + end + + def init + self.value = @settings.write_channel + end + + def opt + [:hstretch] + end + + def label + _("&Read Channel") + end + + def store + @settings.write_channel = value + end + end + + class S390DataChannel < CWM::InputField + def initialize(settings) + textdomain "network" + @settings = settings + end + + def init + self.value = @settings.data_channel + end + + def opt + [:hstretch] + end + + def label + _("Control Channel") + end + + def store + @settings.data_channel = value + end + end + end +end diff --git a/src/lib/y2network/widgets/s390_common.rb b/src/lib/y2network/widgets/s390_common.rb new file mode 100644 index 000000000..047ffb464 --- /dev/null +++ b/src/lib/y2network/widgets/s390_common.rb @@ -0,0 +1,180 @@ +require "cwm/common_widgets" +require "cwm/custom_widget" + +module Y2Network + module Widgets + class S390PortNumber < CWM::ComboBox + def initialize(settings) + textdomain "network" + + @settings = settings + end + + def init + self.value = @settings.port_number.to_i + end + + def label + _("Port Number") + end + + def items + [[0, "0"], [1, "1"]] + end + + def store + @settings.port_number = value + end + end + + class S390QethOptions < CWM::InputField + def initialize(settings) + textdomain "network" + @settings = settings + end + + def label + _("Options") + end + + def init + self.value = @settings.attributes + end + + def opt + [:hstretch] + end + + def help + # TRANSLATORS: S/390 dialog help for QETH Options + _("

Enter any additional Options for this interface (separated by spaces).

") + end + + def store + @settings.attributes = value + end + end + + class S390IPAddressTakeover < CWM::CheckBox + def initialize(settings) + textdomain "network" + @settings = settings + end + + def init + self.value = !!@settings.ipa_takeover + end + + def label + _("Enable IPA takeover") + end + + def help + _("

Select Enable IPA Takeover if IP address takeover should be enabled " \ + "for this interface.

") + end + + def store + @settings.ipa_takeover = value + end + end + + class S390Layer2 < CWM::CustomWidget + def initialize(settings) + textdomain "network" + @settings = settings + self.handle_all_events = true + end + + def contents + VBox( + Left(support_widget), + Left(mac_address_widget) + ) + end + + def init + refresh + end + + def handle(event) + case event["ID"] + when support_widget.widget_id, mac_address_widget.widget_id + refresh + end + + nil + end + + private + + def refresh + support_widget.checked? ? mac_address_widget.enable : mac_address_widget.disable + end + + def support_widget + @support_widget ||= S390Layer2Support.new(@settings) + end + + def mac_address_widget + @mac_address_widget ||= S390Layer2Address.new(@settings) + end + end + + class S390Layer2Support < CWM::CheckBox + def initialize(settings) + textdomain "network" + @settings = settings + end + + def init + self.value = !!@settings.layer2 + end + + def opt + [:notify] + end + + def label + _("Enable Layer2 Support") + end + + def help + "

Select Enable Layer 2 Support if this card has been " \ + "configured with layer 2 support.

" + end + + def store + @settings.layer2 = value + end + end + + class S390Layer2Address < CWM::InputField + def initialize(settings) + textdomain "network" + @settings = settings + end + + def init + self.value = @settings.lladdress + end + + def opt + [:notify] + end + + def label + _("Layer2 MAC Address") + end + + def help + _("

Enter the Layer 2 MAC Address if this card has been " \ + "configured with layer 2 support.

") + end + + def store + @settings.lladdress = value + end + end + end +end From ad4218e69853f5a16e0a499dd44599514af99bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Fri, 23 Aug 2019 17:22:00 +0100 Subject: [PATCH 03/11] Added ctc and lcs activation dialogs. --- Rakefile | 19 +++ src/include/network/lan/hardware.rb | 7 +- src/lib/y2network/dialogs/s390.rb | 2 + .../y2network/dialogs/s390_ctc_activation.rb | 69 ++++++++ .../dialogs/s390_device_activation.rb | 89 +++++------ .../y2network/dialogs/s390_lcs_activation.rb | 73 +++++++++ .../y2network/dialogs/s390_qeth_activation.rb | 79 +++++++++ .../interface_config_builders/ctc.rb | 77 +++++++++ .../interface_config_builders/lcs.rb | 82 ++++++++++ .../interface_config_builders/qeth.rb | 52 +++++- src/lib/y2network/sysconfig/config_writer.rb | 1 + src/lib/y2network/widgets/s390_channels.rb | 52 +++++- src/lib/y2network/widgets/s390_common.rb | 150 +++++++++++++++++- .../dialogs/s390_ctc_activation_test.rb | 30 ++++ .../dialogs/s390_device_activation_test.rb | 38 +++++ .../dialogs/s390_lcs_activation_test.rb | 30 ++++ .../dialogs/s390_qeth_activation_test.rb | 30 ++++ .../interface_config_builders/ctc_test.rb | 144 +++++++++++++++++ .../interface_config_builders/lcs_test.rb | 146 +++++++++++++++++ .../interface_config_builders/qeth_test.rb | 144 +++++++++++++++++ test/y2network/widgets/s390_channels_test.rb | 111 +++++++++++++ test/y2network/widgets/s390_common_test.rb | 51 ++++++ 22 files changed, 1416 insertions(+), 60 deletions(-) create mode 100644 src/lib/y2network/dialogs/s390.rb create mode 100644 src/lib/y2network/dialogs/s390_ctc_activation.rb create mode 100644 src/lib/y2network/dialogs/s390_lcs_activation.rb create mode 100644 src/lib/y2network/dialogs/s390_qeth_activation.rb create mode 100644 src/lib/y2network/interface_config_builders/ctc.rb create mode 100644 src/lib/y2network/interface_config_builders/lcs.rb create mode 100644 test/y2network/dialogs/s390_ctc_activation_test.rb create mode 100644 test/y2network/dialogs/s390_device_activation_test.rb create mode 100644 test/y2network/dialogs/s390_lcs_activation_test.rb create mode 100644 test/y2network/dialogs/s390_qeth_activation_test.rb create mode 100644 test/y2network/interface_config_builders/ctc_test.rb create mode 100644 test/y2network/interface_config_builders/lcs_test.rb create mode 100644 test/y2network/interface_config_builders/qeth_test.rb create mode 100644 test/y2network/widgets/s390_channels_test.rb create mode 100644 test/y2network/widgets/s390_common_test.rb diff --git a/Rakefile b/Rakefile index 7eebc5df4..230638706 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,22 @@ +# 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/rake" Yast::Tasks.configuration do |conf| diff --git a/src/include/network/lan/hardware.rb b/src/include/network/lan/hardware.rb index cdff99d4e..0d9abb8cd 100644 --- a/src/include/network/lan/hardware.rb +++ b/src/include/network/lan/hardware.rb @@ -29,7 +29,7 @@ include Yast::UIShortcuts -require "y2network/dialogs/s390_device_activation" +require "y2network/dialogs/s390" module Yast module NetworkLanHardwareInclude @@ -74,10 +74,13 @@ def initHelp # S/390 devices configuration dialog # @return dialog result def S390Dialog(builder:) - ret = Y2Network::Dialogs::S390DeviceActivation.run(builder) + dialog = Y2Network::Dialogs::S390DeviceActivation.for(builder.type) + ret = dialog ? dialog.run(builder) : :abort + if ret == :next configured = builder.configure builder.name = builder.configured_interface if configured + builder.interface.name = builder.name if configured && builder.interface if !configured || builder.name.empty? Popup.Error( _( diff --git a/src/lib/y2network/dialogs/s390.rb b/src/lib/y2network/dialogs/s390.rb new file mode 100644 index 000000000..56d54fdba --- /dev/null +++ b/src/lib/y2network/dialogs/s390.rb @@ -0,0 +1,2 @@ +require "y2network/dialogs/s390_qeth_activation" +require "y2network/dialogs/s390_ctc_activation" diff --git a/src/lib/y2network/dialogs/s390_ctc_activation.rb b/src/lib/y2network/dialogs/s390_ctc_activation.rb new file mode 100644 index 000000000..b43da40e8 --- /dev/null +++ b/src/lib/y2network/dialogs/s390_ctc_activation.rb @@ -0,0 +1,69 @@ +# 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/dialogs/s390_device_activation" + +module Y2Network + module Dialogs + # Dialog for activating a CTC device + class S390CtcActivation < S390DeviceActivation + def contents + textdomain "network" + + HBox( + HSpacing(6), + # Frame label + Frame( + _("S/390 Device Settings"), + HBox( + HSpacing(2), + VBox( + VSpacing(1), + # TextEntry label + protocol_widget, + VSpacing(1), + HBox( + read_channel_widget, + HSpacing(1), + write_channel_widget + ) + ), + HSpacing(2) + ) + ), + HSpacing(6) + ) + end + + private + + def protocol_widget + Y2Network::Widgets::S390Protocol.new(@settings) + end + + def read_channel_widget + Y2Network::Widgets::S390ReadChannel.new(@settings) + end + + def write_channel_widget + Y2Network::Widgets::S390WriteChannel.new(@settings) + end + end + end +end diff --git a/src/lib/y2network/dialogs/s390_device_activation.rb b/src/lib/y2network/dialogs/s390_device_activation.rb index 6764cffdc..0d9b421aa 100644 --- a/src/lib/y2network/dialogs/s390_device_activation.rb +++ b/src/lib/y2network/dialogs/s390_device_activation.rb @@ -1,10 +1,49 @@ +# 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 "cwm/dialog" require "y2network/widgets/s390_common" require "y2network/widgets/s390_channels" module Y2Network module Dialogs + # Base class dialog for activating S390 devices class S390DeviceActivation < CWM::Dialog + # @param type [Y2Network::InterfaceType] type of device + # @return [S390DeviceActivation, nil] + def self.for(type) + case type.short_name + when "qeth", "hsi" + require "y2network/dialogs/s390_qeth_activation" + Y2Network::Dialogs::S390QethActivation + when "ctc" + require "y2network/dialogs/s390_ctc_activation" + Y2Network::Dialogs::S390CtcActivation + when "lcs" + require "y2network/dialogs/s390_lcs_activation" + Y2Network::Dialogs::S390LcsActivation + end + end + + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @@ -17,57 +56,11 @@ def title end def contents - HBox( - HSpacing(6), - Frame( - _("S/390 Device Settings"), - HBox( - HSpacing(2), - VBox( - VSpacing(1), - HBox( - s390_port_number, - HSpacing(1), - s390_options - ), - VSpacing(1), - Left(s390_ip_takeover), - VSpacing(1), - Left(s390_layer2), - VSpacing(1), - s390_channels - ), - HSpacing(2) - ) - ), - HSpacing(6) - ) + Empty() end def abort_handler - Yast::Popup.YesNo("Really abort?") - end - - private - - def s390_port_number - Y2Network::Widgets::S390PortNumber.new(@settings) - end - - def s390_options - Y2Network::Widgets::S390QethOptions.new(@settings) - end - - def s390_ip_takeover - Y2Network::Widgets::S390IPAddressTakeover.new(@settings) - end - - def s390_channels - Y2Network::Widgets::S390Channels.new(@settings) - end - - def s390_layer2 - Y2Network::Widgets::S390Layer2.new(@settings) + Yast::Popup.ReallyAbort(true) end end end diff --git a/src/lib/y2network/dialogs/s390_lcs_activation.rb b/src/lib/y2network/dialogs/s390_lcs_activation.rb new file mode 100644 index 000000000..7d3190d9b --- /dev/null +++ b/src/lib/y2network/dialogs/s390_lcs_activation.rb @@ -0,0 +1,73 @@ +# 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/dialogs/s390_device_activation" + +module Y2Network + module Dialogs + # Dialog for activating a LCS s390 device + class S390LcsActivation < S390DeviceActivation + def contents + textdomain "network" + + HBox( + HSpacing(6), + # Frame label + Frame( + _("S/390 Device Settings"), + HBox( + HSpacing(2), + VBox( + VSpacing(1), + # TextEntry label + protocol_widget, + VSpacing(1), + HBox( + read_channel_widget, + HSpacing(1), + write_channel_widget + ) + ), + HSpacing(2) + ) + ), + HSpacing(6) + ) + end + + private + + def protocol_widget + Y2Network::Widgets::S390Protocol.new(@settings) + end + + def read_channel_widget + Y2Network::Widgets::S390ReadChannel.new(@settings) + end + + def write_channel_widget + Y2Network::Widgets::S390WriteChannel.new(@settings) + end + + def timeout_widget + Y2network::Widgets::S390LanCmdTimeout.new(@settings) + end + end + end +end diff --git a/src/lib/y2network/dialogs/s390_qeth_activation.rb b/src/lib/y2network/dialogs/s390_qeth_activation.rb new file mode 100644 index 000000000..11b620df7 --- /dev/null +++ b/src/lib/y2network/dialogs/s390_qeth_activation.rb @@ -0,0 +1,79 @@ +# 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/dialogs/s390_device_activation" + +module Y2Network + module Dialogs + # Dialog for activating a QETH device + class S390QethActivation < S390DeviceActivation + def contents + textdomain "network" + + HBox( + HSpacing(6), + Frame( + _("S/390 Device Settings"), + HBox( + HSpacing(2), + VBox( + VSpacing(1), + HBox( + s390_port_number, + HSpacing(1), + s390_attributes + ), + VSpacing(1), + Left(s390_ip_takeover), + VSpacing(1), + Left(s390_layer2), + VSpacing(1), + s390_channels + ), + HSpacing(2) + ) + ), + HSpacing(6) + ) + end + + private + + def s390_port_number + Y2Network::Widgets::S390PortNumber.new(@settings) + end + + def s390_attributes + Y2Network::Widgets::S390Attributes.new(@settings) + end + + def s390_ip_takeover + Y2Network::Widgets::S390IPAddressTakeover.new(@settings) + end + + def s390_channels + Y2Network::Widgets::S390Channels.new(@settings) + end + + def s390_layer2 + Y2Network::Widgets::S390Layer2.new(@settings) + end + end + end +end diff --git a/src/lib/y2network/interface_config_builders/ctc.rb b/src/lib/y2network/interface_config_builders/ctc.rb new file mode 100644 index 000000000..9028a58e8 --- /dev/null +++ b/src/lib/y2network/interface_config_builders/ctc.rb @@ -0,0 +1,77 @@ +# 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 "y2network/interface_config_builder" + +Yast.import "LanItems" +Yast.import "NetworkInterfaces" + +module Y2Network + module InterfaceConfigBuilders + class Ctc < InterfaceConfigBuilder + extend Forwardable + + def initialize(config: nil) + super(type: InterfaceType::CTC, config: config) + end + + def_delegators :@connection_config, + :read_channel, :read_channel=, + :write_channel, :write_channel=, + :protocol, :protocol= + + def device_id + return if read_channel.to_s.empty? + + "#{read_channel}:#{write_channel}" + end + + def device_id_from(channel) + cmd = "/sbin/lszdev ctc -c id -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| + d.include? channel + end + end + + def configure + cmd = "/sbin/chzdev ctc #{device_id} -e protocol=#{protocol}".split(" ") + + Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? + end + + def configured_interface + cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).chomp + end + + def propose_channels + id = device_id_from(hwinfo.busid) + return unless id + self.read_channel, self.write_channel = id.split(":") + end + + def proposal + propose_channels unless device_id + end + end + end +end diff --git a/src/lib/y2network/interface_config_builders/lcs.rb b/src/lib/y2network/interface_config_builders/lcs.rb new file mode 100644 index 000000000..49817acee --- /dev/null +++ b/src/lib/y2network/interface_config_builders/lcs.rb @@ -0,0 +1,82 @@ +# 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 "y2network/interface_config_builder" + +Yast.import "LanItems" +Yast.import "NetworkInterfaces" + +module Y2Network + module InterfaceConfigBuilders + class Lcs < InterfaceConfigBuilder + extend Forwardable + + def initialize(config: nil) + super(type: InterfaceType::LCS, config: config) + end + + def_delegators :@connection_config, + :read_channel, :read_channel=, + :write_channel, :write_channel=, + :protocol, :protocol=, + :timeout, :timeout= + + def device_id + return if read_channel.to_s.empty? + + "#{read_channel}:#{write_channel}" + end + + def device_id_from(busid) + cmd = "/sbin/lszdev lcs -c id -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| + d.include? busid + end + end + + def configure_attributes + "protocol=#{protocol} lancmd_timeout=#{timeout.to_i}".split(" ") + end + + def configure + cmd = "/sbin/chzdev lcs #{device_id} -e ".split(" ").concat(configure_attributes) + + Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? + end + + def configured_interface + cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).chomp + end + + def propose_channels + id = device_id_from(hwinfo.busid) + return unless id + self.read_channel, self.write_channel = id.split(":") + end + + def proposal + propose_channels unless device_id + end + end + end +end diff --git a/src/lib/y2network/interface_config_builders/qeth.rb b/src/lib/y2network/interface_config_builders/qeth.rb index 72c614de9..568daf7fb 100644 --- a/src/lib/y2network/interface_config_builders/qeth.rb +++ b/src/lib/y2network/interface_config_builders/qeth.rb @@ -1,3 +1,22 @@ +# 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 "y2network/interface_config_builder" @@ -6,9 +25,15 @@ module Y2Network module InterfaceConfigBuilders + # Builder for S390 qeth interfaces. It also assumes the activation + # responsibilities. class Qeth < InterfaceConfigBuilder extend Forwardable + # Constructor + # + # @param config [Y2Network::ConnectionConfig::Base, nil] existing configuration of device or nil + # for newly created def initialize(config: nil) super(type: InterfaceType::QETH, config: config) end @@ -23,43 +48,60 @@ def initialize(config: nil) :ipa_takeover, :ipa_takeover=, :attributes, :attributes= - # @return [String] + # @return [Array] def configure_attributes - @connection_config.attributes.split(" ") + return [] unless attributes + + attributes.split(" ") end + # The device id to be used by lszdev or chzdev commands + # + # @return [String] def device_id return if read_channel.to_s.empty? [read_channel, write_channel, data_channel].join(":") end - def device_id_from(busid) + # Returns the complete device id which contains the given channel + # + # @param channel [String] + # @return [String] + def device_id_from(channel) cmd = "/sbin/lszdev qeth -c id -n".split(" ") Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| - d.include? busid + d.include? channel end end + # It tries to enable the interface with the configured device id + # + # @return [Boolean] true when enabled def configure - cmd = "/sbin/chzdev -e qeth #{device_id}".split(" ").concat(configure_attributes) + cmd = "/sbin/chzdev qeth #{device_id} -e".split(" ").concat(configure_attributes) Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? end + # Obtains the enabled interface name associated with the device id + # + # @return [String] device name def configured_interface cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ").concat(configure_attributes) Yast::Execute.stdout.on_target!(cmd).chomp end + # Modifies the read, write and data channel from the the device id def propose_channels id = device_id_from(hwinfo.busid) return unless id self.read_channel, self.write_channel, self.data_channel = id.split(":") end + # Makes a new channels proposal only if not already set def proposal propose_channels unless device_id end diff --git a/src/lib/y2network/sysconfig/config_writer.rb b/src/lib/y2network/sysconfig/config_writer.rb index 453e89cf5..fc28530c7 100644 --- a/src/lib/y2network/sysconfig/config_writer.rb +++ b/src/lib/y2network/sysconfig/config_writer.rb @@ -67,6 +67,7 @@ def write(config, old_config = nil) def write_interface_changes(config, old_config) # Write ifroute files config.interfaces.each do |dev| + next if dev.name.empty? routes = find_routes_for(dev, config.routing.routes) file = routes_file_for(dev) diff --git a/src/lib/y2network/widgets/s390_channels.rb b/src/lib/y2network/widgets/s390_channels.rb index 9de983bdc..9993769e5 100644 --- a/src/lib/y2network/widgets/s390_channels.rb +++ b/src/lib/y2network/widgets/s390_channels.rb @@ -1,18 +1,44 @@ +# 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 "cwm/custom_widget" require "cwm/common_widgets" module Y2Network module Widgets + # A container widget for setting the QETH and HSI device channels (read, + # write and control) class S390Channels < CWM::CustomWidget + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def label "" end + # @see CWM::AbstractWidget def contents HBox( S390ReadChannel.new(@settings), @@ -24,70 +50,94 @@ def contents end end + # Widget for setting the s390 device read channel class S390ReadChannel < CWM::InputField + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init self.value = @settings.read_channel end + # @see CWM::AbstractWidget def opt [:hstretch] end + # @see CWM::AbstractWidget def label _("&Read Channel") end + # @see CWM::AbstractWidget def store @settings.read_channel = value end end + # Widget for setting the s390 device write channel class S390WriteChannel < CWM::InputField + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init self.value = @settings.write_channel end + # @see CWM::AbstractWidget def opt [:hstretch] end + # @see CWM::AbstractWidget def label - _("&Read Channel") + _("&Write Channel") end + # @see CWM::AbstractWidget def store @settings.write_channel = value end end + # Widget for setting the s390 device data channel class S390DataChannel < CWM::InputField + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init self.value = @settings.data_channel end + # @see CWM::AbstractWidget def opt [:hstretch] end + # @see CWM::AbstractWidget def label _("Control Channel") end + # @see CWM::AbstractWidget def store @settings.data_channel = value end diff --git a/src/lib/y2network/widgets/s390_common.rb b/src/lib/y2network/widgets/s390_common.rb index 047ffb464..0dff57bc5 100644 --- a/src/lib/y2network/widgets/s390_common.rb +++ b/src/lib/y2network/widgets/s390_common.rb @@ -1,85 +1,211 @@ +# 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 "cwm/common_widgets" require "cwm/custom_widget" module Y2Network module Widgets + # Widget for setting the s390 device write channel + class S390LanCmdTimeout < CWM::InputField + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] + def initialize(settings) + textdomain "network" + + @settings = settings + end + + # @see CWM::AbstractWidget + def label + _("&LANCMD Time-Out") + end + + # @see CWM::AbstractWidget + def init + self.value = @settings.timeout + end + + # @see CWM::AbstractWidget + def store + @settings.timeout = value + end + + # @see CWM::AbstractWidget + def help + _("

Specify the LANCMD Time-Out for this interface.

") + end + end + + class S390Protocol < CWM::ComboBox + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] + def initialize(settings) + textdomain "network" + + @settings = settings + end + + # @see CWM::AbstractWidget + def init + self.value = @settings.protocol + end + + # @see CWM::AbstractWidget + def label + _("&Protocol") + end + + # @see CWM::AbstractWidget + def items + [ + # ComboBox item: CTC device protocol + ["0", _("Compatibility Mode")], + # ComboBox item: CTC device protocol + ["1", _("Extended Mode")], + # ComboBox item: CTC device protocol + ["2", _("CTC-Based tty (Linux to Linux Connections)")], + # ComboBox item: CTC device protocol + ["3", _("Compatibility Mode with OS/390 and z/OS")] + ] + end + + # @see CWM::AbstractWidget + def store + @settings.protocol = value + end + + # @see CWM::AbstractWidget + def help + _("

Choose the Protocol for this interface.

") + end + end + class S390PortNumber < CWM::ComboBox + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init - self.value = @settings.port_number.to_i + self.value = @settings.port_number.to_s end + # @see CWM::AbstractWidget def label _("Port Number") end + # @see CWM::AbstractWidget def items - [[0, "0"], [1, "1"]] + [["0", "0"], ["1", "1"]] end + # @see CWM::AbstractWidget def store - @settings.port_number = value + @settings.port_number = value.to_i + end + + # @see CWM::AbstractWidget + def help + _("

Choose the Port Number for this interface.

") end end - class S390QethOptions < CWM::InputField + class S390Attributes < CWM::InputField + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def label _("Options") end + # @see CWM::AbstractWidget def init self.value = @settings.attributes end + # @see CWM::AbstractWidget def opt [:hstretch] end + # @see CWM::AbstractWidget def help # TRANSLATORS: S/390 dialog help for QETH Options _("

Enter any additional Options for this interface (separated by spaces).

") end + # @see CWM::AbstractWidget def store @settings.attributes = value end end class S390IPAddressTakeover < CWM::CheckBox + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init self.value = !!@settings.ipa_takeover end + # @see CWM::AbstractWidget def label _("Enable IPA takeover") end + # @see CWM::AbstractWidget def help _("

Select Enable IPA Takeover if IP address takeover should be enabled " \ "for this interface.

") end + # @see CWM::AbstractWidget def store @settings.ipa_takeover = value end end class S390Layer2 < CWM::CustomWidget + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings @@ -122,56 +248,72 @@ def mac_address_widget end class S390Layer2Support < CWM::CheckBox + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init self.value = !!@settings.layer2 end + # @see CWM::AbstractWidget def opt [:notify] end + # @see CWM::AbstractWidget def label _("Enable Layer2 Support") end + # @see CWM::AbstractWidget def help "

Select Enable Layer 2 Support if this card has been " \ "configured with layer 2 support.

" end + # @see CWM::AbstractWidget def store @settings.layer2 = value end end class S390Layer2Address < CWM::InputField + # Constructor + # + # @param settings [Y2Network::InterfaceConfigBuilder] def initialize(settings) textdomain "network" @settings = settings end + # @see CWM::AbstractWidget def init self.value = @settings.lladdress end + # @see CWM::AbstractWidget def opt [:notify] end + # @see CWM::AbstractWidget def label _("Layer2 MAC Address") end + # @see CWM::AbstractWidget def help _("

Enter the Layer 2 MAC Address if this card has been " \ "configured with layer 2 support.

") end + # @see CWM::AbstractWidget def store @settings.lladdress = value end diff --git a/test/y2network/dialogs/s390_ctc_activation_test.rb b/test/y2network/dialogs/s390_ctc_activation_test.rb new file mode 100644 index 000000000..c5eba4cda --- /dev/null +++ b/test/y2network/dialogs/s390_ctc_activation_test.rb @@ -0,0 +1,30 @@ +# 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_relative "../../test_helper" +require "cwm/rspec" + +require "y2network/dialogs/s390_ctc_activation" +require "y2network/interface_config_builder" + +describe Y2Network::Dialogs::S390CtcActivation do + subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("ctc")) } + + include_examples "CWM::Dialog" +end diff --git a/test/y2network/dialogs/s390_device_activation_test.rb b/test/y2network/dialogs/s390_device_activation_test.rb new file mode 100644 index 000000000..7b6e3c1e6 --- /dev/null +++ b/test/y2network/dialogs/s390_device_activation_test.rb @@ -0,0 +1,38 @@ +# 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_relative "../../test_helper" +require "cwm/rspec" + +require "y2network/dialogs/s390_device_activation" +require "y2network/interface_config_builder" + +describe Y2Network::Dialogs::S390DeviceActivation do + subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("qeth")) } + + include_examples "CWM::Dialog" + + describe "#abort_handler" do + it "asks for abort confirmation" do + expect(Yast::Popup).to receive(:ReallyAbort).with(true) + + subject.abort_handler + end + end +end diff --git a/test/y2network/dialogs/s390_lcs_activation_test.rb b/test/y2network/dialogs/s390_lcs_activation_test.rb new file mode 100644 index 000000000..7d2d1fbe0 --- /dev/null +++ b/test/y2network/dialogs/s390_lcs_activation_test.rb @@ -0,0 +1,30 @@ +# 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_relative "../../test_helper" +require "cwm/rspec" + +require "y2network/dialogs/s390_lcs_activation" +require "y2network/interface_config_builder" + +describe Y2Network::Dialogs::S390LcsActivation do + subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("lcs")) } + + include_examples "CWM::Dialog" +end diff --git a/test/y2network/dialogs/s390_qeth_activation_test.rb b/test/y2network/dialogs/s390_qeth_activation_test.rb new file mode 100644 index 000000000..7fa970f61 --- /dev/null +++ b/test/y2network/dialogs/s390_qeth_activation_test.rb @@ -0,0 +1,30 @@ +# 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_relative "../../test_helper" +require "cwm/rspec" + +require "y2network/dialogs/s390_qeth_activation" +require "y2network/interface_config_builder" + +describe Y2Network::Dialogs::S390QethActivation do + subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("qeth")) } + + include_examples "CWM::Dialog" +end diff --git a/test/y2network/interface_config_builders/ctc_test.rb b/test/y2network/interface_config_builders/ctc_test.rb new file mode 100644 index 000000000..80326cb54 --- /dev/null +++ b/test/y2network/interface_config_builders/ctc_test.rb @@ -0,0 +1,144 @@ +#!/usr/bin/env rspec + +# 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_relative "../../test_helper" + +require "yast" +require "y2network/interface_config_builders/ctc" +require "y2network/interface_type" + +describe Y2Network::InterfaceConfigBuilders::Ctc do + subject(:builder) do + res = Y2Network::InterfaceConfigBuilders::Ctc.new + res.name = "ctc0" + res + end + + let(:executor) { double("Yast::Execute", on_target!: "") } + let(:initialize_channels) { true } + + before do + allow(Yast::Execute).to receive(:stdout).and_return(executor) + builder.read_channel = "0.0.0900" if initialize_channels + builder.write_channel = "0.0.0901" if initialize_channels + end + + describe "#type" do + it "returns ctc type" do + expect(subject.type).to eq Y2Network::InterfaceType::CTC + end + end + + describe "#configure" do + it "tries to activate the group device associated with the defined device id" do + expect(Yast::Execute).to receive(:on_target!) + .with("/sbin/chzdev", "ctc", builder.device_id, "-e", + "protocol=#{builder.protocol}", allowed_exitstatus: 0..255) + .and_return(0) + subject.configure + end + + context "when activated succesfully" do + it "returns true" do + expect(Yast::Execute).to receive(:on_target!).and_return(0) + expect(subject.configure).to eq(true) + end + end + + context "when failed the activation and returned a non zero return code" do + it "returns false" do + expect(Yast::Execute).to receive(:on_target!).and_return(34) + expect(subject.configure).to eq(false) + end + end + end + + describe "#configured_interface" do + before do + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", builder.device_id, "-c", "names", "-n"]) + .and_return("ctc1") + end + + it "obtains the network interface associated with builder device id" do + expect(subject.configured_interface).to eq("ctc1") + end + end + + describe "#device_id_from" do + context "given the read or write device id" do + let(:device_id) { "0.0.0800:0.0.0801" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + before do + allow(builder).to receive(:hwinfo).and_return(hwinfo) + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", "ctc", "-c", "id", "-n"]) + .and_return(device_id) + end + + it "obtains the triplet device ids listed by lszdev" do + expect(subject.device_id_from(hwinfo.busid)).to eq(device_id) + end + end + end + + describe "#device_id" do + it "returns the read and write channel device ids joined by ':'" do + expect(subject.device_id).to eql("0.0.0900:0.0.0901") + end + end + + describe "#propose_channels" do + context "when the read and write channel have not been initialized" do + let(:initialize_channels) { false } + let(:device_id) { "0.0.0800:0.0.0801" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + + before do + allow(builder).to receive(:device_id_from).with(write_channel).and_return(device_id) + allow(builder).to receive(:hwinfo).and_return(hwinfo) + end + + it "initializes them from the given busid" do + expect { builder.propose_channels }.to change { builder.device_id }.from(nil).to(device_id) + end + end + end + + describe "#proposal" do + context "when no device id has been initialized" do + let(:initialize_channels) { false } + it "proposes the channel device ids to be used" do + expect(subject).to receive(:propose_channels) + subject.proposal + end + end + + context "when the channel device ids have been set already" do + it "does not propose anything" do + expect(subject).to_not receive(:propose_channels) + subject.proposal + end + end + end +end diff --git a/test/y2network/interface_config_builders/lcs_test.rb b/test/y2network/interface_config_builders/lcs_test.rb new file mode 100644 index 000000000..9b617358c --- /dev/null +++ b/test/y2network/interface_config_builders/lcs_test.rb @@ -0,0 +1,146 @@ +#!/usr/bin/env rspec + +# 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_relative "../../test_helper" + +require "yast" +require "y2network/interface_config_builders/lcs" +require "y2network/interface_type" + +describe Y2Network::InterfaceConfigBuilders::Lcs do + subject(:builder) do + res = Y2Network::InterfaceConfigBuilders::Lcs.new + res.name = "eth1" + res + end + + describe "#type" do + it "returns lcs type" do + expect(subject.type).to eq Y2Network::InterfaceType::LCS + end + end + + let(:executor) { double("Yast::Execute", on_target!: "") } + let(:initialize_channels) { true } + + before do + allow(Yast::Execute).to receive(:stdout).and_return(executor) + builder.read_channel = "0.0.0900" if initialize_channels + builder.write_channel = "0.0.0901" if initialize_channels + end + + describe "#configure" do + it "tries to activate the group device associated with the defined device id" do + expect(Yast::Execute).to receive(:on_target!) + .with("/sbin/chzdev", "lcs", builder.device_id, "-e", + "protocol=#{builder.protocol}", "lancmd_timeout=5", + allowed_exitstatus: 0..255) + .and_return(0) + subject.configure + end + + context "when activated succesfully" do + it "returns true" do + expect(Yast::Execute).to receive(:on_target!).and_return(0) + expect(subject.configure).to eq(true) + end + end + + context "when failed the activation and returned a non zero return code" do + it "returns false" do + expect(Yast::Execute).to receive(:on_target!).and_return(34) + expect(subject.configure).to eq(false) + end + end + end + + describe "#configured_interface" do + before do + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", builder.device_id, "-c", "names", "-n"]) + .and_return("lcs1") + end + + it "obtains the network interface associated with builder device id" do + expect(subject.configured_interface).to eq("lcs1") + end + end + + describe "#device_id_from" do + context "given the read or write device id" do + let(:device_id) { "0.0.0800:0.0.0801" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + before do + allow(builder).to receive(:hwinfo).and_return(hwinfo) + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", "lcs", "-c", "id", "-n"]) + .and_return(device_id) + end + + it "obtains the triplet device ids listed by lszdev" do + expect(subject.device_id_from(hwinfo.busid)).to eq(device_id) + end + end + end + + describe "#device_id" do + it "returns the read and write channel device ids joined by ':'" do + expect(subject.device_id).to eql("0.0.0900:0.0.0901") + end + end + + describe "#propose_channels" do + context "when the read and write channel have not been initialized" do + let(:initialize_channels) { false } + let(:device_id) { "0.0.0800:0.0.0801" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + + before do + allow(builder).to receive(:device_id_from).with(write_channel).and_return(device_id) + allow(builder).to receive(:hwinfo).and_return(hwinfo) + end + + it "initializes them from the given busid" do + expect { builder.propose_channels }.to change { builder.device_id }.from(nil).to(device_id) + end + end + end + + describe "#proposal" do + context "when no device id has been initialized" do + let(:initialize_channels) { false } + it "proposes the channel device ids to be used" do + expect(subject).to receive(:propose_channels) + subject.proposal + end + end + + context "when the channel device ids have been set already" do + it "does not propose anything" do + expect(subject).to_not receive(:propose_channels) + subject.proposal + end + end + end + +end diff --git a/test/y2network/interface_config_builders/qeth_test.rb b/test/y2network/interface_config_builders/qeth_test.rb new file mode 100644 index 000000000..a25fb9036 --- /dev/null +++ b/test/y2network/interface_config_builders/qeth_test.rb @@ -0,0 +1,144 @@ +#!/usr/bin/env rspec + +# 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_relative "../../test_helper" + +require "yast" +require "y2network/interface_config_builders/qeth" +require "y2network/interface_type" + +describe Y2Network::InterfaceConfigBuilders::Qeth do + subject(:builder) do + res = Y2Network::InterfaceConfigBuilders::Qeth.new + res.name = "eth0" + res + end + + let(:executor) { double("Yast::Execute", on_target!: "") } + let(:initialize_channels) { true } + before do + allow(Yast::Execute).to receive(:stdout).and_return(executor) + if initialize_channels + builder.read_channel = "0.0.0800" + builder.write_channel = "0.0.0801" + builder.data_channel = "0.0.0802" + end + end + + describe "#type" do + it "returns qeth type" do + expect(subject.type).to eq Y2Network::InterfaceType::QETH + end + end + + describe "#configure" do + it "tries to activate the group device associated with the defined device id" do + expect(Yast::Execute).to receive(:on_target!) + .with("/sbin/chzdev", "qeth", builder.device_id, "-e", allowed_exitstatus: 0..255).and_return(0) + subject.configure + end + + context "when activated succesfully" do + it "returns true" do + expect(Yast::Execute).to receive(:on_target!).and_return(0) + expect(subject.configure).to eq(true) + end + end + + context "when failed the activation and returned a non zero return code" do + it "returns false" do + expect(Yast::Execute).to receive(:on_target!).and_return(34) + expect(subject.configure).to eq(false) + end + end + end + + describe "#configured_interface" do + before do + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", builder.device_id, "-c", "names", "-n"]) + .and_return("eth1") + end + + it "obtains the network interface associated with builder device id" do + expect(subject.configured_interface).to eq("eth1") + end + end + + describe "#device_id_from" do + context "given the read, write or data device id" do + let(:device_id) { "0.0.0700:0.0.0701:0.0.0702" } + let(:data_channel) { "0.0.0702" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => data_channel }) } + before do + allow(builder).to receive(:hwinfo).and_return(hwinfo) + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", "qeth", "-c", "id", "-n"]) + .and_return(device_id) + end + + it "obtains the triplet device ids listed by lszdev" do + expect(subject.device_id_from("0.0.0702")).to eq(device_id) + end + end + end + + describe "#device_id" do + it "returns the channel, write and data device ids joined by ':'" do + expect(subject.device_id).to eql("0.0.0800:0.0.0801:0.0.0802") + end + end + + describe "#propose_channels" do + context "when the read and write channel have not been initialized" do + let(:initialize_channels) { false } + let(:device_id) { "0.0.0800:0.0.0801:0.0802" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + + before do + allow(builder).to receive(:device_id_from).with(write_channel).and_return(device_id) + allow(builder).to receive(:hwinfo).and_return(hwinfo) + end + + it "initializes them from the given busid" do + expect { builder.propose_channels }.to change { builder.device_id }.from(nil).to(device_id) + end + end + end + + describe "#proposal" do + context "when no device id has been initialized" do + let(:initialize_channels) { false } + it "proposes the channel device ids to be used" do + expect(subject).to receive(:propose_channels) + subject.proposal + end + end + + context "when the channel device ids have been set already" do + it "does not propose anything" do + expect(subject).to_not receive(:propose_channels) + subject.proposal + end + end + end +end diff --git a/test/y2network/widgets/s390_channels_test.rb b/test/y2network/widgets/s390_channels_test.rb new file mode 100644 index 000000000..729241d35 --- /dev/null +++ b/test/y2network/widgets/s390_channels_test.rb @@ -0,0 +1,111 @@ +# 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_relative "../../test_helper" +require "y2network/widgets/s390_channels" +require "y2network/interface_config_builder" + +require "cwm/rspec" + +describe Y2Network::Widgets::S390ReadChannel do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + let(:read_channel) { "0.0.0700" } + subject { described_class.new(builder) } + + include_examples "CWM::InputField" + + describe "#init" do + it "initializes the widget value with the device read channel" do + builder.read_channel = read_channel + expect(subject).to receive(:value=).with(read_channel) + subject.init + end + end + + describe "#store" do + before do + allow(subject).to receive(:value).and_return("0.0.0800") + end + + it "modifies the device read channel with the widget value" do + builder.read_channel = read_channel + expect { subject.store }.to change { builder.read_channel }.from(read_channel).to("0.0.0800") + end + end +end + +describe Y2Network::Widgets::S390WriteChannel do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + let(:write_channel) { "0.0.0701" } + subject { described_class.new(builder) } + + include_examples "CWM::InputField" + + describe "#init" do + it "initializes the widget value with the device write channel" do + builder.write_channel = write_channel + expect(subject).to receive(:value=).with(write_channel) + subject.init + end + end + + describe "#store" do + before do + allow(subject).to receive(:value).and_return("0.0.0801") + end + + it "modifies the device write channel with the widget value" do + builder.write_channel = write_channel + expect { subject.store }.to change { builder.write_channel }.from(write_channel).to("0.0.0801") + end + end +end + +describe Y2Network::Widgets::S390DataChannel do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + let(:data_channel) { "0.0.0702" } + subject { described_class.new(builder) } + + include_examples "CWM::InputField" + + describe "#init" do + it "initializes the widget value with the device data channel" do + builder.data_channel = data_channel + expect(subject).to receive(:value=).with(data_channel) + subject.init + end + end + + describe "#store" do + before do + allow(subject).to receive(:value).and_return("0.0.0802") + end + + it "modifies the device data channel with the widget value" do + builder.data_channel = data_channel + expect { subject.store }.to change { builder.data_channel }.from(data_channel).to("0.0.0802") + end + end +end + +describe Y2Network::Widgets::S390Channels do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + subject { described_class.new(builder) } + include_examples "CWM::CustomWidget" +end diff --git a/test/y2network/widgets/s390_common_test.rb b/test/y2network/widgets/s390_common_test.rb new file mode 100644 index 000000000..dd126c5d5 --- /dev/null +++ b/test/y2network/widgets/s390_common_test.rb @@ -0,0 +1,51 @@ +# 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_relative "../../test_helper" +require "y2network/widgets/s390_common" +require "y2network/interface_config_builder" + +require "cwm/rspec" + +describe Y2Network::Widgets::S390LanCmdTimeout do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("lcs") } + subject { described_class.new(builder) } + include_examples "CWM::InputField" +end + +describe Y2Network::Widgets::S390Protocol do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("ctc") } + subject { described_class.new(builder) } + + include_examples "CWM::ComboBox" +end + +describe Y2Network::Widgets::S390PortNumber do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + subject { described_class.new(builder) } + + include_examples "CWM::ComboBox" +end + +describe Y2Network::Widgets::S390Attributes do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + subject { described_class.new(builder) } + + include_examples "CWM::InputField" +end From ca52539dca22c986204668a745491add7e00054e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Wed, 28 Aug 2019 17:36:20 +0100 Subject: [PATCH 04/11] Added s390 device activator classes (based on CR). --- src/include/network/lan/hardware.rb | 23 +-- src/lib/y2network/connection_config/ctc.rb | 7 +- src/lib/y2network/connection_config/lcs.rb | 11 -- src/lib/y2network/dialogs/s390.rb | 2 - .../y2network/dialogs/s390_ctc_activation.rb | 6 +- .../dialogs/s390_device_activation.rb | 55 +++++-- .../y2network/dialogs/s390_lcs_activation.rb | 8 +- .../y2network/dialogs/s390_qeth_activation.rb | 10 +- src/lib/y2network/interface_config_builder.rb | 8 +- .../interface_config_builders/ctc.rb | 36 ----- .../interface_config_builders/lcs.rb | 40 ----- .../interface_config_builders/qeth.rb | 58 ------- src/lib/y2network/interfaces_collection.rb | 10 ++ src/lib/y2network/s390_device_activator.rb | 96 ++++++++++++ .../y2network/s390_device_activators/ctc.rb | 54 +++++++ .../y2network/s390_device_activators/lcs.rb | 33 ++++ .../y2network/s390_device_activators/qeth.rb | 56 +++++++ src/lib/y2network/widgets/s390_common.rb | 25 +++- .../dialogs/s390_ctc_activation_test.rb | 5 +- .../dialogs/s390_device_activation_test.rb | 56 ++++++- .../dialogs/s390_lcs_activation_test.rb | 3 +- .../dialogs/s390_qeth_activation_test.rb | 3 +- .../interface_config_builder_test.rb | 9 ++ .../interface_config_builders/ctc_test.rb | 104 ------------- .../interface_config_builders/lcs_test.rb | 106 ------------- .../interface_config_builders/qeth_test.rb | 104 ------------- test/y2network/s390_device_activator_test.rb | 54 +++++++ .../s390_device_activators/ctc_test.rb | 140 +++++++++++++++++ .../s390_device_activators/lcs_test.rb | 68 +++++++++ .../s390_device_activators/qeth_test.rb | 141 ++++++++++++++++++ test/y2network/widgets/s390_common_test.rb | 26 +++- 31 files changed, 838 insertions(+), 519 deletions(-) delete mode 100644 src/lib/y2network/dialogs/s390.rb create mode 100644 src/lib/y2network/s390_device_activator.rb create mode 100644 src/lib/y2network/s390_device_activators/ctc.rb create mode 100644 src/lib/y2network/s390_device_activators/lcs.rb create mode 100644 src/lib/y2network/s390_device_activators/qeth.rb create mode 100644 test/y2network/s390_device_activator_test.rb create mode 100644 test/y2network/s390_device_activators/ctc_test.rb create mode 100644 test/y2network/s390_device_activators/lcs_test.rb create mode 100644 test/y2network/s390_device_activators/qeth_test.rb diff --git a/src/include/network/lan/hardware.rb b/src/include/network/lan/hardware.rb index 0d9abb8cd..c1d71aa5a 100644 --- a/src/include/network/lan/hardware.rb +++ b/src/include/network/lan/hardware.rb @@ -29,7 +29,7 @@ include Yast::UIShortcuts -require "y2network/dialogs/s390" +require "y2network/dialogs/s390_device_activation" module Yast module NetworkLanHardwareInclude @@ -74,25 +74,8 @@ def initHelp # S/390 devices configuration dialog # @return dialog result def S390Dialog(builder:) - dialog = Y2Network::Dialogs::S390DeviceActivation.for(builder.type) - ret = dialog ? dialog.run(builder) : :abort - - if ret == :next - configured = builder.configure - builder.name = builder.configured_interface if configured - builder.interface.name = builder.name if configured && builder.interface - if !configured || builder.name.empty? - Popup.Error( - _( - "An error occurred while creating device.\nSee YaST log for details." - ) - ) - - ret = nil - end - end - - ret + dialog = Y2Network::Dialogs::S390DeviceActivation.for(builder) + dialog ? dialog.run : :abort end end end diff --git a/src/lib/y2network/connection_config/ctc.rb b/src/lib/y2network/connection_config/ctc.rb index 360d3e072..a13e734b2 100644 --- a/src/lib/y2network/connection_config/ctc.rb +++ b/src/lib/y2network/connection_config/ctc.rb @@ -46,7 +46,7 @@ class Ctc < Base # @return [String] write device bus id attr_accessor :write_channel # @return [Integer] connection protocol (0, 1, 3, or 4) - # 0 Compatibility with peers other than OS/390®. + # 0 Compatibility with peers other than OS/390®. (default) # 1 Enhanced package checking for Linux peers. # 3 For compatibility with OS/390 or z/OS peers. # 4 For MPC connections to VTAM on traditional mainframe operating systems. @@ -54,6 +54,11 @@ class Ctc < Base # @see https://github.com/SUSE/s390-tools/blob/master/ctc_configure#L16 attr_accessor :protocol + def initialize + super() + @protocol = 0 + end + def ==(other) return false unless super diff --git a/src/lib/y2network/connection_config/lcs.rb b/src/lib/y2network/connection_config/lcs.rb index c6c299a7a..691591296 100644 --- a/src/lib/y2network/connection_config/lcs.rb +++ b/src/lib/y2network/connection_config/lcs.rb @@ -43,16 +43,6 @@ class Lcs < Base attr_accessor :read_channel # @return [String] write device bus id attr_accessor :write_channel - # @return [Integer] connection protocol (0, 1, 3, or 4) - # 0 Compatibility with peers other than OS/390®. - # 1 Enhanced package checking for Linux peers. - # 3 For compatibility with OS/390 or z/OS peers. - # 4 For MPC connections to VTAM on traditional mainframe operating systems. - # @see https://github.com/SUSE/s390-tools/blob/master/ctc_configure#L16 - # - # # FIXME: At lease in linuxrc the protocol is not needed anymore for lcs - # interfaces (once replaced ctc_configure by chzdev) - attr_accessor :protocol # The time the driver wait for a reply issuing a LAN command. # # @return [Integer] lcs lancmd timeout (default 5s) @@ -62,7 +52,6 @@ class Lcs < Base # Constructor def initialize super() - @protocol = 0 @timeout = 5 end diff --git a/src/lib/y2network/dialogs/s390.rb b/src/lib/y2network/dialogs/s390.rb deleted file mode 100644 index 56d54fdba..000000000 --- a/src/lib/y2network/dialogs/s390.rb +++ /dev/null @@ -1,2 +0,0 @@ -require "y2network/dialogs/s390_qeth_activation" -require "y2network/dialogs/s390_ctc_activation" diff --git a/src/lib/y2network/dialogs/s390_ctc_activation.rb b/src/lib/y2network/dialogs/s390_ctc_activation.rb index b43da40e8..50a337b44 100644 --- a/src/lib/y2network/dialogs/s390_ctc_activation.rb +++ b/src/lib/y2network/dialogs/s390_ctc_activation.rb @@ -54,15 +54,15 @@ def contents private def protocol_widget - Y2Network::Widgets::S390Protocol.new(@settings) + Y2Network::Widgets::S390Protocol.new(builder) end def read_channel_widget - Y2Network::Widgets::S390ReadChannel.new(@settings) + Y2Network::Widgets::S390ReadChannel.new(builder) end def write_channel_widget - Y2Network::Widgets::S390WriteChannel.new(@settings) + Y2Network::Widgets::S390WriteChannel.new(builder) end end end diff --git a/src/lib/y2network/dialogs/s390_device_activation.rb b/src/lib/y2network/dialogs/s390_device_activation.rb index 0d9b421aa..be091e7ac 100644 --- a/src/lib/y2network/dialogs/s390_device_activation.rb +++ b/src/lib/y2network/dialogs/s390_device_activation.rb @@ -18,6 +18,7 @@ # find current contact information at www.suse.com. require "cwm/dialog" +require "y2network/s390_device_activator" require "y2network/widgets/s390_common" require "y2network/widgets/s390_channels" @@ -25,30 +26,41 @@ module Y2Network module Dialogs # Base class dialog for activating S390 devices class S390DeviceActivation < CWM::Dialog - # @param type [Y2Network::InterfaceType] type of device + # @param builder [Y2Network::InterfaceConfigBuilder] # @return [S390DeviceActivation, nil] - def self.for(type) - case type.short_name + def self.for(builder) + return nil unless builder.type + case builder.type.short_name when "qeth", "hsi" require "y2network/dialogs/s390_qeth_activation" - Y2Network::Dialogs::S390QethActivation + require "y2network/s390_device_activators/qeth" + activator = S390DeviceActivators::Qeth.new(builder) + Y2Network::Dialogs::S390QethActivation.new(activator) when "ctc" require "y2network/dialogs/s390_ctc_activation" - Y2Network::Dialogs::S390CtcActivation + require "y2network/s390_device_activators/ctc" + activator = S390DeviceActivators::Ctc.new(builder) + Y2Network::Dialogs::S390CtcActivation.new(activator) when "lcs" require "y2network/dialogs/s390_lcs_activation" - Y2Network::Dialogs::S390LcsActivation + require "y2network/s390_device_activators/lcs" + activator = S390DeviceActivators::Lcs.new(builder) + Y2Network::Dialogs::S390LcsActivation.new(activator) end end + attr_reader :builder + attr_reader :activator + # Constructor # - # @param settings [Y2Network::InterfaceConfigBuilder] - def initialize(settings) + # @param activator [Y2Network::S390DeviceActivator] + def initialize(activator) textdomain "network" - @settings = settings - @settings.proposal + @activator = activator + @activator.proposal + @builder = activator.builder end def title @@ -59,6 +71,29 @@ def contents Empty() end + def run + ret = super + if ret == :next + configured = activator.configure + builder.name = activator.configured_interface if configured + # TODO: Refresh the list of interfaces in yast_config. Take into + # account that the interface in yast_config does not have a nem so + # the builder.interface is probably nil and should be obtained + # through the busid. + if !configured || builder.name.empty? + Yast::Popup.Error( + _( + "An error occurred while creating device.\nSee YaST log for details." + ) + ) + + ret = nil + end + end + + ret + end + def abort_handler Yast::Popup.ReallyAbort(true) end diff --git a/src/lib/y2network/dialogs/s390_lcs_activation.rb b/src/lib/y2network/dialogs/s390_lcs_activation.rb index 7d3190d9b..7cf217862 100644 --- a/src/lib/y2network/dialogs/s390_lcs_activation.rb +++ b/src/lib/y2network/dialogs/s390_lcs_activation.rb @@ -54,19 +54,19 @@ def contents private def protocol_widget - Y2Network::Widgets::S390Protocol.new(@settings) + Y2Network::Widgets::S390Protocol.new(builder) end def read_channel_widget - Y2Network::Widgets::S390ReadChannel.new(@settings) + Y2Network::Widgets::S390ReadChannel.new(builder) end def write_channel_widget - Y2Network::Widgets::S390WriteChannel.new(@settings) + Y2Network::Widgets::S390WriteChannel.new(builder) end def timeout_widget - Y2network::Widgets::S390LanCmdTimeout.new(@settings) + Y2network::Widgets::S390LanCmdTimeout.new(builder) end end end diff --git a/src/lib/y2network/dialogs/s390_qeth_activation.rb b/src/lib/y2network/dialogs/s390_qeth_activation.rb index 11b620df7..35c042845 100644 --- a/src/lib/y2network/dialogs/s390_qeth_activation.rb +++ b/src/lib/y2network/dialogs/s390_qeth_activation.rb @@ -56,23 +56,23 @@ def contents private def s390_port_number - Y2Network::Widgets::S390PortNumber.new(@settings) + Y2Network::Widgets::S390PortNumber.new(builder) end def s390_attributes - Y2Network::Widgets::S390Attributes.new(@settings) + Y2Network::Widgets::S390Attributes.new(builder) end def s390_ip_takeover - Y2Network::Widgets::S390IPAddressTakeover.new(@settings) + Y2Network::Widgets::S390IPAddressTakeover.new(builder) end def s390_channels - Y2Network::Widgets::S390Channels.new(@settings) + Y2Network::Widgets::S390Channels.new(builder) end def s390_layer2 - Y2Network::Widgets::S390Layer2.new(@settings) + Y2Network::Widgets::S390Layer2.new(builder) end end end diff --git a/src/lib/y2network/interface_config_builder.rb b/src/lib/y2network/interface_config_builder.rb index 2d55b55da..e65109548 100644 --- a/src/lib/y2network/interface_config_builder.rb +++ b/src/lib/y2network/interface_config_builder.rb @@ -378,12 +378,16 @@ def configure_as_slave self.aliases = [] end - private + def hwinfo_from(info) + @hwinfo = Hwinfo.new(info) + end def hwinfo - @hwinfo ||= Hwinfo.new(name: name) + @hwinfo ||= Hwinfo.for(name) end + private + def ip_config_default return @connection_config.ip if @connection_config.ip @connection_config.ip = ConnectionConfig::IPConfig.new(IPAddress.new("0.0.0.0")) diff --git a/src/lib/y2network/interface_config_builders/ctc.rb b/src/lib/y2network/interface_config_builders/ctc.rb index 9028a58e8..45b8b489b 100644 --- a/src/lib/y2network/interface_config_builders/ctc.rb +++ b/src/lib/y2network/interface_config_builders/ctc.rb @@ -36,42 +36,6 @@ def initialize(config: nil) :read_channel, :read_channel=, :write_channel, :write_channel=, :protocol, :protocol= - - def device_id - return if read_channel.to_s.empty? - - "#{read_channel}:#{write_channel}" - end - - def device_id_from(channel) - cmd = "/sbin/lszdev ctc -c id -n".split(" ") - - Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| - d.include? channel - end - end - - def configure - cmd = "/sbin/chzdev ctc #{device_id} -e protocol=#{protocol}".split(" ") - - Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? - end - - def configured_interface - cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ") - - Yast::Execute.stdout.on_target!(cmd).chomp - end - - def propose_channels - id = device_id_from(hwinfo.busid) - return unless id - self.read_channel, self.write_channel = id.split(":") - end - - def proposal - propose_channels unless device_id - end end end end diff --git a/src/lib/y2network/interface_config_builders/lcs.rb b/src/lib/y2network/interface_config_builders/lcs.rb index 49817acee..25c48f632 100644 --- a/src/lib/y2network/interface_config_builders/lcs.rb +++ b/src/lib/y2network/interface_config_builders/lcs.rb @@ -37,46 +37,6 @@ def initialize(config: nil) :write_channel, :write_channel=, :protocol, :protocol=, :timeout, :timeout= - - def device_id - return if read_channel.to_s.empty? - - "#{read_channel}:#{write_channel}" - end - - def device_id_from(busid) - cmd = "/sbin/lszdev lcs -c id -n".split(" ") - - Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| - d.include? busid - end - end - - def configure_attributes - "protocol=#{protocol} lancmd_timeout=#{timeout.to_i}".split(" ") - end - - def configure - cmd = "/sbin/chzdev lcs #{device_id} -e ".split(" ").concat(configure_attributes) - - Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? - end - - def configured_interface - cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ") - - Yast::Execute.stdout.on_target!(cmd).chomp - end - - def propose_channels - id = device_id_from(hwinfo.busid) - return unless id - self.read_channel, self.write_channel = id.split(":") - end - - def proposal - propose_channels unless device_id - end end end end diff --git a/src/lib/y2network/interface_config_builders/qeth.rb b/src/lib/y2network/interface_config_builders/qeth.rb index 568daf7fb..9286bf00a 100644 --- a/src/lib/y2network/interface_config_builders/qeth.rb +++ b/src/lib/y2network/interface_config_builders/qeth.rb @@ -47,64 +47,6 @@ def initialize(config: nil) :lladdress, :lladdress=, :ipa_takeover, :ipa_takeover=, :attributes, :attributes= - - # @return [Array] - def configure_attributes - return [] unless attributes - - attributes.split(" ") - end - - # The device id to be used by lszdev or chzdev commands - # - # @return [String] - def device_id - return if read_channel.to_s.empty? - - [read_channel, write_channel, data_channel].join(":") - end - - # Returns the complete device id which contains the given channel - # - # @param channel [String] - # @return [String] - def device_id_from(channel) - cmd = "/sbin/lszdev qeth -c id -n".split(" ") - - Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| - d.include? channel - end - end - - # It tries to enable the interface with the configured device id - # - # @return [Boolean] true when enabled - def configure - cmd = "/sbin/chzdev qeth #{device_id} -e".split(" ").concat(configure_attributes) - - Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? - end - - # Obtains the enabled interface name associated with the device id - # - # @return [String] device name - def configured_interface - cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ").concat(configure_attributes) - - Yast::Execute.stdout.on_target!(cmd).chomp - end - - # Modifies the read, write and data channel from the the device id - def propose_channels - id = device_id_from(hwinfo.busid) - return unless id - self.read_channel, self.write_channel, self.data_channel = id.split(":") - end - - # Makes a new channels proposal only if not already set - def proposal - propose_channels unless device_id - end end end end diff --git a/src/lib/y2network/interfaces_collection.rb b/src/lib/y2network/interfaces_collection.rb index 50cc5b030..f9cbb6859 100644 --- a/src/lib/y2network/interfaces_collection.rb +++ b/src/lib/y2network/interfaces_collection.rb @@ -68,6 +68,16 @@ def by_name(name) end end + # Returns an interface with the given hardware busid if present + # + # @param busid [String] interface busid ("0.0.0700", "0000:00:19.0", ...) + # @return [Interface,nil] Interface with the given busid or nil if not found + def by_busid(busid) + interfaces.find do |iface| + iface.hardware.busid == busid + end + end + # Returns list of interfaces of given type # # @param type [InterfaceType] device type diff --git a/src/lib/y2network/s390_device_activator.rb b/src/lib/y2network/s390_device_activator.rb new file mode 100644 index 000000000..424336be7 --- /dev/null +++ b/src/lib/y2network/s390_device_activator.rb @@ -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 "yast2/execute" + +module Y2Network + class S390DeviceActivator + extend Forwardable + include Yast::Logger + + attr_accessor :builder + + # Load fresh instace of device activator for given interface config builder + def self.for(builder) + type = builder.type + require "y2network/s390_device_activators/#{type.file_name}" + S390DeviceActivators.const_get(type.class_name).new(builder) + rescue LoadError => e + log.info "Specialized device activator for #{type.short_name} not found. #{e.inspect}" + nil + end + + def initialize(builder) + @builder = builder + end + + # @return [Array] + def configure_attributes + [] + end + + def type + builder.type.short_name + end + + # The device id to be used by lszdev or chzdev commands + # + # @return [String, nil] + def device_id + nil + end + + # Returns the complete device id which contains the given channel + # + # @param channel [String] + # @return [String] + def device_id_from(channel) + cmd = "/sbin/lszdev #{type} -c id -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| + d.include? channel + end + end + + # It tries to enable the interface with the configured device id + # + # @return [Boolean] true when enabled + def configure + return false unless device_id + cmd = "/sbin/chzdev #{type} #{device_id} -e".split(" ").concat(configure_attributes) + + Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? + end + + # Obtains the enabled interface name associated with the device id + # + # @return [String] device name + def configured_interface + return "" unless device_id + cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ") + + Yast::Execute.stdout.on_target!(cmd).chomp + end + + # Makes a new proposal + def proposal + end + end +end diff --git a/src/lib/y2network/s390_device_activators/ctc.rb b/src/lib/y2network/s390_device_activators/ctc.rb new file mode 100644 index 000000000..59d2c6a83 --- /dev/null +++ b/src/lib/y2network/s390_device_activators/ctc.rb @@ -0,0 +1,54 @@ +# 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/s390_device_activator" + +module Y2Network + module S390DeviceActivators + class Ctc < S390DeviceActivator + def_delegators :@builder, + :read_channel, :read_channel=, + :write_channel, :write_channel=, + :hwinfo, :protocol + + def device_id + return if read_channel.to_s.empty? + + [read_channel, write_channel].join(":") + end + + def configure_attributes + return [] unless builder.protocol + + ["protocol=#{builder.protocol}"] + end + + # Modifies the read, write and data channel from the the device id + def propose_channels + id = device_id_from(hwinfo.busid) + return unless id + self.read_channel, self.write_channel = id.split(":") + end + + def proposal + propose_channels unless device_id + end + end + end +end diff --git a/src/lib/y2network/s390_device_activators/lcs.rb b/src/lib/y2network/s390_device_activators/lcs.rb new file mode 100644 index 000000000..6af8c2f88 --- /dev/null +++ b/src/lib/y2network/s390_device_activators/lcs.rb @@ -0,0 +1,33 @@ +# 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/s390_device_activators/ctc" + +module Y2Network + module S390DeviceActivators + # The Lcs device activator is based in Ctc + class Lcs < Ctc + def configure_attributes + return [] unless builder.timeout + + ["lancmd_timeout=#{builder.timeout}"] + end + end + end +end diff --git a/src/lib/y2network/s390_device_activators/qeth.rb b/src/lib/y2network/s390_device_activators/qeth.rb new file mode 100644 index 000000000..fd2eaaac6 --- /dev/null +++ b/src/lib/y2network/s390_device_activators/qeth.rb @@ -0,0 +1,56 @@ +# 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/s390_device_activator" + +module Y2Network + module S390DeviceActivators + class Qeth < S390DeviceActivator + def_delegators :@builder, + :read_channel, :read_channel=, + :write_channel, :write_channel=, + :data_channel, :data_channel=, + :hwinfo, :attributes + + def device_id + return if read_channel.to_s.empty? + + [read_channel, write_channel, data_channel].join(":") + end + + # @return [Array] + def configure_attributes + return [] unless attributes + + attributes.split(" ") + end + + # Modifies the read, write and data channel from the the device id + def propose_channels + id = device_id_from(hwinfo.busid) + return unless id + self.read_channel, self.write_channel, self.data_channel = id.split(":") + end + + def proposal + propose_channels unless device_id + end + end + end +end diff --git a/src/lib/y2network/widgets/s390_common.rb b/src/lib/y2network/widgets/s390_common.rb index 0dff57bc5..ded7f832b 100644 --- a/src/lib/y2network/widgets/s390_common.rb +++ b/src/lib/y2network/widgets/s390_common.rb @@ -54,6 +54,7 @@ def help end end + # Widget for setting the Ctc device protocol to be used class S390Protocol < CWM::ComboBox # Constructor # @@ -66,7 +67,7 @@ def initialize(settings) # @see CWM::AbstractWidget def init - self.value = @settings.protocol + self.value = @settings.protocol.to_s end # @see CWM::AbstractWidget @@ -90,7 +91,7 @@ def items # @see CWM::AbstractWidget def store - @settings.protocol = value + @settings.protocol = value.to_i end # @see CWM::AbstractWidget @@ -99,6 +100,7 @@ def help end end + # Widget for specifying whether use the port number 0 or 1 class S390PortNumber < CWM::ComboBox # Constructor # @@ -135,6 +137,8 @@ def help end end + # This widget permits to pass defined any extra attribute to set during + # Qeth device activation class S390Attributes < CWM::InputField # Constructor # @@ -171,6 +175,7 @@ def store end end + # Checkbox for enabling IPA Takeover in the configured interface class S390IPAddressTakeover < CWM::CheckBox # Constructor # @@ -202,6 +207,9 @@ def store end end + # This custom widget contents a checkbox for enabling the layer2 support + # and an input field for setting the mac address to be used in case of + # enablement. class S390Layer2 < CWM::CustomWidget # Constructor # @@ -212,6 +220,7 @@ def initialize(settings) self.handle_all_events = true end + # @see CWM::AbstractWidget def contents VBox( Left(support_widget), @@ -219,13 +228,15 @@ def contents ) end + # @see CWM::AbstractWidget def init refresh end + # @see CWM::AbstractWidget def handle(event) case event["ID"] - when support_widget.widget_id, mac_address_widget.widget_id + when support_widget.widget_id refresh end @@ -247,6 +258,7 @@ def mac_address_widget end end + # Widget for enabling layer2 support in the configured device class S390Layer2Support < CWM::CheckBox # Constructor # @@ -263,6 +275,7 @@ def init # @see CWM::AbstractWidget def opt + # Needed for handling the event in other widgets that contents it. [:notify] end @@ -283,6 +296,7 @@ def store end end + # Widget for setting the mac address to be used in case of layer2 supported class S390Layer2Address < CWM::InputField # Constructor # @@ -297,11 +311,6 @@ def init self.value = @settings.lladdress end - # @see CWM::AbstractWidget - def opt - [:notify] - end - # @see CWM::AbstractWidget def label _("Layer2 MAC Address") diff --git a/test/y2network/dialogs/s390_ctc_activation_test.rb b/test/y2network/dialogs/s390_ctc_activation_test.rb index c5eba4cda..9a4edd97c 100644 --- a/test/y2network/dialogs/s390_ctc_activation_test.rb +++ b/test/y2network/dialogs/s390_ctc_activation_test.rb @@ -24,7 +24,10 @@ require "y2network/interface_config_builder" describe Y2Network::Dialogs::S390CtcActivation do - subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("ctc")) } + let(:builder) { Y2Network::InterfaceConfigBuilder.for("ctc") } + let(:activator) { Y2Network::S390DeviceActivator.for(builder) } + + subject { described_class.new(activator) } include_examples "CWM::Dialog" end diff --git a/test/y2network/dialogs/s390_device_activation_test.rb b/test/y2network/dialogs/s390_device_activation_test.rb index 7b6e3c1e6..aeef33770 100644 --- a/test/y2network/dialogs/s390_device_activation_test.rb +++ b/test/y2network/dialogs/s390_device_activation_test.rb @@ -24,10 +24,64 @@ require "y2network/interface_config_builder" describe Y2Network::Dialogs::S390DeviceActivation do - subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("qeth")) } + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + let(:activator) { Y2Network::S390DeviceActivator.for(builder) } + + subject { described_class.new(activator) } include_examples "CWM::Dialog" + describe ".new" do + it "creates a proposal for the configured device" do + expect(activator).to receive(:proposal) + described_class.new(activator) + end + end + + describe "#run" do + let(:configured) { true } + let(:dialog_action) { :next } + + before do + allow(activator).to receive(:configure).and_return(configured) + allow(activator).to receive(:configured_interface).and_return("eth4") + allow(subject).to receive(:cwm_show).and_return(dialog_action) + end + + context "when going :next" do + it "tries to activate the s390 device" do + expect(activator).to receive(:configure) + subject.run + end + + context "when activated the device" do + it "sets the builder name with the associated interface" do + subject.run + expect(builder.name).to eql("eth4") + end + + it "returns :next" do + expect(subject.run).to eql(:next) + end + end + + context "when failed the activation" do + let(:configured) { false } + it "popups an error" do + expect(Yast::Popup).to receive(:Error) + subject.run + end + + it "returns nil" do + expect(subject.run).to be_nil + end + end + end + + context "when pressed :abort" do + end + end + describe "#abort_handler" do it "asks for abort confirmation" do expect(Yast::Popup).to receive(:ReallyAbort).with(true) diff --git a/test/y2network/dialogs/s390_lcs_activation_test.rb b/test/y2network/dialogs/s390_lcs_activation_test.rb index 7d2d1fbe0..62bc87f84 100644 --- a/test/y2network/dialogs/s390_lcs_activation_test.rb +++ b/test/y2network/dialogs/s390_lcs_activation_test.rb @@ -24,7 +24,8 @@ require "y2network/interface_config_builder" describe Y2Network::Dialogs::S390LcsActivation do - subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("lcs")) } + let(:builder) { Y2Network::InterfaceConfigBuilder.for("lcs") } + subject { described_class.for(builder) } include_examples "CWM::Dialog" end diff --git a/test/y2network/dialogs/s390_qeth_activation_test.rb b/test/y2network/dialogs/s390_qeth_activation_test.rb index 7fa970f61..6439c11fe 100644 --- a/test/y2network/dialogs/s390_qeth_activation_test.rb +++ b/test/y2network/dialogs/s390_qeth_activation_test.rb @@ -24,7 +24,8 @@ require "y2network/interface_config_builder" describe Y2Network::Dialogs::S390QethActivation do - subject { described_class.new(Y2Network::InterfaceConfigBuilder.for("qeth")) } + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + subject { described_class.for(builder) } include_examples "CWM::Dialog" end diff --git a/test/y2network/interface_config_builder_test.rb b/test/y2network/interface_config_builder_test.rb index 38886bb37..c4100978c 100644 --- a/test/y2network/interface_config_builder_test.rb +++ b/test/y2network/interface_config_builder_test.rb @@ -289,4 +289,13 @@ end end end + + describe "#hwinfo_from" do + let(:hwinfo) { { "dev_name" => "", "busid" => "0.0.0700" } } + + it "overrides the builder hwinfo with the given hardware info" do + config_builder.hwinfo_from(hwinfo) + expect(config_builder.hwinfo.busid).to eq("0.0.0700") + end + end end diff --git a/test/y2network/interface_config_builders/ctc_test.rb b/test/y2network/interface_config_builders/ctc_test.rb index 80326cb54..7c55571c8 100644 --- a/test/y2network/interface_config_builders/ctc_test.rb +++ b/test/y2network/interface_config_builders/ctc_test.rb @@ -32,113 +32,9 @@ res end - let(:executor) { double("Yast::Execute", on_target!: "") } - let(:initialize_channels) { true } - - before do - allow(Yast::Execute).to receive(:stdout).and_return(executor) - builder.read_channel = "0.0.0900" if initialize_channels - builder.write_channel = "0.0.0901" if initialize_channels - end - describe "#type" do it "returns ctc type" do expect(subject.type).to eq Y2Network::InterfaceType::CTC end end - - describe "#configure" do - it "tries to activate the group device associated with the defined device id" do - expect(Yast::Execute).to receive(:on_target!) - .with("/sbin/chzdev", "ctc", builder.device_id, "-e", - "protocol=#{builder.protocol}", allowed_exitstatus: 0..255) - .and_return(0) - subject.configure - end - - context "when activated succesfully" do - it "returns true" do - expect(Yast::Execute).to receive(:on_target!).and_return(0) - expect(subject.configure).to eq(true) - end - end - - context "when failed the activation and returned a non zero return code" do - it "returns false" do - expect(Yast::Execute).to receive(:on_target!).and_return(34) - expect(subject.configure).to eq(false) - end - end - end - - describe "#configured_interface" do - before do - allow(executor).to receive(:on_target!) - .with(["/sbin/lszdev", builder.device_id, "-c", "names", "-n"]) - .and_return("ctc1") - end - - it "obtains the network interface associated with builder device id" do - expect(subject.configured_interface).to eq("ctc1") - end - end - - describe "#device_id_from" do - context "given the read or write device id" do - let(:device_id) { "0.0.0800:0.0.0801" } - let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } - before do - allow(builder).to receive(:hwinfo).and_return(hwinfo) - allow(executor).to receive(:on_target!) - .with(["/sbin/lszdev", "ctc", "-c", "id", "-n"]) - .and_return(device_id) - end - - it "obtains the triplet device ids listed by lszdev" do - expect(subject.device_id_from(hwinfo.busid)).to eq(device_id) - end - end - end - - describe "#device_id" do - it "returns the read and write channel device ids joined by ':'" do - expect(subject.device_id).to eql("0.0.0900:0.0.0901") - end - end - - describe "#propose_channels" do - context "when the read and write channel have not been initialized" do - let(:initialize_channels) { false } - let(:device_id) { "0.0.0800:0.0.0801" } - let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } - - before do - allow(builder).to receive(:device_id_from).with(write_channel).and_return(device_id) - allow(builder).to receive(:hwinfo).and_return(hwinfo) - end - - it "initializes them from the given busid" do - expect { builder.propose_channels }.to change { builder.device_id }.from(nil).to(device_id) - end - end - end - - describe "#proposal" do - context "when no device id has been initialized" do - let(:initialize_channels) { false } - it "proposes the channel device ids to be used" do - expect(subject).to receive(:propose_channels) - subject.proposal - end - end - - context "when the channel device ids have been set already" do - it "does not propose anything" do - expect(subject).to_not receive(:propose_channels) - subject.proposal - end - end - end end diff --git a/test/y2network/interface_config_builders/lcs_test.rb b/test/y2network/interface_config_builders/lcs_test.rb index 9b617358c..5060b7e49 100644 --- a/test/y2network/interface_config_builders/lcs_test.rb +++ b/test/y2network/interface_config_builders/lcs_test.rb @@ -37,110 +37,4 @@ expect(subject.type).to eq Y2Network::InterfaceType::LCS end end - - let(:executor) { double("Yast::Execute", on_target!: "") } - let(:initialize_channels) { true } - - before do - allow(Yast::Execute).to receive(:stdout).and_return(executor) - builder.read_channel = "0.0.0900" if initialize_channels - builder.write_channel = "0.0.0901" if initialize_channels - end - - describe "#configure" do - it "tries to activate the group device associated with the defined device id" do - expect(Yast::Execute).to receive(:on_target!) - .with("/sbin/chzdev", "lcs", builder.device_id, "-e", - "protocol=#{builder.protocol}", "lancmd_timeout=5", - allowed_exitstatus: 0..255) - .and_return(0) - subject.configure - end - - context "when activated succesfully" do - it "returns true" do - expect(Yast::Execute).to receive(:on_target!).and_return(0) - expect(subject.configure).to eq(true) - end - end - - context "when failed the activation and returned a non zero return code" do - it "returns false" do - expect(Yast::Execute).to receive(:on_target!).and_return(34) - expect(subject.configure).to eq(false) - end - end - end - - describe "#configured_interface" do - before do - allow(executor).to receive(:on_target!) - .with(["/sbin/lszdev", builder.device_id, "-c", "names", "-n"]) - .and_return("lcs1") - end - - it "obtains the network interface associated with builder device id" do - expect(subject.configured_interface).to eq("lcs1") - end - end - - describe "#device_id_from" do - context "given the read or write device id" do - let(:device_id) { "0.0.0800:0.0.0801" } - let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } - before do - allow(builder).to receive(:hwinfo).and_return(hwinfo) - allow(executor).to receive(:on_target!) - .with(["/sbin/lszdev", "lcs", "-c", "id", "-n"]) - .and_return(device_id) - end - - it "obtains the triplet device ids listed by lszdev" do - expect(subject.device_id_from(hwinfo.busid)).to eq(device_id) - end - end - end - - describe "#device_id" do - it "returns the read and write channel device ids joined by ':'" do - expect(subject.device_id).to eql("0.0.0900:0.0.0901") - end - end - - describe "#propose_channels" do - context "when the read and write channel have not been initialized" do - let(:initialize_channels) { false } - let(:device_id) { "0.0.0800:0.0.0801" } - let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } - - before do - allow(builder).to receive(:device_id_from).with(write_channel).and_return(device_id) - allow(builder).to receive(:hwinfo).and_return(hwinfo) - end - - it "initializes them from the given busid" do - expect { builder.propose_channels }.to change { builder.device_id }.from(nil).to(device_id) - end - end - end - - describe "#proposal" do - context "when no device id has been initialized" do - let(:initialize_channels) { false } - it "proposes the channel device ids to be used" do - expect(subject).to receive(:propose_channels) - subject.proposal - end - end - - context "when the channel device ids have been set already" do - it "does not propose anything" do - expect(subject).to_not receive(:propose_channels) - subject.proposal - end - end - end - end diff --git a/test/y2network/interface_config_builders/qeth_test.rb b/test/y2network/interface_config_builders/qeth_test.rb index a25fb9036..ebb1460af 100644 --- a/test/y2network/interface_config_builders/qeth_test.rb +++ b/test/y2network/interface_config_builders/qeth_test.rb @@ -32,113 +32,9 @@ res end - let(:executor) { double("Yast::Execute", on_target!: "") } - let(:initialize_channels) { true } - before do - allow(Yast::Execute).to receive(:stdout).and_return(executor) - if initialize_channels - builder.read_channel = "0.0.0800" - builder.write_channel = "0.0.0801" - builder.data_channel = "0.0.0802" - end - end - describe "#type" do it "returns qeth type" do expect(subject.type).to eq Y2Network::InterfaceType::QETH end end - - describe "#configure" do - it "tries to activate the group device associated with the defined device id" do - expect(Yast::Execute).to receive(:on_target!) - .with("/sbin/chzdev", "qeth", builder.device_id, "-e", allowed_exitstatus: 0..255).and_return(0) - subject.configure - end - - context "when activated succesfully" do - it "returns true" do - expect(Yast::Execute).to receive(:on_target!).and_return(0) - expect(subject.configure).to eq(true) - end - end - - context "when failed the activation and returned a non zero return code" do - it "returns false" do - expect(Yast::Execute).to receive(:on_target!).and_return(34) - expect(subject.configure).to eq(false) - end - end - end - - describe "#configured_interface" do - before do - allow(executor).to receive(:on_target!) - .with(["/sbin/lszdev", builder.device_id, "-c", "names", "-n"]) - .and_return("eth1") - end - - it "obtains the network interface associated with builder device id" do - expect(subject.configured_interface).to eq("eth1") - end - end - - describe "#device_id_from" do - context "given the read, write or data device id" do - let(:device_id) { "0.0.0700:0.0.0701:0.0.0702" } - let(:data_channel) { "0.0.0702" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => data_channel }) } - before do - allow(builder).to receive(:hwinfo).and_return(hwinfo) - allow(executor).to receive(:on_target!) - .with(["/sbin/lszdev", "qeth", "-c", "id", "-n"]) - .and_return(device_id) - end - - it "obtains the triplet device ids listed by lszdev" do - expect(subject.device_id_from("0.0.0702")).to eq(device_id) - end - end - end - - describe "#device_id" do - it "returns the channel, write and data device ids joined by ':'" do - expect(subject.device_id).to eql("0.0.0800:0.0.0801:0.0.0802") - end - end - - describe "#propose_channels" do - context "when the read and write channel have not been initialized" do - let(:initialize_channels) { false } - let(:device_id) { "0.0.0800:0.0.0801:0.0802" } - let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } - - before do - allow(builder).to receive(:device_id_from).with(write_channel).and_return(device_id) - allow(builder).to receive(:hwinfo).and_return(hwinfo) - end - - it "initializes them from the given busid" do - expect { builder.propose_channels }.to change { builder.device_id }.from(nil).to(device_id) - end - end - end - - describe "#proposal" do - context "when no device id has been initialized" do - let(:initialize_channels) { false } - it "proposes the channel device ids to be used" do - expect(subject).to receive(:propose_channels) - subject.proposal - end - end - - context "when the channel device ids have been set already" do - it "does not propose anything" do - expect(subject).to_not receive(:propose_channels) - subject.proposal - end - end - end end diff --git a/test/y2network/s390_device_activator_test.rb b/test/y2network/s390_device_activator_test.rb new file mode 100644 index 000000000..ff40e72ac --- /dev/null +++ b/test/y2network/s390_device_activator_test.rb @@ -0,0 +1,54 @@ +#!/usr/bin/env rspec + +# 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_relative "../test_helper" + +require "y2network/s390_device_activator" +require "y2network/interface_config_builder" + +describe Y2Network::S390DeviceActivator do + let(:logger) { double(info: true) } + let(:known_builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + let(:unknown_builder) { Y2Network::InterfaceConfigBuilder.for("dummy") } + + describe ".for" do + context "specialized class for given known builder" do + it "returns new instance of that class" do + expect(described_class.for(known_builder).class.to_s).to eq "Y2Network::S390DeviceActivators::Qeth" + end + end + + context "specialized class for given builder does NOT exist" do + before do + allow(described_class).to receive(:log).and_return(logger) + end + + it "returns nil" do + expect(described_class.for(unknown_builder)).to be_nil + end + + it "logs the error" do + expect(logger).to receive(:info).with(/Specialized device activator for dummy not found/) + described_class.for(unknown_builder) + end + end + end +end diff --git a/test/y2network/s390_device_activators/ctc_test.rb b/test/y2network/s390_device_activators/ctc_test.rb new file mode 100644 index 000000000..a68250c7b --- /dev/null +++ b/test/y2network/s390_device_activators/ctc_test.rb @@ -0,0 +1,140 @@ +#!/usr/bin/env rspec + +# 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_relative "../../test_helper" + +require "y2network/s390_device_activators/ctc" +require "y2network/interface_config_builders/ctc" + +describe Y2Network::S390DeviceActivators::Ctc do + let(:builder) do + res = Y2Network::InterfaceConfigBuilders::Ctc.new + res.name = "ctc0" + res + end + + subject(:activator) { Y2Network::S390DeviceActivators::Ctc.new(builder) } + + let(:executor) { double("Yast::Execute", on_target!: "") } + let(:initialize_channels) { true } + before do + allow(Yast::Execute).to receive(:stdout).and_return(executor) + builder.read_channel = "0.0.0900" if initialize_channels + builder.write_channel = "0.0.0901" if initialize_channels + builder.protocol = 0 + end + + describe "#configure" do + it "tries to activate the group device associated with the defined device id" do + expect(Yast::Execute).to receive(:on_target!) + .with("/sbin/chzdev", "ctc", subject.device_id, "-e", + "protocol=#{builder.protocol}", allowed_exitstatus: 0..255) + .and_return(0) + subject.configure + end + + context "when activated succesfully" do + it "returns true" do + expect(Yast::Execute).to receive(:on_target!).and_return(0) + expect(subject.configure).to eq(true) + end + end + + context "when failed the activation and returned a non zero return code" do + it "returns false" do + expect(Yast::Execute).to receive(:on_target!).and_return(34) + expect(subject.configure).to eq(false) + end + end + end + + describe "#configured_interface" do + before do + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", activator.device_id, "-c", "names", "-n"]) + .and_return("ctc1") + end + + it "obtains the network interface associated with builder device id" do + expect(subject.configured_interface).to eq("ctc1") + end + end + + describe "#device_id_from" do + context "given the read or write device id" do + let(:device_id) { "0.0.0800:0.0.0801" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + before do + allow(builder).to receive(:hwinfo).and_return(hwinfo) + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", "ctc", "-c", "id", "-n"]) + .and_return(device_id) + end + + it "obtains the triplet device ids listed by lszdev" do + expect(subject.device_id_from(hwinfo.busid)).to eq(device_id) + end + end + end + + describe "#device_id" do + it "returns the read and write channel device ids joined by ':'" do + expect(subject.device_id).to eql("0.0.0900:0.0.0901") + end + end + + describe "#propose_channels" do + context "when the read and write channel have not been initialized" do + let(:initialize_channels) { false } + let(:device_id) { "0.0.0800:0.0.0801" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + + before do + allow(subject).to receive(:device_id_from).with(write_channel).and_return(device_id) + allow(builder).to receive(:hwinfo).and_return(hwinfo) + end + + it "initializes them from the given busid" do + expect { subject.propose_channels }.to change { subject.device_id }.from(nil).to(device_id) + end + end + end + + describe "#proposal" do + context "when no device id has been initialized" do + let(:initialize_channels) { false } + it "proposes the channel device ids to be used" do + expect(subject).to receive(:propose_channels) + subject.proposal + end + end + + context "when the channel device ids have been set already" do + it "does not propose anything" do + expect(subject).to_not receive(:propose_channels) + subject.proposal + end + end + end + +end diff --git a/test/y2network/s390_device_activators/lcs_test.rb b/test/y2network/s390_device_activators/lcs_test.rb new file mode 100644 index 000000000..52e7ab639 --- /dev/null +++ b/test/y2network/s390_device_activators/lcs_test.rb @@ -0,0 +1,68 @@ +#!/usr/bin/env rspec + +# 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_relative "../../test_helper" + +require "y2network/s390_device_activators/lcs" +require "y2network/interface_config_builders/lcs" + +describe Y2Network::S390DeviceActivators::Lcs do + let(:builder) do + res = Y2Network::InterfaceConfigBuilders::Lcs.new + res.name = "lcs0" + res + end + + subject(:activator) { Y2Network::S390DeviceActivator.for(builder) } + + let(:executor) { double("Yast::Execute", on_target!: "") } + let(:initialize_channels) { true } + before do + allow(Yast::Execute).to receive(:stdout).and_return(executor) + builder.read_channel = "0.0.0900" if initialize_channels + builder.write_channel = "0.0.0901" if initialize_channels + builder.timeout = 15 + end + + describe "#configure" do + it "tries to activate the group device associated with the defined device id" do + expect(Yast::Execute).to receive(:on_target!) + .with("/sbin/chzdev", "lcs", subject.device_id, "-e", + "lancmd_timeout=15", allowed_exitstatus: 0..255) + .and_return(0) + subject.configure + end + + context "when activated succesfully" do + it "returns true" do + expect(Yast::Execute).to receive(:on_target!).and_return(0) + expect(subject.configure).to eq(true) + end + end + + context "when failed the activation and returned a non zero return code" do + it "returns false" do + expect(Yast::Execute).to receive(:on_target!).and_return(34) + expect(subject.configure).to eq(false) + end + end + end +end diff --git a/test/y2network/s390_device_activators/qeth_test.rb b/test/y2network/s390_device_activators/qeth_test.rb new file mode 100644 index 000000000..49b309f39 --- /dev/null +++ b/test/y2network/s390_device_activators/qeth_test.rb @@ -0,0 +1,141 @@ +#!/usr/bin/env rspec + +# 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_relative "../../test_helper" + +require "y2network/s390_device_activators/qeth" +require "y2network/interface_config_builders/qeth" + +describe Y2Network::S390DeviceActivators::Qeth do + let(:builder) do + res = Y2Network::InterfaceConfigBuilders::Qeth.new + res.name = "eth0" + res + end + + subject(:activator) { Y2Network::S390DeviceActivator.for(builder) } + + let(:executor) { double("Yast::Execute", on_target!: "") } + let(:initialize_channels) { true } + before do + allow(Yast::Execute).to receive(:stdout).and_return(executor) + if initialize_channels + builder.read_channel = "0.0.0700" + builder.write_channel = "0.0.0701" + builder.data_channel = "0.0.0702" + end + end + + describe "#configure" do + it "tries to activate the group device associated with the defined device id" do + expect(Yast::Execute).to receive(:on_target!) + .with("/sbin/chzdev", "qeth", subject.device_id, "-e", allowed_exitstatus: 0..255) + .and_return(0) + subject.configure + end + + context "when activated succesfully" do + it "returns true" do + expect(Yast::Execute).to receive(:on_target!).and_return(0) + expect(subject.configure).to eq(true) + end + end + + context "when failed the activation and returned a non zero return code" do + it "returns false" do + expect(Yast::Execute).to receive(:on_target!).and_return(34) + expect(subject.configure).to eq(false) + end + end + end + + describe "#configured_interface" do + before do + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", activator.device_id, "-c", "names", "-n"]) + .and_return("eth1") + end + + it "obtains the network interface associated with builder device id" do + expect(subject.configured_interface).to eq("eth1") + end + end + + describe "#device_id_from" do + context "given the read or write device id" do + let(:device_id) { "0.0.0800:0.0.0801:0.0.0802" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + before do + allow(builder).to receive(:hwinfo).and_return(hwinfo) + allow(executor).to receive(:on_target!) + .with(["/sbin/lszdev", "qeth", "-c", "id", "-n"]) + .and_return(device_id) + end + + it "obtains the triplet device ids listed by lszdev" do + expect(subject.device_id_from(hwinfo.busid)).to eq(device_id) + end + end + end + + describe "#device_id" do + it "returns the read and write channel device ids joined by ':'" do + expect(subject.device_id).to eql("0.0.0700:0.0.0701:0.0.0702") + end + end + + describe "#propose_channels" do + context "when the read and write channel have not been initialized" do + let(:initialize_channels) { false } + let(:device_id) { "0.0.0800:0.0.0801:0.0.0802" } + let(:write_channel) { "0.0.0801" } + let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + + before do + allow(subject).to receive(:device_id_from).with(write_channel).and_return(device_id) + allow(builder).to receive(:hwinfo).and_return(hwinfo) + end + + it "initializes them from the given busid" do + expect { subject.propose_channels }.to change { subject.device_id }.from(nil).to(device_id) + end + end + end + + describe "#proposal" do + context "when no device id has been initialized" do + let(:initialize_channels) { false } + it "proposes the channel device ids to be used" do + expect(subject).to receive(:propose_channels) + subject.proposal + end + end + + context "when the channel device ids have been set already" do + it "does not propose anything" do + expect(subject).to_not receive(:propose_channels) + subject.proposal + end + end + end + +end diff --git a/test/y2network/widgets/s390_common_test.rb b/test/y2network/widgets/s390_common_test.rb index dd126c5d5..510afb4e6 100644 --- a/test/y2network/widgets/s390_common_test.rb +++ b/test/y2network/widgets/s390_common_test.rb @@ -30,10 +30,34 @@ end describe Y2Network::Widgets::S390Protocol do - let(:builder) { Y2Network::InterfaceConfigBuilder.for("ctc") } + let(:builder) do + res = Y2Network::InterfaceConfigBuilder.for("ctc") + res.name = "ctc0" + res.protocol = 1 + res + end + subject { described_class.new(builder) } include_examples "CWM::ComboBox" + + describe "#init" do + it "initializes the widget value with the configured protocol" do + expect(subject).to receive(:value=).with("1") + subject.init + end + end + + describe "#store" do + before do + allow(subject).to receive(:value).and_return("4") + end + + it "modifies the builder protocol attribute with the widget value" do + expect { subject.store }.to change { builder.protocol }.from(1).to(4) + end + end + end describe Y2Network::Widgets::S390PortNumber do From 9a596c8e1d3da81bb612a83e2d6dbe31c72210c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Thu, 29 Aug 2019 11:02:31 +0100 Subject: [PATCH 05/11] Changes based on code review. --- src/lib/y2network/dialogs/s390_device_activation.rb | 2 ++ src/lib/y2network/s390_device_activator.rb | 9 ++++++++- src/lib/y2network/s390_device_activators/ctc.rb | 3 ++- src/lib/y2network/s390_device_activators/lcs.rb | 7 ++++++- src/lib/y2network/s390_device_activators/qeth.rb | 2 ++ src/lib/y2network/widgets/s390_common.rb | 5 +++-- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/lib/y2network/dialogs/s390_device_activation.rb b/src/lib/y2network/dialogs/s390_device_activation.rb index be091e7ac..cf4b43db7 100644 --- a/src/lib/y2network/dialogs/s390_device_activation.rb +++ b/src/lib/y2network/dialogs/s390_device_activation.rb @@ -31,6 +31,8 @@ class S390DeviceActivation < CWM::Dialog def self.for(builder) return nil unless builder.type case builder.type.short_name + # Both interfaces uses the qeth driver and uses the same configuration + # for activating the group device. when "qeth", "hsi" require "y2network/dialogs/s390_qeth_activation" require "y2network/s390_device_activators/qeth" diff --git a/src/lib/y2network/s390_device_activator.rb b/src/lib/y2network/s390_device_activator.rb index 424336be7..e8e3e8503 100644 --- a/src/lib/y2network/s390_device_activator.rb +++ b/src/lib/y2network/s390_device_activator.rb @@ -21,6 +21,7 @@ require "yast2/execute" module Y2Network + # This class is responsable of activating the supported S390 devices. class S390DeviceActivator extend Forwardable include Yast::Logger @@ -37,6 +38,9 @@ def self.for(builder) nil end + # Constructor + # + # @param [Y2Network::InterfaceConfigBuilder] def initialize(builder) @builder = builder end @@ -46,6 +50,9 @@ def configure_attributes [] end + # Convenience method for obtaining the short name of the builder's type.. + # + # @return string def type builder.type.short_name end @@ -89,7 +96,7 @@ def configured_interface Yast::Execute.stdout.on_target!(cmd).chomp end - # Makes a new proposal + # Makes a new configuration proposal def proposal end end diff --git a/src/lib/y2network/s390_device_activators/ctc.rb b/src/lib/y2network/s390_device_activators/ctc.rb index 59d2c6a83..0737454a1 100644 --- a/src/lib/y2network/s390_device_activators/ctc.rb +++ b/src/lib/y2network/s390_device_activators/ctc.rb @@ -21,6 +21,7 @@ module Y2Network module S390DeviceActivators + # This class is responsible of activating CTC group devices. class Ctc < S390DeviceActivator def_delegators :@builder, :read_channel, :read_channel=, @@ -39,7 +40,7 @@ def configure_attributes ["protocol=#{builder.protocol}"] end - # Modifies the read, write and data channel from the the device id + # Modifies the read and write channel from the the device id def propose_channels id = device_id_from(hwinfo.busid) return unless id diff --git a/src/lib/y2network/s390_device_activators/lcs.rb b/src/lib/y2network/s390_device_activators/lcs.rb index 6af8c2f88..5a8f61655 100644 --- a/src/lib/y2network/s390_device_activators/lcs.rb +++ b/src/lib/y2network/s390_device_activators/lcs.rb @@ -21,7 +21,12 @@ module Y2Network module S390DeviceActivators - # The Lcs device activator is based in Ctc + # The Lcs device activator is based in Ctc as both have two group device + # channels (read and write). + # + # In the past they shared also the configure command 'ctc_configure)' and + # the 'protocol' attribute was needed, but as the configuration has + # been moved to 'chzdev' command it is not the case anymore. class Lcs < Ctc def configure_attributes return [] unless builder.timeout diff --git a/src/lib/y2network/s390_device_activators/qeth.rb b/src/lib/y2network/s390_device_activators/qeth.rb index fd2eaaac6..b20fc5865 100644 --- a/src/lib/y2network/s390_device_activators/qeth.rb +++ b/src/lib/y2network/s390_device_activators/qeth.rb @@ -21,6 +21,8 @@ module Y2Network module S390DeviceActivators + # This class is responsible of activating OSA-Express (QDIO) and + # HiperSockets group devices (qeth driver). class Qeth < S390DeviceActivator def_delegators :@builder, :read_channel, :read_channel=, diff --git a/src/lib/y2network/widgets/s390_common.rb b/src/lib/y2network/widgets/s390_common.rb index ded7f832b..852027629 100644 --- a/src/lib/y2network/widgets/s390_common.rb +++ b/src/lib/y2network/widgets/s390_common.rb @@ -22,7 +22,7 @@ module Y2Network module Widgets - # Widget for setting the s390 device write channel + # Widget for setting the Lcs group device lancmd timeout class S390LanCmdTimeout < CWM::InputField # Constructor # @@ -133,7 +133,8 @@ def store # @see CWM::AbstractWidget def help - _("

Choose the Port Number for this interface.

") + _("

Choose which physical Port Number on the OSA Adapter " \ + "will be used by this interface. (0 by default)

") end end From c921d39ffc698a9d99e75266771cbfc2433a3b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Thu, 29 Aug 2019 14:11:13 +0100 Subject: [PATCH 06/11] Fix update of hardware information. --- src/lib/y2network/interface_config_builder.rb | 3 +++ src/lib/y2network/s390_device_activator.rb | 2 +- test/y2network/s390_device_activators/ctc_test.rb | 4 ++-- test/y2network/s390_device_activators/qeth_test.rb | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/lib/y2network/interface_config_builder.rb b/src/lib/y2network/interface_config_builder.rb index e65109548..aff3261f8 100644 --- a/src/lib/y2network/interface_config_builder.rb +++ b/src/lib/y2network/interface_config_builder.rb @@ -378,10 +378,13 @@ def configure_as_slave self.aliases = [] end + # @param info [Hash] Hardware information + # @return [Hwinfo] def hwinfo_from(info) @hwinfo = Hwinfo.new(info) end + # @return [Hwinfo] def hwinfo @hwinfo ||= Hwinfo.for(name) end diff --git a/src/lib/y2network/s390_device_activator.rb b/src/lib/y2network/s390_device_activator.rb index e8e3e8503..0169061bb 100644 --- a/src/lib/y2network/s390_device_activator.rb +++ b/src/lib/y2network/s390_device_activator.rb @@ -40,7 +40,7 @@ def self.for(builder) # Constructor # - # @param [Y2Network::InterfaceConfigBuilder] + # @param builder [Y2Network::InterfaceConfigBuilder] def initialize(builder) @builder = builder end diff --git a/test/y2network/s390_device_activators/ctc_test.rb b/test/y2network/s390_device_activators/ctc_test.rb index a68250c7b..124958f49 100644 --- a/test/y2network/s390_device_activators/ctc_test.rb +++ b/test/y2network/s390_device_activators/ctc_test.rb @@ -82,7 +82,7 @@ context "given the read or write device id" do let(:device_id) { "0.0.0800:0.0.0801" } let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + let(:hwinfo) { Y2Network::Hwinfo.new("busid" => write_channel) } before do allow(builder).to receive(:hwinfo).and_return(hwinfo) allow(executor).to receive(:on_target!) @@ -107,7 +107,7 @@ let(:initialize_channels) { false } let(:device_id) { "0.0.0800:0.0.0801" } let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + let(:hwinfo) { Y2Network::Hwinfo.new("busid" => write_channel) } before do allow(subject).to receive(:device_id_from).with(write_channel).and_return(device_id) diff --git a/test/y2network/s390_device_activators/qeth_test.rb b/test/y2network/s390_device_activators/qeth_test.rb index 49b309f39..af532227c 100644 --- a/test/y2network/s390_device_activators/qeth_test.rb +++ b/test/y2network/s390_device_activators/qeth_test.rb @@ -83,7 +83,7 @@ context "given the read or write device id" do let(:device_id) { "0.0.0800:0.0.0801:0.0.0802" } let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + let(:hwinfo) { Y2Network::Hwinfo.new("busid" => write_channel) } before do allow(builder).to receive(:hwinfo).and_return(hwinfo) allow(executor).to receive(:on_target!) @@ -108,7 +108,7 @@ let(:initialize_channels) { false } let(:device_id) { "0.0.0800:0.0.0801:0.0.0802" } let(:write_channel) { "0.0.0801" } - let(:hwinfo) { Y2Network::Hwinfo.new(hwinfo: { "busid" => write_channel }) } + let(:hwinfo) { Y2Network::Hwinfo.new("busid" => write_channel) } before do allow(subject).to receive(:device_id_from).with(write_channel).and_return(device_id) From bb660e05a2a5baa5fb248b32f54256ea8bc9153a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2019 09:29:07 +0100 Subject: [PATCH 07/11] Add the port number and layer attribute when configuring. --- .../y2network/s390_device_activators/qeth.rb | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib/y2network/s390_device_activators/qeth.rb b/src/lib/y2network/s390_device_activators/qeth.rb index b20fc5865..6b9bb9a8c 100644 --- a/src/lib/y2network/s390_device_activators/qeth.rb +++ b/src/lib/y2network/s390_device_activators/qeth.rb @@ -28,6 +28,7 @@ class Qeth < S390DeviceActivator :read_channel, :read_channel=, :write_channel, :write_channel=, :data_channel, :data_channel=, + :layer2, :port_number, :hwinfo, :attributes def device_id @@ -40,7 +41,7 @@ def device_id def configure_attributes return [] unless attributes - attributes.split(" ") + attributes.split(" ").concat([layer2_attribute, port_ttribute]) end # Modifies the read, write and data channel from the the device id @@ -54,5 +55,23 @@ def proposal propose_channels unless device_id end end + + private + + # Convenience method to obtain the layer2 attribute + # + # @return [String] + def layer2_attribute + return "" unless layer2 + + "layer2=#{layer2 ? 1 : 0}" + end + + # Convenience method to obtain the port number attribute + # + # @return [String] + def port_attribute + "port_number=#{port_number}" + end end end From 1049e5fb7657646d5b19bc0f9c160e55b02de3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2019 10:30:11 +0100 Subject: [PATCH 08/11] Validate mac address when layer2 is enabled. --- src/lib/y2network/widgets/s390_common.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/lib/y2network/widgets/s390_common.rb b/src/lib/y2network/widgets/s390_common.rb index 852027629..935e259d6 100644 --- a/src/lib/y2network/widgets/s390_common.rb +++ b/src/lib/y2network/widgets/s390_common.rb @@ -244,8 +244,30 @@ def handle(event) nil end + def validate + return true if !layer2? || valid_mac?(mac_address_widget.value) + + report_mac_error && false + end + private + def report_mac_error + # TRANSLATORS: Popup error about not valid MAC address provided + msg = _("The MAC address provided is not valid, please provide a valid one.") + Yast::Popup.Error(msg) + end + + def layer2? + !!support_widget.value + end + + def valid_mac?(mac_address) + return false if mac_address.to_s.empty? + return false if mac_address == "00:00:00:00:00:00" + !!(mac_address =~ /^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/i) + end + def refresh support_widget.checked? ? mac_address_widget.enable : mac_address_widget.disable end From f0532e966e71b0ea4e8f4c0cac9cfb0a43bba42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2019 13:17:40 +0100 Subject: [PATCH 09/11] Added tests for QETH layer2 support widgets --- src/lib/y2network/widgets/s390_common.rb | 15 +++- test/y2network/widgets/s390_common_test.rb | 84 ++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/lib/y2network/widgets/s390_common.rb b/src/lib/y2network/widgets/s390_common.rb index 935e259d6..8944c801f 100644 --- a/src/lib/y2network/widgets/s390_common.rb +++ b/src/lib/y2network/widgets/s390_common.rb @@ -247,7 +247,8 @@ def handle(event) def validate return true if !layer2? || valid_mac?(mac_address_widget.value) - report_mac_error && false + report_mac_error + false end private @@ -258,24 +259,36 @@ def report_mac_error Yast::Popup.Error(msg) end + # Convenience method to check whether layer2 support is enabled or not + # + # @return [Boolean] true if enabled; false otherwise def layer2? !!support_widget.value end + # Convenience method to check whether the MAC address provided is valid + # or not + # + # @return [Boolean] true when valid; false otherwise + # @param mac_address [String] def valid_mac?(mac_address) return false if mac_address.to_s.empty? return false if mac_address == "00:00:00:00:00:00" !!(mac_address =~ /^([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}$/i) end + # Convenience method to enable or disable the mac address widget when the + # layer2 support is modified def refresh support_widget.checked? ? mac_address_widget.enable : mac_address_widget.disable end + # @return [S390Layer2Support] def support_widget @support_widget ||= S390Layer2Support.new(@settings) end + # @return [S390Layer2Address] def mac_address_widget @mac_address_widget ||= S390Layer2Address.new(@settings) end diff --git a/test/y2network/widgets/s390_common_test.rb b/test/y2network/widgets/s390_common_test.rb index 510afb4e6..0c957b220 100644 --- a/test/y2network/widgets/s390_common_test.rb +++ b/test/y2network/widgets/s390_common_test.rb @@ -73,3 +73,87 @@ include_examples "CWM::InputField" end + +describe Y2Network::Widgets::S390Layer2 do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + let(:layer2_support) { true } + let(:layer2_address) { "00:00:00:00:00:00" } + let(:layer2_support_widget) do + instance_double("Y2Network::WidgetsS390Layer2Support", + value: layer2_support, widget_id: "layer2_support") + end + + let(:layer2_address_widget) do + instance_double("Y2Network::WidgetsS390Layer2Address", + value: layer2_address, widget_id: "layer2_address") + end + + subject { described_class.new(builder) } + + before do + allow(subject).to receive(:support_widget).and_return(layer2_support_widget) + allow(subject).to receive(:mac_address_widget).and_return(layer2_address_widget) + end + + include_examples "CWM::CustomWidget" + + describe "#handle" do + context "when the event handled is for the layer2_support widget" do + it "refresh the mac address widget" do + expect(subject).to receive(:refresh) + subject.handle("ID" => "layer2_support") + end + end + + it "returns nil" do + allow(subject).to receive(:refresh) + expect(subject.handle("ID" => "layer2_address")).to be_nil + expect(subject.handle("ID" => "layer2_support")).to be_nil + end + end + + describe "#validate" do + context "when the layer2 support is not enabled" do + let(:layer2_support) { false } + it "returns true" do + expect(subject.validate).to eql(true) + end + end + + context "when the layer2 support is enabled" do + context "and the MAC provided is valid" do + let(:layer2_address) { "02:00:00:00:01:FD" } + + it "returns true" do + expect(subject.validate).to eql(true) + end + end + + context "and the MAC address provided is invalid" do + it "returns false" do + allow(Yast::Popup).to receive(:Error) + expect(subject.validate).to eql(false) + end + + it "reports an error" do + expect(Yast::Popup).to receive(:Error).with(/MAC address provided is not valid/) + expect(subject.validate).to eql(false) + end + end + end + end +end + +describe Y2Network::Widgets::S390Layer2Support do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + subject { described_class.new(builder) } + + include_examples "CWM::CheckBox" +end + +describe Y2Network::Widgets::S390Layer2Address do + let(:builder) { Y2Network::InterfaceConfigBuilder.for("qeth") } + subject { described_class.new(builder) } + + include_examples "CWM::InputField" +end From ef57de8acdacd5c1fbfd62e41063b2b8fc8108ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Wed, 18 Sep 2019 14:47:58 +0100 Subject: [PATCH 10/11] Compare also the QETH extra attributes changes --- src/lib/y2network/connection_config/qeth.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/y2network/connection_config/qeth.rb b/src/lib/y2network/connection_config/qeth.rb index c4b698f24..7e5a09001 100644 --- a/src/lib/y2network/connection_config/qeth.rb +++ b/src/lib/y2network/connection_config/qeth.rb @@ -65,7 +65,8 @@ def initialize def ==(other) return false unless super - [:read_channel, :write_channel, :data_channel, :layer2, :port_number].all? do |method| + [:read_channel, :write_channel, :data_channel, + :layer2, :port_number, :attributes].all? do |method| public_send(method) == other.public_send(method) end end From 85503d660f0a0ea32c1bddd7f17a81bd00567240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Thu, 19 Sep 2019 09:04:36 +0100 Subject: [PATCH 11/11] Changes based on code review. --- src/lib/y2network/connection_config/qeth.rb | 4 +- .../y2network/dialogs/s390_ctc_activation.rb | 2 + .../dialogs/s390_device_activation.rb | 4 +- src/lib/y2network/interfaces_collection.rb | 2 +- src/lib/y2network/s390_device_activator.rb | 34 ++++++---- .../y2network/s390_device_activators/ctc.rb | 2 +- .../y2network/s390_device_activators/lcs.rb | 2 +- .../y2network/s390_device_activators/qeth.rb | 62 +++++++++++++------ src/lib/y2network/sysconfig/config_writer.rb | 2 + .../dialogs/s390_device_activation_test.rb | 2 +- .../s390_device_activators/ctc_test.rb | 6 +- .../s390_device_activators/qeth_test.rb | 10 +-- 12 files changed, 86 insertions(+), 46 deletions(-) diff --git a/src/lib/y2network/connection_config/qeth.rb b/src/lib/y2network/connection_config/qeth.rb index 7e5a09001..eae90618d 100644 --- a/src/lib/y2network/connection_config/qeth.rb +++ b/src/lib/y2network/connection_config/qeth.rb @@ -65,8 +65,8 @@ def initialize def ==(other) return false unless super - [:read_channel, :write_channel, :data_channel, - :layer2, :port_number, :attributes].all? do |method| + [:read_channel, :write_channel, :data_channel, :layer2, + :port_number, :ipa_takeover, :attributes].all? do |method| public_send(method) == other.public_send(method) end end diff --git a/src/lib/y2network/dialogs/s390_ctc_activation.rb b/src/lib/y2network/dialogs/s390_ctc_activation.rb index 50a337b44..36a2cc15d 100644 --- a/src/lib/y2network/dialogs/s390_ctc_activation.rb +++ b/src/lib/y2network/dialogs/s390_ctc_activation.rb @@ -24,6 +24,8 @@ module Dialogs # Dialog for activating a CTC device class S390CtcActivation < S390DeviceActivation def contents + # Already defined in the base class but added here just because of the + # pot check textdomain "network" HBox( diff --git a/src/lib/y2network/dialogs/s390_device_activation.rb b/src/lib/y2network/dialogs/s390_device_activation.rb index cf4b43db7..85dd6c0cd 100644 --- a/src/lib/y2network/dialogs/s390_device_activation.rb +++ b/src/lib/y2network/dialogs/s390_device_activation.rb @@ -61,7 +61,7 @@ def initialize(activator) textdomain "network" @activator = activator - @activator.proposal + @activator.propose! @builder = activator.builder end @@ -79,7 +79,7 @@ def run configured = activator.configure builder.name = activator.configured_interface if configured # TODO: Refresh the list of interfaces in yast_config. Take into - # account that the interface in yast_config does not have a nem so + # account that the interface in yast_config does not have a name so # the builder.interface is probably nil and should be obtained # through the busid. if !configured || builder.name.empty? diff --git a/src/lib/y2network/interfaces_collection.rb b/src/lib/y2network/interfaces_collection.rb index f9cbb6859..eb65c6ecb 100644 --- a/src/lib/y2network/interfaces_collection.rb +++ b/src/lib/y2network/interfaces_collection.rb @@ -74,7 +74,7 @@ def by_name(name) # @return [Interface,nil] Interface with the given busid or nil if not found def by_busid(busid) interfaces.find do |iface| - iface.hardware.busid == busid + iface.hardware && iface.hardware.busid == busid end end diff --git a/src/lib/y2network/s390_device_activator.rb b/src/lib/y2network/s390_device_activator.rb index 0169061bb..03996db3c 100644 --- a/src/lib/y2network/s390_device_activator.rb +++ b/src/lib/y2network/s390_device_activator.rb @@ -26,6 +26,13 @@ class S390DeviceActivator extend Forwardable include Yast::Logger + # Command for configuring z Systems specific devices + CONFIGURE_CMD = "/sbin/chzdev".freeze + # Command for displaying configuration of z Systems specific devices + LIST_CMD = "/sbin/lszdev".freeze + + def_delegators :@builder, :type + attr_accessor :builder # Load fresh instace of device activator for given interface config builder @@ -45,18 +52,23 @@ def initialize(builder) @builder = builder end + # Each s390 device type permits a set of attributes to be passed as extra + # options to the configuration command. This method return a list of each + # option in the form "attribute=value" + # + # @example qeth options + # @activator.configure_attributes + # #=> ["bridge_role=primary", "layer2=1", "portno=0", "ipa_takeover/enable=1"] + # + # @example ctc options + # @activator.configure_attributes + # #=> ["protocol=1"] + # # @return [Array] def configure_attributes [] end - # Convenience method for obtaining the short name of the builder's type.. - # - # @return string - def type - builder.type.short_name - end - # The device id to be used by lszdev or chzdev commands # # @return [String, nil] @@ -69,7 +81,7 @@ def device_id # @param channel [String] # @return [String] def device_id_from(channel) - cmd = "/sbin/lszdev #{type} -c id -n".split(" ") + cmd = [LIST_CMD, type.short_name, "-c", "id", "-n"] Yast::Execute.stdout.on_target!(cmd).split("\n").find do |d| d.include? channel @@ -81,7 +93,7 @@ def device_id_from(channel) # @return [Boolean] true when enabled def configure return false unless device_id - cmd = "/sbin/chzdev #{type} #{device_id} -e".split(" ").concat(configure_attributes) + cmd = [CONFIGURE_CMD, type.short_name, device_id, "-e"].concat(configure_attributes) Yast::Execute.on_target!(*cmd, allowed_exitstatus: 0..255).zero? end @@ -91,13 +103,13 @@ def configure # @return [String] device name def configured_interface return "" unless device_id - cmd = "/sbin/lszdev #{device_id} -c names -n".split(" ") + cmd = [LIST_CMD, device_id, "-c", "names", "-n"] Yast::Execute.stdout.on_target!(cmd).chomp end # Makes a new configuration proposal - def proposal + def propose! end end end diff --git a/src/lib/y2network/s390_device_activators/ctc.rb b/src/lib/y2network/s390_device_activators/ctc.rb index 0737454a1..6c3c771ec 100644 --- a/src/lib/y2network/s390_device_activators/ctc.rb +++ b/src/lib/y2network/s390_device_activators/ctc.rb @@ -47,7 +47,7 @@ def propose_channels self.read_channel, self.write_channel = id.split(":") end - def proposal + def propose! propose_channels unless device_id end end diff --git a/src/lib/y2network/s390_device_activators/lcs.rb b/src/lib/y2network/s390_device_activators/lcs.rb index 5a8f61655..14097cdaa 100644 --- a/src/lib/y2network/s390_device_activators/lcs.rb +++ b/src/lib/y2network/s390_device_activators/lcs.rb @@ -24,7 +24,7 @@ module S390DeviceActivators # The Lcs device activator is based in Ctc as both have two group device # channels (read and write). # - # In the past they shared also the configure command 'ctc_configure)' and + # In the past they shared also the configure command 'ctc_configure' and # the 'protocol' attribute was needed, but as the configuration has # been moved to 'chzdev' command it is not the case anymore. class Lcs < Ctc diff --git a/src/lib/y2network/s390_device_activators/qeth.rb b/src/lib/y2network/s390_device_activators/qeth.rb index 6b9bb9a8c..fc6198a43 100644 --- a/src/lib/y2network/s390_device_activators/qeth.rb +++ b/src/lib/y2network/s390_device_activators/qeth.rb @@ -28,7 +28,7 @@ class Qeth < S390DeviceActivator :read_channel, :read_channel=, :write_channel, :write_channel=, :data_channel, :data_channel=, - :layer2, :port_number, + :layer2, :port_number, :ipa_takeover, :hwinfo, :attributes def device_id @@ -37,11 +37,25 @@ def device_id [read_channel, write_channel, data_channel].join(":") end - # @return [Array] + # Return a list of the options to be set when activating the device. The + # list is composed by the attributes configured and the attributes that + # have their own variable (layer2, port_number and ipa_takeover). + # + # @example Qeth configuration + # activator.layer2 #=> true + # activator.port_number #=> 1 + # activator.ipa_takeover #=> true + # activator.attributes #=> "bridge_role=secondary" + # activator.configure_attributes #=> ["bridge_role=secondary", + # "ipa_takeover/enable=1", "layer2=1", "portno=1"] + # + # @see [S390DeviceActivator#configure_attributes] def configure_attributes - return [] unless attributes - - attributes.split(" ").concat([layer2_attribute, port_ttribute]) + extra_attributes = [] + extra_attributes.concat(attributes.split(" ")) if attributes + extra_attributes << ipa_takeover_attribute unless ipa_takeover.nil? + extra_attributes << layer2_attribute unless layer2.nil? + extra_attributes << port_attribute end # Modifies the read, write and data channel from the the device id @@ -51,27 +65,35 @@ def propose_channels self.read_channel, self.write_channel, self.data_channel = id.split(":") end - def proposal + def propose! propose_channels unless device_id end - end - private + private - # Convenience method to obtain the layer2 attribute - # - # @return [String] - def layer2_attribute - return "" unless layer2 + # Convenience method to obtain the layer2 attribute for the configuration + # command + # + # @return [String] + def layer2_attribute + "layer2=#{layer2 ? 1 : 0}" + end - "layer2=#{layer2 ? 1 : 0}" - end + # Convenience method to obtain the port number attribute for the + # configuration command + # + # @return [String] + def port_attribute + "portno=#{port_number}" + end - # Convenience method to obtain the port number attribute - # - # @return [String] - def port_attribute - "port_number=#{port_number}" + # Convenience method to obtain the port number attribute for the + # configuration command + # + # @return [String] + def ipa_takeover_attribute + "ipa_takeover/enable=#{ipa_takeover ? 1 : 0}" + end end end end diff --git a/src/lib/y2network/sysconfig/config_writer.rb b/src/lib/y2network/sysconfig/config_writer.rb index fc28530c7..25ce377d7 100644 --- a/src/lib/y2network/sysconfig/config_writer.rb +++ b/src/lib/y2network/sysconfig/config_writer.rb @@ -67,6 +67,8 @@ def write(config, old_config = nil) def write_interface_changes(config, old_config) # Write ifroute files config.interfaces.each do |dev| + # S390 devices that have not been activated yet will be part of the + # collection but with an empty name. next if dev.name.empty? routes = find_routes_for(dev, config.routing.routes) file = routes_file_for(dev) diff --git a/test/y2network/dialogs/s390_device_activation_test.rb b/test/y2network/dialogs/s390_device_activation_test.rb index aeef33770..4db495ba9 100644 --- a/test/y2network/dialogs/s390_device_activation_test.rb +++ b/test/y2network/dialogs/s390_device_activation_test.rb @@ -33,7 +33,7 @@ describe ".new" do it "creates a proposal for the configured device" do - expect(activator).to receive(:proposal) + expect(activator).to receive(:propose!) described_class.new(activator) end end diff --git a/test/y2network/s390_device_activators/ctc_test.rb b/test/y2network/s390_device_activators/ctc_test.rb index 124958f49..0dda0f382 100644 --- a/test/y2network/s390_device_activators/ctc_test.rb +++ b/test/y2network/s390_device_activators/ctc_test.rb @@ -120,19 +120,19 @@ end end - describe "#proposal" do + describe "#propose!" do context "when no device id has been initialized" do let(:initialize_channels) { false } it "proposes the channel device ids to be used" do expect(subject).to receive(:propose_channels) - subject.proposal + subject.propose! end end context "when the channel device ids have been set already" do it "does not propose anything" do expect(subject).to_not receive(:propose_channels) - subject.proposal + subject.propose! end end end diff --git a/test/y2network/s390_device_activators/qeth_test.rb b/test/y2network/s390_device_activators/qeth_test.rb index af532227c..5720f3446 100644 --- a/test/y2network/s390_device_activators/qeth_test.rb +++ b/test/y2network/s390_device_activators/qeth_test.rb @@ -47,7 +47,9 @@ describe "#configure" do it "tries to activate the group device associated with the defined device id" do expect(Yast::Execute).to receive(:on_target!) - .with("/sbin/chzdev", "qeth", subject.device_id, "-e", allowed_exitstatus: 0..255) + .with("/sbin/chzdev", "qeth", subject.device_id, "-e", + "ipa_takeover/enable=0", "layer2=0", "portno=0", + allowed_exitstatus: 0..255) .and_return(0) subject.configure end @@ -121,19 +123,19 @@ end end - describe "#proposal" do + describe "#propose!" do context "when no device id has been initialized" do let(:initialize_channels) { false } it "proposes the channel device ids to be used" do expect(subject).to receive(:propose_channels) - subject.proposal + subject.propose! end end context "when the channel device ids have been set already" do it "does not propose anything" do expect(subject).to_not receive(:propose_channels) - subject.proposal + subject.propose! end end end