• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / d-installer / 4512499803

pending completion
4512499803

Pull #501

github

Unknown Committer
Unknown Commit Message
Pull Request #501: [web] Add DASD UI - first version

462 of 863 branches covered (53.53%)

Branch coverage included in aggregate %.

64 of 235 new or added lines in 9 files covered. (27.23%)

14 existing lines in 1 file now uncovered.

4668 of 6129 relevant lines covered (76.16%)

10.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.62
/service/lib/dinstaller/dbus/storage/manager.rb
1
# frozen_string_literal: true
2

3
# Copyright (c) [2022-2023] SUSE LLC
4
#
5
# All Rights Reserved.
6
#
7
# This program is free software; you can redistribute it and/or modify it
8
# under the terms of version 2 of the GNU General Public License as published
9
# by the Free Software Foundation.
10
#
11
# This program is distributed in the hope that it will be useful, but WITHOUT
12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
# more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with this program; if not, contact SUSE LLC.
18
#
19
# To contact SUSE LLC about this file by physical or electronic mail, you may
20
# find current contact information at www.suse.com.
21

22
require "dbus"
1✔
23
require "yast"
1✔
24
require "dinstaller/dbus/base_object"
1✔
25
require "dinstaller/dbus/with_service_status"
1✔
26
require "dinstaller/dbus/interfaces/progress"
1✔
27
require "dinstaller/dbus/interfaces/service_status"
1✔
28
require "dinstaller/dbus/interfaces/validation"
1✔
29
require "dinstaller/dbus/interfaces/dasd"
1✔
30
require "dinstaller/dbus/storage/proposal"
1✔
31
require "dinstaller/dbus/storage/proposal_settings_converter"
1✔
32
require "dinstaller/dbus/storage/volume_converter"
1✔
33
require "dinstaller/dbus/storage/with_iscsi_auth"
1✔
34
require "dinstaller/dbus/storage/iscsi_nodes_tree"
1✔
35

36
Yast.import "Arch"
1✔
37

38
module DInstaller
1✔
39
  module DBus
1✔
40
    module Storage
1✔
41
      # D-Bus object to manage storage installation
42
      class Manager < BaseObject
1✔
43
        include WithISCSIAuth
1✔
44
        include WithServiceStatus
1✔
45
        include ::DBus::ObjectManager
1✔
46
        include DBus::Interfaces::Progress
1✔
47
        include DBus::Interfaces::ServiceStatus
1✔
48
        include DBus::Interfaces::Validation
1✔
49

50
        PATH = "/org/opensuse/DInstaller/Storage1"
1✔
51
        private_constant :PATH
1✔
52

53
        # Constructor
54
        #
55
        # @param backend [DInstaller::Storage::Manager]
56
        # @param logger [Logger]
57
        def initialize(backend, logger)
1✔
58
          super(PATH, logger: logger)
34✔
59
          @backend = backend
34✔
60
          register_proposal_callbacks
34✔
61
          register_progress_callbacks
34✔
62
          register_service_status_callbacks
34✔
63
          register_iscsi_callbacks
34✔
64
          register_software_callbacks
34✔
65
          return unless Yast::Arch.s390
34✔
66

67
          singleton_class.include DBus::Interfaces::Dasd
10✔
68
          register_and_extend_dasd_callbacks
10✔
69
        end
70

71
        STORAGE_INTERFACE = "org.opensuse.DInstaller.Storage1"
1✔
72
        private_constant :STORAGE_INTERFACE
1✔
73

74
        def probe
1✔
75
          busy_while do
×
76
            backend.probe
×
77
            storage_properties_changed
×
78
          end
79
        end
80

81
        def install
1✔
82
          busy_while { backend.install }
×
83
        end
84

85
        def finish
1✔
86
          busy_while { backend.finish }
×
87
        end
88

89
        # Whether the system is in a deprecated status
90
        #
91
        # @return [Boolean]
92
        def deprecated_system
1✔
93
          backend.deprecated_system
2✔
94
        end
95

96
        dbus_interface STORAGE_INTERFACE do
1✔
97
          dbus_method(:Probe) { probe }
1✔
98
          dbus_method(:Install) { install }
1✔
99
          dbus_method(:Finish) { finish }
