Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package yast2-s390 for openSUSE:Factory 
checked in at 2023-06-09 20:40:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-s390 (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-s390.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-s390"

Fri Jun  9 20:40:08 2023 rev:31 rq:1091788 version:4.6.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-s390/yast2-s390.changes    2023-05-10 
17:39:29.835693566 +0200
+++ /work/SRC/openSUSE:Factory/.yast2-s390.new.15902/yast2-s390.changes 
2023-06-09 20:43:31.304674130 +0200
@@ -1,0 +2,7 @@
+Mon Jun  5 10:09:02 UTC 2023 - José Iván López González <jlo...@suse.com>
+
+- Expose zFCP core functionallity (related to
+  gh#openSUSUE/agama#594)
+- 4.6.2
+
+-------------------------------------------------------------------

Old:
----
  yast2-s390-4.6.1.tar.bz2

New:
----
  yast2-s390-4.6.2.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-s390.spec ++++++
--- /var/tmp/diff_new_pack.Vf2mpk/_old  2023-06-09 20:43:32.296679892 +0200
+++ /var/tmp/diff_new_pack.Vf2mpk/_new  2023-06-09 20:43:32.316680007 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-s390
-Version:        4.6.1
+Version:        4.6.2
 Release:        0
 Group:          System/YaST
 License:        GPL-2.0-only

++++++ yast2-s390-4.6.1.tar.bz2 -> yast2-s390-4.6.2.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-s390-4.6.1/package/yast2-s390.changes 
new/yast2-s390-4.6.2/package/yast2-s390.changes
--- old/yast2-s390-4.6.1/package/yast2-s390.changes     2023-05-10 
17:09:12.000000000 +0200
+++ new/yast2-s390-4.6.2/package/yast2-s390.changes     2023-06-09 
11:19:12.000000000 +0200
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Mon Jun  5 10:09:02 UTC 2023 - José Iván López González <jlo...@suse.com>
+
+- Expose zFCP core functionallity (related to
+  gh#openSUSUE/agama#594)
+- 4.6.2
+
+-------------------------------------------------------------------
 Wed May 10 13:35:34 UTC 2023 - Stefan Hundhammer <shundham...@suse.com>
 
 - Prevent crash when the user closes the DASD context menu
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-s390-4.6.1/package/yast2-s390.spec 
new/yast2-s390-4.6.2/package/yast2-s390.spec
--- old/yast2-s390-4.6.1/package/yast2-s390.spec        2023-05-10 
17:09:12.000000000 +0200
+++ new/yast2-s390-4.6.2/package/yast2-s390.spec        2023-06-09 
11:19:12.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-s390
-Version:        4.6.1
+Version:        4.6.2
 Release:        0
 Group:          System/YaST
 License:        GPL-2.0-only
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-s390-4.6.1/src/lib/y2s390/zfcp.rb 
new/yast2-s390-4.6.2/src/lib/y2s390/zfcp.rb
--- old/yast2-s390-4.6.1/src/lib/y2s390/zfcp.rb 1970-01-01 01:00:00.000000000 
+0100
+++ new/yast2-s390-4.6.2/src/lib/y2s390/zfcp.rb 2023-06-09 11:19:12.000000000 
+0200
@@ -0,0 +1,183 @@
+# Copyright (c) [2023] 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 "yaml"
+
+module Y2S390
+  # Manager for zFCP devices
+  class ZFCP
+    include Yast
+    include Yast::Logger
+
+    # Detected controllers
+    #
+    # @return [Array<Hash>] keys for each hash:
+    #   "sysfs_bus_id", "resource"
+    attr_reader :controllers
+
+    # Detected LUN disks
+    #
+    # @return [Array<Hash>] keys for each hash:
+    #   "dev_name", "detail", "vendor", "device" and "io".
+    attr_reader :disks
+
+    def initialize
+      @controllers = []
+      @disks = []
+    end
+
+    # Probes the zFCP controllers
+    def probe_controllers
+      make_all_devices_visible
+
+      storage_devices = Yast::SCR.Read(path(".probe.storage"))
+      controllers = storage_devices.select { |i| i["device"] == "zFCP 
controller" }
+
+      @controllers = controllers.map { |c| c.slice("sysfs_bus_id", "resource") 
}
+    end
+
+    # Probes the zFCP disks
+    def probe_disks
+      storage_disks = read_mock_disks || Yast::SCR.Read(path(".probe.disk"))
+      zfcp_disks = storage_disks.select { |d| d["driver"] == "zfcp" }
+
+      tapes = Yast::SCR.Read(path(".probe.tape"))
+      scsi_tapes = tapes.select { |t| t["bus"] == "SCSI" }
+
+      disks = zfcp_disks + scsi_tapes
+
+      @disks = disks.map { |d| d.slice("dev_name", "detail", "vendor", 
"device", "io") }
+    end
+
+    # Runs the command for activating a controller
+    #
+    # @note All LUNs are automatically activated if "allow_lun_scan" is 
active, see
+    #   
https://www.ibm.com/docs/en/linux-on-systems?topic=wsd-configuring-devices.
+    #
+    # @param channel [String] E.g., "0.0.fa00"
+    # @return [Hash] See {#run}. The exit code corresponds to the chzdev one.
+    def activate_controller(channel)
+      command = format("/sbin/zfcp_host_configure '%s' %d", channel, 1)
+      run(command)
+    end
+
+    # Whether the controller is activated
+    #
+    # @param channel [String] E.g., "0.0.fa00"
+    # @return [Boolean]
+    def activated_controller?(channel)
+      controller = controllers.find { |c| c["sysfs_bus_id"] == channel }
+      return false unless controller
+
+      io = controller.dig("resource", "io") || []
+      io.any? { |i| i["active"] }
+    end
+
+    # Runs the command for activating a zFCP disk
+    #
+    # @param channel [String] E.g., "0.0.fa00"
+    # @param wwpn [String] E.g., "0x500507630708d3b3"
+    # @param lun [String] E.g., "0x0013000000000000"
+    #
+    # @return [Hash] See {#run}. The exit code corresponds to the chzdev one.
+    def activate_disk(channel, wwpn, lun)
+      command = format("/sbin/zfcp_disk_configure '%s' '%s' '%s' %d", channel, 
wwpn, lun, 1)
+      run(command)
+    end
+
+    # Runs the command for deactivating a zFCP disk
+    #
+    # @note Deactivate fails if "allow_lun_scan" is active, see
+    #   
https://www.ibm.com/docs/en/linux-on-systems?topic=wsd-configuring-devices.
+    #
+    # @param channel [String] E.g., "0.0.fa00"
+    # @param wwpn [String] E.g., "0x500507630708d3b3"
+    # @param lun [String] E.g., "0x0013000000000000"
+    #
+    # @return [Hash] See {#run}. The exit code corresponds to the chzdev one.
+    def deactivate_disk(channel, wwpn, lun)
+      command = format("/sbin/zfcp_disk_configure '%s' '%s' '%s' %d", channel, 
wwpn, lun, 0)
+      run(command)
+    end
+
+    # Runs the command for finding WWPNs
+    #
+    # @param channel [String] E.g., "0.0.fa00"
+    # @return [Hash] See {#run}
+    def find_wwpns(channel)
+      command = format("zfcp_san_disc -b '%s' -W", channel)
+      run(command)
+    end
+
+    # Runs the command for finding LUNs
+    #
+    # @param channel [String] E.g., "0.0.fa00"
+    # @param wwpn [String] E.g., "0x500507630708d3b3"
+    #
+    # @return [Hash] See {#run}
+    def find_luns(channel, wwpn)
+      command = format("zfcp_san_disc -b '%s' -p '%s' -L", channel, wwpn)
+      run(command)
+    end
+
+  private
+
+    # Sets all detected controllers as visible
+    def make_all_devices_visible
+      # Checking if it is a z/VM and evaluating all FCP controllers in order 
to activate
+      output = run("/sbin/vmcp q v fcp")
+      return if output["exit"] != 0
+
+      fcp_lines = output["stdout"].map(&:split).select { |l| l.first == "FCP" }
+      devices = fcp_lines.map { |l| l[1].downcase }
+
+      # Remove all needed devices from CIO device driver blacklist in order to 
see it
+      devices.each do |device|
+        log.info "Removing #{device} from the CIO device driver blacklist"
+        run("/sbin/cio_ignore -r #{device}")
+      end
+    end
+
+    # Runs the given command
+    #
+    # @param command [String]
+    # @return [Hash] Output of the command which has these keys: "exit", 
"stdout", "stderr".
+    def run(command)
+      Yast::SCR.Execute(path(".target.bash_output"), command).tap do |output|
+        log.info("command #{command} output #{output}")
+
+        output["exit"] = output["exit"].to_i
+        output["stdout"] = output["stdout"].split("\n").reject(&:empty?)
+      end
+    end
+
+    # Reads the mock disks from the YAML file pointed by YAST2_S390_PROBE_DISK
+    #
+    # Suggestion: YAST2_S390_PROBE_DISK=test/data/probe_disk.yml rake run[zfcp]
+    #
+    # @return [Array<Hash>, nil] List of mocked LUN disks or nil if no file 
found
+    def read_mock_disks
+      mock_filename = ENV["YAST2_S390_PROBE_DISK"]
+      return nil unless mock_filename
+
+      YAML.safe_load(File.read(mock_filename))
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-s390-4.6.1/src/modules/ZFCPController.rb 
new/yast2-s390-4.6.2/src/modules/ZFCPController.rb
--- old/yast2-s390-4.6.1/src/modules/ZFCPController.rb  2023-05-10 
17:09:12.000000000 +0200
+++ new/yast2-s390-4.6.2/src/modules/ZFCPController.rb  2023-06-09 
11:19:12.000000000 +0200
@@ -29,6 +29,7 @@
 
 require "yaml"
 require "yast"
+require "y2s390/zfcp"
 
 module Yast
   class ZFCPControllerClass < Module
@@ -43,6 +44,8 @@
       Yast.import "Popup"
       Yast.import "Arch"
 
+      @zfcp = Y2S390::ZFCP.new
+
       @devices = {}
 
       @filter_min = "0.0.0000"
@@ -50,7 +53,9 @@
 
       @previous_settings = {}
 
-      @controllers = nil
+      @probed_controllers = false
+
+      @probed_disks = false
 
       @activated_controllers = nil
 
@@ -296,49 +301,22 @@
     # Get available zfcp controllers
     # @return [Array<Hash{String => Object>}] of availabel Controllers
     def GetControllers
-      if @controllers.nil?
-        # Checking if it is a z/VM and evaluating all fcp controllers in
-        # order to activate
-        ret_vmcp = SCR.Execute(path(".target.bash_output"), "/sbin/vmcp q v 
fcp")
-        if ret_vmcp["exit"] == 0
-          devices = ret_vmcp["stdout"].split("\n").collect do |line|
-            columns = line.split
-            columns[1].downcase if columns[0] == "FCP"
-          end.compact
-
-          # Remove all needed devices from CIO device driver blacklist
-          # in order to see it
-          devices.each do |device|
-            log.info "Removing #{device} from the CIO device driver blacklist"
-            SCR.Execute(path(".target.bash"), "/sbin/cio_ignore -r #{device}")
-          end
-        end
-
-        @controllers = Convert.convert(
-          SCR.Read(path(".probe.storage")),
-          from: "any",
-          to:   "list <map <string, any>>"
-        )
-        @controllers = Builtins.filter(@controllers) do |c|
-          Ops.get_string(c, "device", "") == "zFCP controller"
-        end
-
-        @controllers = Builtins.maplist(@controllers) do |c|
-          Builtins.filter(c) do |k, _v|
-            Builtins.contains(["sysfs_bus_id", "resource"], k)
-          end
-        end
+      if !@probed_controllers
+        zfcp.probe_controllers
 
         # zKVM uses virtio devices instead of ZFCP, skip the warning in that 
case
-        if ret_vmcp != 0 && @controllers.empty? && !Arch.is_zkvm
+        if zfcp.controllers.none? && !Arch.is_zkvm
           # TRANSLATORS: warning message
           Report.Warning(_("Cannot evaluate ZFCP controllers (e.g. in 
LPAR).\n" \
             "You will have to set it manually."))
         end
 
-        Builtins.y2milestone("probed ZFCP controllers %1", @controllers)
+        Builtins.y2milestone("probed ZFCP controllers %1", zfcp.controllers)
+
+        @probed_controllers = true
       end
-      deep_copy(@controllers)
+
+      zfcp.controllers
     end
 
     # Check if ZFCP subsystem is available
@@ -541,21 +519,11 @@
     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
-      )
+      output = zfcp.activate_controller(channel)
+      exit_code = output["exit"]
 
-      if ret2 != 0
-        ReportControllerActivationError(channel, ret2)
+      if exit_code != 0
+        ReportControllerActivationError(channel, exit_code)
       else
         register_as_activated(channel)
       end
@@ -574,22 +542,8 @@
       end
 
       if disk.nil? && (wwpn != "" || lun != "") # we are not using 
allow_lun_scan
-        command = Builtins.sformat(
-          "/sbin/zfcp_disk_configure '%1' '%2' '%3' %4",
-          channel,
-          wwpn,
-          lun,
-          1
-        )
-        Builtins.y2milestone("Running command \"%1\"", command)
-        ret = Convert.to_integer(SCR.Execute(path(".target.bash"), command))
-        Builtins.y2milestone(
-          "Command \"%1\" returned with exit code %2",
-          command,
-          ret
-        )
-
-        ReportActivationError(channel, ret)
+        output = zfcp.activate_disk(channel, wwpn, lun)
+        ReportActivationError(channel, output["exit"])
       end
 
       @disk_configured = true
@@ -602,58 +556,26 @@
     # @param [String] wwpn string wwpn (hexa number)
     # @param [String] lun string lun   (hexa number)
     def DeactivateDisk(channel, wwpn, lun)
-      command = Builtins.sformat(
-        "/sbin/zfcp_disk_configure '%1' '%2' '%3' %4",
-        channel,
-        wwpn,
-        lun,
-        0
-      )
-      Builtins.y2milestone("Running command \"%1\"", command)
-      ret = Convert.to_integer(SCR.Execute(path(".target.bash"), command))
-      Builtins.y2milestone(
-        "Command \"%1\" returned with exit code %2",
-        command,
-        ret
-      )
-
-      ReportActivationError(channel, ret)
+      output = zfcp.deactivate_disk(channel, wwpn, lun)
+      ReportActivationError(channel, output["exit"])
 
       @disk_configured = true
 
       nil
     end
 
-    def runCommand(cmd)
-      ret = []
-      cmd_output = Convert.convert(
-        SCR.Execute(path(".target.bash_output"), cmd),
-        from: "any",
-        to:   "map <string, any>"
-      )
-      if Ops.get_integer(cmd_output, "exit", -1) == 0
-        ret = Builtins.splitstring(
-          Ops.get_string(cmd_output, "stdout", ""),
-          "\n"
-        )
-        ret = Builtins.filter(ret) do |row|
-          Ops.greater_than(Builtins.size(row), 0)
-        end
-      else
-        Popup.Error(Ops.get_string(cmd_output, "stderr", ""))
-      end
-      Builtins.y2milestone("command %1, output %2", cmd, cmd_output)
-      deep_copy(ret)
+    def command_result(output)
+      return output["stdout"] if output["exit"] == 0
+
+      Popup.Error(output["stderr"])
     end
 
     def GetWWPNs(busid)
-      runCommand(Builtins.sformat("zfcp_san_disc -b '%1' -W", busid))
+      command_result(zfcp.find_wwpns(busid))
     end
 
     def GetLUNs(busid, wwpn)
-      runCommand(
-        Builtins.sformat("zfcp_san_disc -b '%1' -p '%2' -L", busid, wwpn)
-      )
+      command_result(zfcp.find_luns(busid, wwpn))
     end
 
     publish variable: :devices, type: "map <integer, map <string, any>>"
@@ -692,20 +614,7 @@
 
   private
 
-    # In production, call SCR.Read(.probe.disk).
-    # For testing, point YAST2_S390_PROBE_DISK to a YAML file
-    # with the mock value.
-    # Suggesstion:
-    #   YAST2_S390_PROBE_DISK=test/data/probe_disk.yml rake run"[zfcp]"
-    # @return [Array<Hash>] .probe.disk output
-    def probe_or_mock_disks
-      mock_filename = ENV["YAST2_S390_PROBE_DISK"]
-      if mock_filename
-        YAML.safe_load(File.read(mock_filename))
-      else
-        SCR.Read(path(".probe.disk"))
-      end
-    end
+    attr_reader :zfcp
 
     # Finds the activated controllers
     #
@@ -715,12 +624,11 @@
     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"] }
+      channels = GetControllers().map { |c| c["sysfs_bus_id"] }
+      active_channels = channels.select { |c| zfcp.activated_controller?(c) }
+
+      log.info "Already activated controllers: #{active_channels}"
+      @activated_controllers = active_channels
     end
 
     # Mark a controller as activated
@@ -745,42 +653,12 @@
     # @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 = probe_or_mock_disks
-      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
+      if !@probed_disks || force_probing
+        zfcp.probe_disks
+        @probed_disks = true
       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"])
+      zfcp.disks
     end
 
     # Finds a disk
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-s390-4.6.1/test/y2s390/zfcp_test.rb 
new/yast2-s390-4.6.2/test/y2s390/zfcp_test.rb
--- old/yast2-s390-4.6.1/test/y2s390/zfcp_test.rb       1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-s390-4.6.2/test/y2s390/zfcp_test.rb       2023-06-09 
11:19:12.000000000 +0200
@@ -0,0 +1,244 @@
+#!/usr/bin/env rspec
+
+# Copyright (c) [2023] 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 "y2s390/zfcp"
+
+describe Y2S390::ZFCP do
+  describe "#probe_controllers" do
+    before do
+      allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.storage"))
+        .and_return(controllers_data)
+
+      allow(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/vmcp q v 
fcp/)
+        .and_return(vmcp_output)
+
+      allow(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/cio_ignore 
-r/)
+        .and_return("exit" => 0, "stdout" => "")
+    end
+
+    let(:controllers_data) { load_data("probe_storage.yml") }
+
+    let(:vmcp_output) do
+      {
+        "exit"   => 0,
+        "stdout" => "FCP  F800 ON FCP   F807 CHPID 1C SUBCHANNEL = 000B\n" \
+                    "F800 TOKEN = 0000000362A42C00"
+      }
+    end
+
+    it "removes all FCP devices from the blacklist" do
+      expect(Yast::SCR).to receive(:Execute).with(anything, 
/\/sbin\/cio_ignore -r f800/)
+
+      subject.probe_controllers
+    end
+
+    it "reads all the zFCP controllers" do
+      expect(subject.controllers).to eq([])
+
+      subject.probe_controllers
+
+      expect(subject.controllers).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")
+      )
+    end
+  end
+
+  describe "#probe_disks" do
+    before do
+      allow(Yast::SCR).to receive(:Read).with(Yast.path(".probe.disk"))
+        .and_return(disks_data)
+
+      allow(Yast::SCR).to 
receive(:Read).with(Yast.path(".probe.tape")).and_return([])
+    end
+
+    let(:disks_data) { load_data("probe_disk.yml") }
+
+    it "reads all the zFCP disks" do
+      expect(subject.disks).to eq([])
+
+      subject.probe_disks
+
+      expect(subject.disks).to contain_exactly(
+        hash_including("dev_name" => "/dev/sda"),
+        hash_including("dev_name" => "/dev/sdb")
+      )
+    end
+  end
+
+  describe "#activate_controller" do
+    before do
+      allow(Yast::SCR).to receive(:Execute).with(anything, 
command).and_return(output)
+    end
+
+    let(:command) { /\/sbin\/zfcp_host_configure '0.0.fc00' 1/ }
+
+    let(:output) { { "exit" => 0, "stdout" => "" } }
+
+    it "tries to activate the given controller" do
+      expect(Yast::SCR).to receive(:Execute).with(anything, command)
+
+      subject.activate_controller("0.0.fc00")
+    end
+
+    it "returns the output of the command" do
+      result = subject.activate_controller("0.0.fc00")
+
+      expect(result).to eq(output)
+    end
+  end
+
+  describe "#activated_controller?" do
+    before do
+      allow(subject).to receive(:controllers).and_return(controllers)
+    end
+
+    let(:controllers) do
+      [
+        {
+          "sysfs_bus_id" => "0.0.fa00",
+          "resource"     => { "io" => [{ "active" => true }] }
+        },
+        {
+          "sysfs_bus_id" => "0.0.fc00",
+          "resource"     => { "io" => [{ "active" => false }] }
+        }
+      ]
+    end
+
+    context "if the given controller is activated" do
+      let(:channel) { "0.0.fa00" }
+
+      it "returns true" do
+        expect(subject.activated_controller?(channel)).to eq(true)
+      end
+    end
+
+    context "if the given controller is not activated" do
+      let(:channel) { "0.0.fc00" }
+
+      it "returns false" do
+        expect(subject.activated_controller?(channel)).to eq(false)
+      end
+    end
+  end
+
+  describe "#activate_disk" do
+    before do
+      allow(Yast::SCR).to receive(:Execute).with(anything, 
command).and_return(output)
+    end
+
+    let(:command) do
+      /\/sbin\/zfcp_disk_configure '0.0.fc00' '0x500507630708d3b3' 
'0x0000000000000005' 1/
+    end
+
+    let(:output) { { "exit" => 1, "stdout" => "An error" } }
+
+    it "tries to activate a zFCP disk" do
+      expect(Yast::SCR).to receive(:Execute).with(anything, command)
+
+      subject.activate_disk("0.0.fc00", "0x500507630708d3b3", 
"0x0000000000000005")
+    end
+
+    it "returns the output of the command" do
+      result = subject.activate_disk("0.0.fc00", "0x500507630708d3b3", 
"0x0000000000000005")
+
+      expect(result).to eq(output)
+    end
+  end
+
+  describe "#deactivate_disk" do
+    before do
+      allow(Yast::SCR).to receive(:Execute).with(anything, 
command).and_return(output)
+    end
+
+    let(:command) do
+      /\/sbin\/zfcp_disk_configure '0.0.fc00' '0x500507630708d3b3' 
'0x0000000000000005' 0/
+    end
+
+    let(:output) { { "exit" => 0, "stdout" => "" } }
+
+    it "tries to deactivate a zFCP disk" do
+      expect(Yast::SCR).to receive(:Execute).with(anything, command)
+
+      subject.deactivate_disk("0.0.fc00", "0x500507630708d3b3", 
"0x0000000000000005")
+    end
+
+    it "returns the output of the command" do
+      result = subject.deactivate_disk("0.0.fc00", "0x500507630708d3b3", 
"0x0000000000000005")
+
+      expect(result).to eq(output)
+    end
+  end
+
+  describe "#find_wwpns" do
+    before do
+      allow(Yast::SCR).to receive(:Execute).with(anything, 
command).and_return(output)
+    end
+
+    let(:command) { /zfcp_san_disc -b '0.0.fc00' -W/ }
+
+    let(:output) { { "exit" => 0, "stdout" => 
"0x500507630703d3b3\n0x500507630708d3b3" } }
+
+    it "runs the command for finding WWPNs" do
+      expect(Yast::SCR).to receive(:Execute).with(anything, command)
+
+      subject.find_wwpns("0.0.fc00")
+    end
+
+    it "returns the output of the command" do
+      result = subject.find_wwpns("0.0.fc00")
+
+      expect(result).to eq(
+        "exit"   => 0,
+        "stdout" => ["0x500507630703d3b3", "0x500507630708d3b3"]
+      )
+    end
+  end
+
+  describe "#find_luns" do
+    before do
+      allow(Yast::SCR).to receive(:Execute).with(anything, 
command).and_return(output)
+    end
+
+    let(:command) { /zfcp_san_disc -b '0.0.fc00' -p '0x500507630708d3b3' -L/ }
+
+    let(:output) { { "exit" => 0, "stdout" => 
"0x0000000000000005\n0x0000000000000006" } }
+
+    it "runs the command for finding LUNs" do
+      expect(Yast::SCR).to receive(:Execute).with(anything, command)
+
+      subject.find_luns("0.0.fc00", "0x500507630708d3b3")
+    end
+
+    it "returns the output of the command" do
+      result = subject.find_luns("0.0.fc00", "0x500507630708d3b3")
+
+      expect(result).to eq(
+        "exit"   => 0,
+        "stdout" => ["0x0000000000000005", "0x0000000000000006"]
+      )
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-s390-4.6.1/test/zfcp_controller_test.rb 
new/yast2-s390-4.6.2/test/zfcp_controller_test.rb
--- old/yast2-s390-4.6.1/test/zfcp_controller_test.rb   2023-05-10 
17:09:12.000000000 +0200
+++ new/yast2-s390-4.6.2/test/zfcp_controller_test.rb   2023-06-09 
11:19:12.000000000 +0200
@@ -23,7 +23,7 @@
       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)
+        .and_return("exit" => "0", "stdout" => "")
       subject.ActivateDisk("0.0.fa00", "0x5000000000000000", 
"0x4010400000000000")
     end
 
@@ -49,27 +49,31 @@
         "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)
+      allow(Yast::SCR).to receive(:Execute).with(anything, /\/sbin\/cio_ignore 
-r f800/)
+        .and_return("exit" => "0", "stdout" => "")
     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(Yast::SCR)
+        .to receive(:Execute).with(anything, /\/sbin\/zfcp_host_configure 
'0.0.fc00' 1/)
+        .and_return("exit" => "0", "stdout" => "")
       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)
+      expect(Yast::SCR)
+        .to receive(:Execute).with(anything, /\/sbin\/zfcp_host_configure 
'0.0.fc00' 1/).once
+        .and_return("exit" => "0", "stdout" => "")
       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)
+        allow(Yast::SCR)
+          .to receive(:Execute).with(anything, /\/sbin\/zfcp_host_configure 
'0.0.fc00' 1/)
+          .and_return("exit" => "1", "stdout" => "")
       end
 
       it "reports the error" do
@@ -105,7 +109,9 @@
         "exit"   => 0,
         "stdout" => "FCP  F800 ON FCP   F807 CHPID 1C SUBCHANNEL = 000B\n  
F800 TOKEN = 0000000362A42C00"
       )
-      expect(Yast::SCR).to receive(:Execute).with(anything, 
/\/sbin\/cio_ignore -r f800/).and_return(0)
+      expect(Yast::SCR)
+        .to receive(:Execute).with(anything, /\/sbin\/cio_ignore -r f800/)
+        .and_return("exit" => "0", "stdout" => "")
 
       ctrls = subject.GetControllers
       expect(ctrls).to contain_exactly(

Reply via email to