Hello community, here is the log from the commit of package yast2-s390 for openSUSE:Leap:15.2 checked in at 2020-04-03 15:52:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:15.2/yast2-s390 (Old) and /work/SRC/openSUSE:Leap:15.2/.yast2-s390.new.3248 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-s390" Fri Apr 3 15:52:41 2020 rev:36 rq:790999 version:4.2.5 Changes: -------- --- /work/SRC/openSUSE:Leap:15.2/yast2-s390/yast2-s390.changes 2020-03-24 19:05:30.857495596 +0100 +++ /work/SRC/openSUSE:Leap:15.2/.yast2-s390.new.3248/yast2-s390.changes 2020-04-03 15:52:57.225842925 +0200 @@ -1,0 +2,7 @@ +Tue Mar 31 13:52:28 UTC 2020 - Imobach Gonzalez Sosa <[email protected]> + +- Do not try to activate DASD and zFCP devices that are already + active (bsc#1163149). Related to jsc#SLE-7396. +- 4.2.5 + +------------------------------------------------------------------- Old: ---- yast2-s390-4.2.4.tar.bz2 New: ---- yast2-s390-4.2.5.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yast2-s390.spec ++++++ --- /var/tmp/diff_new_pack.fUpvvI/_old 2020-04-03 15:52:57.545843292 +0200 +++ /var/tmp/diff_new_pack.fUpvvI/_new 2020-04-03 15:52:57.545843292 +0200 @@ -17,7 +17,7 @@ Name: yast2-s390 -Version: 4.2.4 +Version: 4.2.5 Release: 0 Summary: YaST2 - S/390 Specific Features Configuration License: GPL-2.0-only ++++++ yast2-s390-4.2.4.tar.bz2 -> yast2-s390-4.2.5.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/package/yast2-s390.changes new/yast2-s390-4.2.5/package/yast2-s390.changes --- old/yast2-s390-4.2.4/package/yast2-s390.changes 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/package/yast2-s390.changes 2020-04-02 10:15:43.000000000 +0200 @@ -1,4 +1,11 @@ ------------------------------------------------------------------- +Tue Mar 31 13:52:28 UTC 2020 - Imobach Gonzalez Sosa <[email protected]> + +- Do not try to activate DASD and zFCP devices that are already + active (bsc#1163149). Related to jsc#SLE-7396. +- 4.2.5 + +------------------------------------------------------------------- Mon Mar 23 13:56:13 UTC 2020 - Imobach Gonzalez Sosa <[email protected]> - Properly identify zFCP devices (bsc#1158443). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/package/yast2-s390.spec new/yast2-s390-4.2.5/package/yast2-s390.spec --- old/yast2-s390-4.2.4/package/yast2-s390.spec 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/package/yast2-s390.spec 2020-04-02 10:15:43.000000000 +0200 @@ -17,7 +17,7 @@ Name: yast2-s390 -Version: 4.2.4 +Version: 4.2.5 Release: 0 Group: System/YaST License: GPL-2.0-only diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/src/modules/DASDController.rb new/yast2-s390-4.2.5/src/modules/DASDController.rb --- old/yast2-s390-4.2.4/src/modules/DASDController.rb 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/src/modules/DASDController.rb 2020-04-02 10:15:43.000000000 +0200 @@ -143,7 +143,7 @@ channel = Ops.get_string(device, "channel", "") format = Ops.get_boolean(device, "format", false) do_diag = Ops.get_boolean(device, "diag", false) - act_ret = ActivateDisk(channel, do_diag) + act_ret = activate_disk_if_needed(channel, do_diag) # FIXME: general activation error handling - also in sync with below # for AutoInstall, format unformatted disks later at once # even disks manually selected for formatting must be reactivated @@ -381,71 +381,7 @@ # popup label UI.OpenDialog(Label(_("Reading Configured DASD Disks"))) - disks = Convert.convert( - SCR.Read(path(".probe.disk")), - from: "any", - to: "list <map <string, any>>" - ) - disks = Builtins.filter(disks) do |d| - Builtins.tolower(Ops.get_string(d, "device", "")) == "dasd" - end - - disks.sort_by! { |disk| FormatChannel(disk.fetch("sysfs_bus_id", "0.0.0000")) } - - disks = Builtins.maplist(disks) do |d| - channel = Ops.get_string(d, "sysfs_bus_id", "") - Ops.set(d, "channel", channel) - active = Ops.get_boolean(d, ["resource", "io", 0, "active"], false) - if active - device = Ops.get_string(d, "dev_name", "") - scr_out = Convert.to_map( - SCR.Execute( - path(".target.bash_output"), - Builtins.sformat("/sbin/dasdview --extended '%1' | grep formatted", device) - ) - ) - formatted = false - if Ops.get_integer(scr_out, "exit", 0) == 0 - out = Ops.get_string(scr_out, "stdout", "") - formatted = !Builtins.regexpmatch( - Builtins.toupper(out), - "NOT[ \t]*FORMATTED" - ) - end - Ops.set(d, "formatted", formatted) - - Ops.set(d, "partition_info", GetPartitionInfo(device)) if formatted - - diag_file = Builtins.sformat( - "/sys/%1/device/use_diag", - Ops.get_string(d, "sysfs_id", "") - ) - if FileUtils.Exists(diag_file) - use_diag = Convert.to_string( - SCR.Read(path(".target.string"), diag_file) - ) - Ops.set(d, "diag", Builtins.substring(use_diag, 0, 1) == "1") - Ops.set(@diag, channel, Builtins.substring(use_diag, 0, 1) == "1") - end - end - d = Builtins.filter(d) do |k, _v| - Builtins.contains( - [ - "channel", - "diag", - "resource", - "formatted", - "partition_info", - "dev_name", - "detail", - "device_id", - "sub_device_id" - ], - k - ) - end - deep_copy(d) - end + disks = find_disks(force_probing: true) index = -1 @devices = Builtins.listmap(disks) do |d| @@ -453,6 +389,10 @@ { index => d } end + disks.each do |dev| + @diag[dev["channel"]] = dev["diag"] if dev["diag"] + end + Builtins.y2milestone("probed DASD devices %1", @devices) UI.CloseDialog @@ -545,6 +485,22 @@ ret["exit"] end + # Activates a disk if it is not active + # + # When the disk is already activated, it returns '8' if the + # disk is unformatted or '0' otherwise. The idea is to mimic + # the same API than ActivateDisk. + # + # @return [Integer] Returns an error code (8 means 'unformatted'). + def activate_disk_if_needed(channel, diag) + disk = find_disks.find { |d| d["channel"] == channel } + if disk && active_disk?(disk) + log.info "Disk #{disk.inspect} is already active. Skipping the activation." + return disk["formatted"] ? 0 : 8 + end + ActivateDisk(channel, diag) + end + # Deactivate disk # @param [String] channel string Name of the disk to deactivate # @param [Boolean] diag boolean Activate DIAG or not @@ -851,6 +807,93 @@ Yast2::Popup.show(message, headline: headline, details: details) end end + + # Determines whether the disk is activated or not + # + # Since any of its IO elements in 'resource' is active, consider the device + # as 'active'. + # + # @param disk [Hash] + # @return [Boolean] + def active_disk?(disk) + io = disk.fetch("resource", {}).fetch("io", []) + io.any? { |i| i["active"] } + end + + # Returns the DASD disks + # + # Probes and returns the found DASD disks ordered by channel. + # It caches the found disks. + # + # @param force_probing [Boolean] Ignore the cached values and probes again. + # @return [Array<Hash>] Found DASD disks + def find_disks(force_probing: false) + return @disks if @disks && !force_probing + disks = Convert.convert( + SCR.Read(path(".probe.disk")), + from: "any", + to: "list <map <string, any>>" + ) + disks = Builtins.filter(disks) do |d| + Builtins.tolower(Ops.get_string(d, "device", "")) == "dasd" + end + + disks.sort_by! { |disk| FormatChannel(disk.fetch("sysfs_bus_id", "0.0.0000")) } + + @disks = Builtins.maplist(disks) do |d| + channel = Ops.get_string(d, "sysfs_bus_id", "") + Ops.set(d, "channel", channel) + active = Ops.get_boolean(d, ["resource", "io", 0, "active"], false) + if active + device = Ops.get_string(d, "dev_name", "") + scr_out = Convert.to_map( + SCR.Execute( + path(".target.bash_output"), + Builtins.sformat("/sbin/dasdview --extended '%1' | grep formatted", device) + ) + ) + formatted = false + if Ops.get_integer(scr_out, "exit", 0) == 0 + out = Ops.get_string(scr_out, "stdout", "") + formatted = !Builtins.regexpmatch( + Builtins.toupper(out), + "NOT[ \t]*FORMATTED" + ) + end + Ops.set(d, "formatted", formatted) + + Ops.set(d, "partition_info", GetPartitionInfo(device)) if formatted + + diag_file = Builtins.sformat( + "/sys/%1/device/use_diag", + Ops.get_string(d, "sysfs_id", "") + ) + if FileUtils.Exists(diag_file) + use_diag = Convert.to_string( + SCR.Read(path(".target.string"), diag_file) + ) + Ops.set(d, "diag", Builtins.substring(use_diag, 0, 1) == "1") + end + end + d = Builtins.filter(d) do |k, _v| + Builtins.contains( + [ + "channel", + "diag", + "resource", + "formatted", + "partition_info", + "dev_name", + "detail", + "device_id", + "sub_device_id" + ], + k + ) + end + deep_copy(d) + end + end end DASDController = DASDControllerClass.new diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/src/modules/ZFCPController.rb new/yast2-s390-4.2.5/src/modules/ZFCPController.rb --- old/yast2-s390-4.2.4/src/modules/ZFCPController.rb 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/src/modules/ZFCPController.rb 2020-04-02 10:15:43.000000000 +0200 @@ -52,7 +52,7 @@ @controllers = nil - @activated_controllers = {} + @activated_controllers = nil @disk_configured = false @@ -338,7 +338,7 @@ @controllers = Builtins.maplist(@controllers) do |c| Builtins.filter(c) do |k, _v| - Builtins.contains(["sysfs_bus_id"], k) + Builtins.contains(["sysfs_bus_id", "resource"], k) end end @@ -365,38 +365,8 @@ # popup label UI.OpenDialog(Label(_("Reading Configured ZFCP Devices"))) - disks = Convert.convert( - SCR.Read(path(".probe.disk")), - from: "any", - to: "list <map <string, any>>" - ) - disks = Builtins.filter(disks) do |d| - d["driver"] == "zfcp" - end - - tapes = Convert.convert( - SCR.Read(path(".probe.tape")), - from: "any", - to: "list <map <string, any>>" - ) - tapes = Builtins.filter(tapes) do |d| - Ops.get_string(d, "bus", "") == "SCSI" - end - - disks_tapes = Convert.convert( - Builtins.merge(disks, tapes), - from: "list", - to: "list <map <string, any>>" - ) - - disks_tapes = Builtins.maplist(disks_tapes) do |d| - Builtins.filter(d) do |k, _v| - Builtins.contains(["dev_name", "detail", "vendor", "device"], k) - end - end - index = -1 - @devices = Builtins.listmap(disks_tapes) do |d| + @devices = Builtins.listmap(find_disks(force_probing: true)) do |d| index = Ops.add(index, 1) { index => d } end @@ -578,33 +548,45 @@ nil end + # Activates the controller unless it was already activated + # + # @param channel [String] channel + def activate_controller(channel) + return if activated_controller?(channel) + + command2 = Builtins.sformat( + "/sbin/zfcp_host_configure '%1' %2", + channel, + 1 + ) + Builtins.y2milestone("Running command \"%1\"", command2) + ret2 = Convert.to_integer(SCR.Execute(path(".target.bash"), command2)) + Builtins.y2milestone( + "Command \"%1\" returned with exit code %2", + command2, + ret2 + ) + + if ret2 != 0 + ReportControllerActivationError(channel, ret2) + else + register_as_activated(channel) + end + end + # Activate a disk # @param [String] channel string channel # @param [String] wwpn string wwpn (hexa number) # @param [String] lun string lun (hexa number) def ActivateDisk(channel, wwpn, lun) - if !Ops.get(@activated_controllers, channel, false) - command2 = Builtins.sformat( - "/sbin/zfcp_host_configure '%1' %2", - channel, - 1 - ) - Builtins.y2milestone("Running command \"%1\"", command2) - ret2 = Convert.to_integer(SCR.Execute(path(".target.bash"), command2)) - Builtins.y2milestone( - "Command \"%1\" returned with exit code %2", - command2, - ret2 - ) - - if ret2 != 0 - ReportControllerActivationError(channel, ret2) - else - Ops.set(@activated_controllers, channel, true) - end + disk = find_disk(channel, wwpn, lun) + if disk + log.info "Disk #{disk.inspect} is already active. Skipping the activation." + else + activate_controller(channel) end - if wwpn != "" || lun != "" # we are not using allow_lun_scan + if disk.nil? && (wwpn != "" || lun != "") # we are not using allow_lun_scan command = Builtins.sformat( "/sbin/zfcp_disk_configure '%1' '%2' '%3' %4", channel, @@ -720,6 +702,100 @@ publish function: :DeactivateDisk, type: "void (string, string, string)" publish function: :GetWWPNs, type: "list <string> (string)" publish function: :GetLUNs, type: "list <string> (string, string)" + + private + + # Finds the activated controllers + # + # Initially, it reads the activated controllers from hwinfo. + # + # @return [Array<String>] List of controller channels + def activated_controllers + return @activated_controllers if @activated_controllers + ctrls = GetControllers().select do |ctrl| + io = ctrl.fetch("resource", {}).fetch("io", []) + io.any? { |i| i["active"] } + end + log.info "Already activated controllers: #{ctrls}" + @activated_controllers = ctrls.map { |c| c["sysfs_bus_id"] } + end + + # Mark a controller as activated + # + # @param channel [String] Channel + def register_as_activated(channel) + activated_controllers << channel + end + + # Determines whether a controller is activated or not + # + # @param channel [String] Channel + # @return [Boolean] + def activated_controller?(channel) + activated_controllers.include?(channel) + end + + # Returns the zFCP disks + # + # Probes and returns the found zFCP . It caches the found disks. + # + # @param force_probing [Boolean] Ignore the cached values and probes again. + # @return [Array<Hash>] Found zFCP disks + def find_disks(force_probing: false) + return @disks if @disks && !force_probing + disks = Convert.convert( + SCR.Read(path(".probe.disk")), + from: "any", + to: "list <map <string, any>>" + ) + disks = Builtins.filter(disks) do |d| + d["driver"] == "zfcp" + end + + tapes = Convert.convert( + SCR.Read(path(".probe.tape")), + from: "any", + to: "list <map <string, any>>" + ) + tapes = Builtins.filter(tapes) do |d| + Ops.get_string(d, "bus", "") == "SCSI" + end + + disks_tapes = Convert.convert( + Builtins.merge(disks, tapes), + from: "list", + to: "list <map <string, any>>" + ) + + @disks = Builtins.maplist(disks_tapes) do |d| + Builtins.filter(d) do |k, _v| + Builtins.contains(["dev_name", "detail", "vendor", "device", "io"], k) + end + end + end + + # Determines whether the disk is activated or not + # + # @param disk [Hash] + # @return [Boolean] + def active_disk?(disk) + io = disk.fetch("resource", {}).fetch("io", []).first + !!(io && io["active"]) + end + + # Finds a disk + # + # @param [String] channel string channel + # @param [String] wwpn string wwpn (hexa number) + # @param [String] lun string lun (hexa number) + # @return [Hash,nil] Disk information is found; nil is the disk is not found + def find_disk(channel, wwpn, lun) + find_disks.find do |d| + detail = d["detail"] + next unless detail + detail["controller_id"] == channel && detail["wwpn"] == wwpn && detail["fcp_lun"] == lun + end + end end ZFCPController = ZFCPControllerClass.new diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/test/dasd_controller_test.rb new/yast2-s390-4.2.5/test/dasd_controller_test.rb --- old/yast2-s390-4.2.4/test/dasd_controller_test.rb 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/test/dasd_controller_test.rb 2020-04-02 10:15:43.000000000 +0200 @@ -4,9 +4,101 @@ Yast.import "DASDController" -describe "Yast::DASDController" do +describe Yast::DASDController do subject { Yast::DASDController } + describe "#ActivateDisk" do + let(:exit_code) { 8 } + let(:channel) { "0.0.0100" } + + before do + allow(Yast::SCR).to receive(:Execute).and_return( + "exit" => exit_code + ) + end + + it "runs dasd_configure" do + expect(Yast::SCR).to receive(:Execute).with( + path(".target.bash_output"), "/sbin/dasd_configure '0.0.0100' 1 0" + ) + subject.ActivateDisk(channel, false) + end + + it "returns dasd_configure exit value" do + expect(subject.ActivateDisk(channel, false)).to eq(exit_code) + end + + context "when exit code is 7" do + let(:exit_code) { 7 } + + it "deactivates the device" do + expect(subject).to receive(:DeactivateDisk).with(channel, false) + subject.ActivateDisk(channel, false) + end + end + + context "when exit code is other than 7 or 8" do + let(:exit_code) { 1 } + + it "reports activation error" do + expect(subject).to receive(:ReportActivationError).with(channel, "exit" => exit_code) + subject.ActivateDisk(channel, false) + end + end + end + + describe "#activate_disk_if_needed" do + let(:channel) { "0.0.0150" } + let(:formatted) { true } + let(:active) { true } + + let(:disk) do + { + "dev_name" => "/dev/dasda", + "formatted" => formatted, + "channel" => channel, + "resource" => { + "io" => [{ "active" => active }] + } + } + end + + before do + allow(subject).to receive(:find_disks).and_return([disk]) + end + + context "when the disk is already active" do + it "does not activate the disk" do + expect(subject).to_not receive(:ActivateDisk) + subject.activate_disk_if_needed(channel, false) + end + + context "and it is not formatted" do + let(:formatted) { false } + + it "returns 8" do + expect(subject.activate_disk_if_needed(channel, false)).to eq(8) + end + end + + context "and it is formatted" do + it "returns 0" do + expect(subject.activate_disk_if_needed(channel, false)).to eq(0) + end + end + end + + context "when the disk is not active" do + let(:active) { false } + + it "activates the disk" do + expect(subject).to receive(:ActivateDisk).with(channel, false) + .and_return(0) + expect(subject.activate_disk_if_needed(channel, false)).to eq(0) + end + end + end + describe "#DeactivateDisk" do let(:auto) { false } let(:channel) { "0.0.0160" } @@ -110,7 +202,7 @@ it "returns true if .probe.disk contains DASDs" do expect(Yast::SCR).to receive(:Read).with(Yast.path(".probe.disk")).once .and_return(load_data("probe_disk_dasd.yml")) - expect(Yast::DASDController.IsAvailable()).to eq(true) + expect(subject.IsAvailable()).to eq(true) end end @@ -118,8 +210,8 @@ it "returns DASDs" do expect(Yast::SCR).to receive(:Read).with(Yast.path(".probe.disk")).once .and_return(load_data("probe_disk_dasd.yml")) - expect(Yast::DASDController.ProbeDisks()).to eq(nil) - expect(Yast::DASDController.GetDevices()).to eq( + expect(subject.ProbeDisks()).to eq(nil) + expect(subject.GetDevices()).to eq( 0 => { "detail" => { "cu_model" => 233, "dev_model" => 10, "lcss" => 0 }, "device_id" => 276880, "resource" => { "io" => [{ "active" => false, @@ -140,15 +232,26 @@ end end + describe "#FormatDisks" do + it "formats the given disks using dasdfmt" do + expect(Yast::SCR).to receive(:Execute).with( + path(".process.start_shell"), "/sbin/dasdfmt -Y -P 1 -b 4096 -y -r 10 -m 10 -f '/dev/dasda'" + ) + subject.FormatDisks(["/dev/dasda"], 8) + end + end + describe "#Write" do let(:data) do - { "devices" => [{ "channel" => "0.0.0100", "diag" => false, - "format" => true }], "format_unformatted" => true } + { "devices" => [{ "channel" => channel, "diag" => false, + "format" => format }], "format_unformatted" => format_unformatted } end + let(:format_unformatted) { false } + let(:format) { true } + let(:channel) { "0.0.0100" } before do - allow(Yast::SCR).to receive(:Execute).with(path(".target.bash_output"), - /\/sbin\/dasdview/) + allow(Yast::SCR).to receive(:Execute).with(path(".target.bash_output"), /\/sbin\/dasdview/) .and_return("exitstatus" => 0, "stdout" => load_file("dasdview_eckd.txt"), "stderr" => "") allow(Yast::Mode).to receive(:normal).and_return(false) @@ -156,29 +259,106 @@ allow(Yast::Mode).to receive(:autoinst).and_return(true) # speed up the test a bit allow(Yast::Builtins).to receive(:sleep) - allow(Yast::DASDController).to receive(:ActivateDisk).and_return(0) - allow(Yast::DASDController).to receive(:GetDeviceName).and_return("/dev/dasda") + allow(subject).to receive(:ActivateDisk).and_return(0) + allow(subject).to receive(:GetDeviceName).and_return("/dev/dasda") end - it "writes the dasd settings to the target (formating disks)" do - # bnc 928388 - expect(Yast::SCR).to receive(:Execute).with(path(".process.start_shell"), - "/sbin/dasdfmt -Y -P 1 -b 4096 -y -r 10 -m 10 -f '/dev/dasda'") + context "during autoinstallation" do + before do + subject.Import(data) + end - expect(Yast::DASDController.Import(data)).to eq(true) - expect(Yast::DASDController.Write).to eq(true) - end + it "activates the disk" do + allow(subject).to receive(:FormatDisks) + expect(subject).to receive(:ActivateDisk).with("0.0.0100", false) + subject.Write + end + + context "when 'format' is sets to true" do + let(:format) { true } - it "does not format disk for FBA disk" do - allow(Yast::SCR).to receive(:Execute).with(path(".target.bash_output"), - /\/sbin\/dasdview/) - .and_return("exitstatus" => 0, "stdout" => load_file("dasdview_fba.txt"), "stderr" => "") + it "formats the disk" do + expect(subject).to receive(:FormatDisks).with(["/dev/dasda"], 8) + expect(subject.Write).to eq(true) + end + end + + context "when 'format' is set to false" do + let(:format) { false } + + it "does not format the disk" do + expect(subject).to_not receive(:FormatDisks) + subject.Write + end + end + + context "when the activated device is not formatted" do + NOT_FORMATTED_CODE = 8 # means that the device is not formatted + + let(:format) { false } + + before do + allow(subject).to receive(:activate_disk_if_needed).with(channel, false) + .and_return(NOT_FORMATTED_CODE) + end - expect(Yast::SCR).to_not receive(:Execute).with(path(".process.start_shell"), - /dasdfmt.*\/dev\/dasda/) + context "and 'format_unformatted' is set to 'true'" do + let(:format_unformatted) { true } - expect(Yast::DASDController.Import(data)).to eq(true) - expect(Yast::DASDController.Write).to eq(true) + it "formats the device" do + expect(subject).to receive(:FormatDisks).with(["/dev/dasda"], anything) + subject.Write + end + + it "reactivates the disk" do + allow(subject).to receive(:FormatDisks) + expect(subject).to receive(:ActivateDisk).with(channel, false) + subject.Write + end + end + + context "and 'format_unformatted' is set to 'false'" do + let(:format_unformatted) { false } + + it "does not format the device" do + expect(subject).to_not receive(:FormatDisks) + subject.Write + end + + it "does not reactivate the disk" do + expect(subject).to_not receive(:ActivateDisk) + subject.Write + end + end + + context "and 'format' is set to 'true'" do + let(:format) { true } + let(:format_unformatted) { false } + + it "formats the device" do + expect(subject).to receive(:FormatDisks).with(["/dev/dasda"], anything) + subject.Write + end + + it "reactivates the disk" do + expect(subject).to receive(:FormatDisks) + expect(subject).to receive(:ActivateDisk).with(channel, false) + subject.Write + end + end + end + + it "does not format disk for FBA disk" do + allow(Yast::SCR).to receive(:Execute).with(path(".target.bash_output"), + /\/sbin\/dasdview/) + .and_return("exitstatus" => 0, "stdout" => load_file("dasdview_fba.txt"), "stderr" => "") + + expect(Yast::SCR).to_not receive(:Execute).with(path(".process.start_shell"), + /dasdfmt.*\/dev\/dasda/) + + expect(subject.Import(data)).to eq(true) + expect(subject.Write).to eq(true) + end end end @@ -242,6 +422,7 @@ "device" => "DASD", "dev_name" => "/dev/dasda", "sysfs_bus_id" => "0.0.0150", + "sysfs_id" => "/class/block/dasda", "resource" => { "io" => ["active" => true] } @@ -262,15 +443,33 @@ expect(subject.devices.size).to eq 1 expect(subject.devices.values.first["formatted"]).to eq false end + + context "when the 'use_diag' file exists" do + let(:diag_path) { "/sys//class/block/dasda/device/use_diag" } + + before do + allow(Yast::FileUtils).to receive(:Exists).with(diag_path) + .and_return(true) + allow(Yast::SCR).to receive(:Read) + .with(Yast::Path.new(".target.string"), diag_path) + .and_return("1") + end + + it "reads its value" do + subject.ProbeDisks + device = subject.devices.values.first + expect(device["diag"]).to eq(true) + expect(subject.diag).to eq("0.0.0150" => true) + end + end end end describe "#ActivateDiag" do it "deactivates and reactivates dasd" do - expect(Yast::DASDController).to receive(:DeactivateDisk).ordered - expect(Yast::DASDController).to receive(:ActivateDisk).ordered - expect(Yast::DASDController.ActivateDiag("0.0.3333", true)).to eq(nil) + expect(subject).to receive(:DeactivateDisk).ordered + expect(subject).to receive(:ActivateDisk).ordered + expect(subject.ActivateDiag("0.0.3333", true)).to eq(nil) end end - end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/test/data/probe_storage.yml new/yast2-s390-4.2.5/test/data/probe_storage.yml --- old/yast2-s390-4.2.4/test/data/probe_storage.yml 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/test/data/probe_storage.yml 2020-04-02 10:15:43.000000000 +0200 @@ -108,7 +108,7 @@ old_unique_key: _AAN.6czr7zOIMz1 resource: io: - - active: true + - active: false length: 3 mode: rw start: 64512 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-s390-4.2.4/test/zfcp_controller_test.rb new/yast2-s390-4.2.5/test/zfcp_controller_test.rb --- old/yast2-s390-4.2.4/test/zfcp_controller_test.rb 2020-03-23 15:07:39.000000000 +0100 +++ new/yast2-s390-4.2.5/test/zfcp_controller_test.rb 2020-04-02 10:15:43.000000000 +0200 @@ -4,23 +4,97 @@ Yast.import "ZFCPController" -describe "Yast::ZFCPController" do +describe Yast::ZFCPController do + before do + Yast::ZFCPController.main + end describe "#ActivateDisk" do - it "Activates the given disk" do - expect(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/zfcp_host_configure '1' 1/).and_return(0) - expect(Yast::ZFCPController).to_not receive(:ReportControllerActivationError) - Yast::ZFCPController.ActivateDisk(1, "", "") + before do + allow(Yast::Arch).to receive(:is_zkvm).and_return(false) + allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.storage")).once + .and_return(load_data("probe_storage.yml")) + allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.disk")).once + .and_return(load_data("probe_disk.yml")) + allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.tape")).once.and_return([]) + end + + it "activates the controller and the given disk" do + expect(subject).to receive(:activate_controller).with("0.0.fa00") + expect(Yast::SCR).to receive(:Execute) + .with(anything, /\/sbin\/zfcp_disk_configure '0.0.fa00' '0x500\d+' '0x401\d+' 1/) + .and_return(0) + subject.ActivateDisk("0.0.fa00", "0x5000000000000000", "0x4010400000000000") + end + + context "when the disk is already active" do + it "does not try to active the given disk" do + allow(subject).to receive(:activate_controller).with("0.0.fa00") + expect(Yast::SCR).to_not receive(:Execute) + subject.ActivateDisk("0.0.fa00", "0x500507630500873a", "0x4010400000000000") + end end end - describe "#GetControllers" do - after do - # workaround: the GetControllers() result is cached, force reset - # after each test - Yast::ZFCPController.instance_eval("@controllers = nil") + describe "#activate_controller" do + let(:channel) { "0.0.fc00" } + + before do + allow(Yast::Arch).to receive(:is_zkvm).and_return(false) + allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.storage")).once + .and_return(load_data("probe_storage.yml")) + + # Removing all fcp devices from blacklist + allow(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/vmcp q v fcp/).and_return( + "exit" => 0, + "stdout" => "FCP F800 ON FCP F807 CHPID 1C SUBCHANNEL = 000B\n F800 TOKEN = 0000000362A42C00" + ) + allow(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/cio_ignore -r f800/).and_return(0) + end + + it "activates the given controller" do + expect(Yast::SCR).to receive(:Execute) + .with(anything, /\/sbin\/zfcp_host_configure '0.0.fc00' 1/).and_return(0) + expect(subject).to_not receive(:ReportControllerActivationError) + subject.activate_controller(channel) + end + + it "does not activate a controller twice" do + expect(Yast::SCR).to receive(:Execute) + .with(anything, /\/sbin\/zfcp_host_configure '0.0.fc00' 1/).once.and_return(0) + subject.activate_controller(channel) + subject.activate_controller(channel) + end + + context "when the activation fails" do + before do + allow(Yast::SCR).to receive(:Execute) + .with(anything, /\/sbin\/zfcp_host_configure '0.0.fc00' 1/).and_return(1) + end + + it "reports the error" do + expect(subject).to receive(:ReportControllerActivationError) + .with("0.0.fc00", 1) + subject.activate_controller(channel) + end + end + + context "when the controller is already activated" do + let(:channel) { "0.0.fa00" } + + before do + allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.storage")).once + .and_return(load_data("probe_storage.yml")) + end + + it "does not activate the controller" do + expect(Yast::SCR).to_not receive(:Execute).with(anything, /\/sbin\/zfcp_host_configure/) + subject.activate_controller(channel) + end end + end + describe "#GetControllers" do it "Returns all controllers" do allow(Yast::Arch).to receive(:is_zkvm).and_return(false) expect(Yast::SCR).to receive(:Read).with(Yast.path(".probe.storage")).once @@ -33,14 +107,14 @@ ) expect(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/cio_ignore -r f800/).and_return(0) - expect(Yast::ZFCPController.GetControllers).to eq( - [ - { "sysfs_bus_id"=>"0.0.f800" }, - { "sysfs_bus_id"=>"0.0.f900" }, - { "sysfs_bus_id"=>"0.0.fa00" }, - { "sysfs_bus_id"=>"0.0.fc00" } - ] + ctrls = subject.GetControllers + expect(ctrls).to contain_exactly( + hash_including("sysfs_bus_id" => "0.0.f800"), + hash_including("sysfs_bus_id" => "0.0.f900"), + hash_including("sysfs_bus_id" => "0.0.fa00"), + hash_including("sysfs_bus_id" => "0.0.fc00") ) + expect(ctrls.first["resource"]).to be_a(Hash) end context "no ZFCP controller found" do @@ -60,7 +134,7 @@ let(:is_zkvm) { false } it "reports a warning" do expect(Yast::Report).to receive(:Warning).with(/Cannot evaluate ZFCP controllers/) - Yast::ZFCPController.GetControllers + subject.GetControllers end end @@ -68,7 +142,7 @@ let(:is_zkvm) { true } it "does not report a warning" do expect(Yast::Report).to_not receive(:Warning).with(/Cannot evaluate ZFCP controllers/) - Yast::ZFCPController.GetControllers + subject.GetControllers end end end @@ -81,8 +155,8 @@ { "controller_id" => "0.0.f800" }, { "controller_id" => "0.0.f900" }] } - expect(Yast::ZFCPController.Import(import_data)).to eq(true) - expect(Yast::ZFCPController.GetDeviceIndex("0.0.f800", "", "")).to eq(2) + expect(subject.Import(import_data)).to eq(true) + expect(subject.GetDeviceIndex("0.0.f800", "", "")).to eq(2) end end @@ -94,8 +168,8 @@ end it "Probing disk" do - expect(Yast::ZFCPController.ProbeDisks()).to eq(nil) - expect(Yast::ZFCPController.devices).to eq(load_data("device_list.yml")) + expect(subject.ProbeDisks()).to eq(nil) + expect(subject.devices).to eq(load_data("device_list.yml")) end end @@ -107,10 +181,10 @@ { "controller_id" => "0.0.f800" }, { "controller_id" => "0.0.f900" }] } - expect(Yast::ZFCPController.Import(import_data)).to eq(true) - Yast::ZFCPController.filter_max = Yast::ZFCPController.FormatChannel("0.0.FA00") - Yast::ZFCPController.filter_min = Yast::ZFCPController.FormatChannel("0.0.f900") - expect(Yast::ZFCPController.GetFilteredDevices()).to eq( + expect(subject.Import(import_data)).to eq(true) + subject.filter_max = subject.FormatChannel("0.0.FA00") + subject.filter_min = subject.FormatChannel("0.0.f900") + expect(subject.GetFilteredDevices()).to eq( 0 => { "detail"=>{ "controller_id" => "0.0.fa00", "wwpn" => "", "fcp_lun" => "" } }, 4 => { "detail"=>{ "controller_id" => "0.0.f900", "wwpn" => "", "fcp_lun" => "" } } )
