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" => "" } }
       )


Reply via email to