1✔
100
          dbus_reader(:deprecated_system, "b")
1✔
101
        end
102

103
        PROPOSAL_CALCULATOR_INTERFACE = "org.opensuse.DInstaller.Storage1.Proposal.Calculator"
1✔
104
        private_constant :PROPOSAL_CALCULATOR_INTERFACE
1✔
105

106
        # List of disks available for installation
107
        #
108
        # Each device is represented by an array containing the name of the device and the label to
109
        # represent that device in the UI when further information is needed.
110
        #
111
        # @return [Array<String, String, Hash>]
112
        def available_devices
1✔
113
          proposal.available_devices.map do |dev|
2✔
114
            [dev.name, proposal.device_label(dev), {}]
2✔
115
          end
116
        end
117

118
        # Volumes used as template for creating a new proposal
119
        #
120
        # @return [Hash]
121
        def volume_templates
1✔
122
          converter = VolumeConverter.new
4✔
123
          proposal.volume_templates.map { |v| converter.to_dbus(v) }
10✔
124
        end
125

126
        # Path of the D-Bus object containing the calculated proposal
127
        #
128
        # @return [::DBus::ObjectPath] Proposal object path or root path if no exported proposal yet
129
        def result
1✔
130
          dbus_proposal&.path || ::DBus::ObjectPath.new("/")
2✔
131
        end
132

133
        # Calculates a new proposal
134
        #
135
        # @param dbus_settings [Hash]
136
        # @return [Integer] 0 success; 1 error
137
        def calculate_proposal(dbus_settings)
1✔
138
          logger.info("Calculating storage proposal from D-Bus settings: #{dbus_settings}")
4✔
139

140
          converter = ProposalSettingsConverter.new
4✔
141
          success = proposal.calculate(converter.to_dinstaller(dbus_settings))
4✔
142

143
          success ? 0 : 1
4✔
144
        end
145

146
        dbus_interface PROPOSAL_CALCULATOR_INTERFACE do
1✔
147
          dbus_reader :available_devices, "a(ssa{sv})"
1✔
148

149
          dbus_reader :volume_templates, "aa{sv}"
1✔
150

151
          dbus_reader :result, "o"
1✔
152

153
          # result: 0 success; 1 error
154
          dbus_method :Calculate, "in settings:a{sv}, out result:u" do |settings|
1✔
155
            busy_while { calculate_proposal(settings) }
×
156
          end
157
        end
158

159
        ISCSI_INITIATOR_INTERFACE = "org.opensuse.DInstaller.Storage1.ISCSI.Initiator"
1✔
160
        private_constant :ISCSI_INITIATOR_INTERFACE
1✔
161

162
        # Gets the iSCSI initiator name
163
        #
164
        # @return [String]
165
        def initiator_name
1✔
166
          backend.iscsi.initiator.name || ""
×
167
        end
168

169
        # Sets the iSCSI initiator name
170
        #
171
        # @param value [String]
172
        def initiator_name=(value)
1✔
173
          backend.iscsi.initiator.name = value
×
174
        end
175

176
        # Whether the initiator name was set via iBFT
177
        #
178
        # @return [Boolean]
179
        def ibft
1✔
180
          backend.iscsi.initiator.ibft_name?
×
181
        end
182

183
        # Performs an iSCSI discovery
184
        #
185
        # @param address [String] IP address of the iSCSI server
186
        # @param port [Integer] Port of the iSCSI server
187
        # @param options [Hash<String, String>] Options from a D-Bus call:
188
        #   @option Username [String] Username for authentication by target
189
        #   @option Password [String] Password for authentication by target
190
        #   @option ReverseUsername [String] Username for authentication by initiator
191
        #   @option ReversePassword [String] Username for authentication by inititator
192
        #
193
        # @return [Integer] 0 on success, 1 on failure
194
        def iscsi_discover(address, port, options = {})
1✔
195
          success = backend.iscsi.discover_send_targets(address, port, iscsi_auth(options))
5✔
196
          success ? 0 : 1
5✔
197
        end
198

199
        # Deletes an iSCSI node from the database
200
        #
201
        # @param path [::DBus::ObjectPath]
202
        # @return [Integer] 0 on success, 1 on failure if the given node is not exported, 2 on
203
        #   failure because any other reason.
204
        def iscsi_delete(path)
1✔
205
          dbus_node = iscsi_nodes_tree.find(path)
5✔
206
          if !dbus_node
5✔
207
            logger.info("iSCSI delete error: iSCSI node #{path} is not exported")
2✔
208
            return 1
2✔
209
          end
210

211
          success = backend.iscsi.delete(dbus_node.iscsi_node)
3✔
212
          return 0 if success
3✔
213

214
          logger.info("iSCSI delete error: fail to delete iSCSI node #{path}")
2✔
215
          2 # Error code
2✔
216
        end
217

218
        dbus_interface ISCSI_INITIATOR_INTERFACE do
1✔
219
          dbus_accessor :initiator_name, "s"
1✔
220

221
          dbus_reader :ibft, "b", dbus_name: "IBFT"
1✔
222

223
          dbus_method :Discover,
1✔
224
            "in address:s, in port:u, in options:a{sv}, out result:u" do |address, port, options|
225
            busy_while { iscsi_discover(address, port, options) }
×
226
          end
227

228
          dbus_method(:Delete, "in node:o, out result:u") { |n| iscsi_delete(n) }
1✔
229
        end
230

231
      private
1✔
232

233
        # @return [DInstaller::Storage::Manager]
234
        attr_reader :backend
1✔
235

236
        # @return [DBus::Storage::Proposal, nil]
237
        attr_reader :dbus_proposal
1✔
238

239
        # @return [DInstaller::Storage::Proposal]
240
        def proposal
1✔
241
          backend.proposal
46✔
242
        end
243

244
        def register_proposal_callbacks
1✔
245
          proposal.on_calculate do
34✔
246
            export_proposal
×
247
            proposal_properties_changed
×
248
            update_validation
×
249
          end
250
        end
251

252
        def register_iscsi_callbacks
1✔
253
          backend.iscsi.on_activate do
34✔
254
            properties = interfaces_and_properties[ISCSI_INITIATOR_INTERFACE]
×
255
            dbus_properties_changed(ISCSI_INITIATOR_INTERFACE, properties, [])
×
256
          end
257

258
          backend.iscsi.on_probe do
34✔
259
            refresh_iscsi_nodes
×
260
          end
261

262
          backend.iscsi.on_sessions_change do
34✔
263
            deprecate_system
×
264
          end
265
        end
266

267
        def register_software_callbacks
1✔
268
          backend.software.on_product_selected do |_product|
34✔
269
            backend.proposal.reset
×
270
          end
271
        end
272

273
        def register_and_extend_dasd_callbacks
1✔
274
          register_dasd_callbacks
10✔
275

276
          dasd_backend.on_refresh do |_|
10✔
NEW
277
            deprecate_system
×
278
          end
279
        end
280

281
        def deprecate_system
1✔
282
          backend.deprecated_system = true
×
283
          storage_properties_changed
×
284
          update_validation
×
285
        end
286

287
        def storage_properties_changed
1✔
288
          properties = interfaces_and_properties[STORAGE_INTERFACE]
×
289
          dbus_properties_changed(STORAGE_INTERFACE, properties, [])
×
290
        end
291

292
        def proposal_properties_changed
1✔
293
          properties = interfaces_and_properties[PROPOSAL_CALCULATOR_INTERFACE]
×
294
          dbus_properties_changed(PROPOSAL_CALCULATOR_INTERFACE, properties, [])
×
295
        end
296

297
        def export_proposal
1✔
298
          @service.unexport(dbus_proposal) if dbus_proposal
×
299
          @dbus_proposal = DBus::Storage::Proposal.new(proposal, logger)
×
300
          @service.export(@dbus_proposal)
×
301
        end
302

303
        def refresh_iscsi_nodes
1✔
304
          nodes = backend.iscsi.nodes
×
305
          iscsi_nodes_tree.update(nodes)
×
306
        end
307

308
        def iscsi_nodes_tree
1✔
309
          @iscsi_nodes_tree ||= ISCSINodesTree.new(@service, backend.iscsi, logger: logger)
5✔
310
        end
311
      end
312
    end
313
  end
314
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc