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

yast / yast-network / 13673746440

05 Mar 2025 10:22AM UTC coverage: 79.763% (-0.8%) from 80.591%
13673746440

Pull #1373

github

teclator
Merge branch 'SLE-15-SP6' into merge_SLE-15-SP6
Pull Request #1373: Added dialog for changing the bond ports naming schema to BusID (bsc#1233653) - SLE-15-SP7

11 of 138 new or added lines in 5 files covered. (7.97%)

2 existing lines in 2 files now uncovered.

9294 of 11652 relevant lines covered (79.76%)

19.82 hits per line

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

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

20
require "ui/text_helpers"
1✔
21
require "yast"
1✔
22
require "cwm/custom_widget"
1✔
23
require "y2network/widgets/port_items"
1✔
24

25
Yast.import "Label"
1✔
26
Yast.import "Lan"
1✔
27
Yast.import "Popup"
1✔
28
Yast.import "UI"
1✔
29

30
module Y2Network
1✔
31
  module Widgets
1✔
32
    class BondPort < CWM::CustomWidget
1✔
33
      include PortItems
1✔
34
      include ::UI::TextHelpers
1✔
35

36
      def initialize(settings)
1✔
37
        textdomain "network"
9✔
38
        @settings = settings
9✔
39
      end
40

41
      def contents
1✔
42
        Frame(
1✔
43
          _("Bond Ports and Order"),
44
          VBox(
45
            MultiSelectionBox(Id(:bond_ports_items), Opt(:notify), "", []),
46
            HBox(
47
              # TRANSLATORS: this means "move this line upwards"
48
              PushButton(Id(:bond_ports_up), Opt(:disabled), _("Up")),
49
              # TRANSLATORS: this means "move this line downwards"
50
              PushButton(Id(:bond_ports_down), Opt(:disabled), _("Down"))
51
            )
52
          )
53
        )
54
      end
55

56
      def handle(event)
1✔
57
        if event["EventReason"] == "SelectionChanged"
1✔
58
          enable_position_buttons
×
59
        elsif event["EventReason"] == "Activated" && event["WidgetClass"] == :PushButton
1✔
60
          items = ui_items || []
×
61
          current = value.to_s
×
62
          index = value_index
×
63
          case event["ID"]
×
64
          when :bond_ports_up
65
            items[index], items[index - 1] = items[index - 1], items[index]
×
66
          when :bond_ports_down
67
            items[index], items[index + 1] = items[index + 1], items[index]
×
68
          else
69
            log.warn("unknown action #{event["ID"]}")
×
70
            return nil
×
71
          end
72
          Yast::UI.ChangeWidget(:bond_ports_items, :Items, items)
×
73
          Yast::UI.ChangeWidget(:bond_ports_items, :CurrentItem, current)
×
74
          enable_position_buttons
×
75
        else
76
          log.debug("event:#{event}")
1✔
77
        end
78

79
        nil
80
      end
81

82
      def help
1✔
83
        # TODO: write it
84
        _(
1✔
85
          "<p>Select a devices for including into the bond.\n" \
86
            "Only devices with the device activation set to <b>Never</b> " \
87
            "and with <b>No Address Setup</b> are available.</p>"
88
        )
89
      end
90

91
      # Default function to init the value of port devices box for bonding.
92
      def init
1✔
93
        ports = @settings.ports
×
94
        # TODO: use def items, but problem now is that port_items returns term and not array
95
        items = port_items_from(
×
96
          @settings.bondable_interfaces.map(&:name),
97
          ports,
98
          Yast::Lan.yast_config # ideally get it from builder?
99
        )
100

101
        # reorder the items
102
        l1, l2 = items.partition { |t| ports.include? t[0][0] }
×
103

104
        items = l1 + l2.sort_by { |t| justify_dev_name(t[0][0]) }
×
105

106
        Yast::UI.ChangeWidget(:bond_ports_items, :Items, items)
×
107

108
        Yast::UI.ChangeWidget(
×
109
          :bond_ports_items,
110
          :SelectedItems,
111
          ports
112
        )
113

114
        enable_position_buttons
×
115

116
        nil
117
      end
118

119
      # Default function to store the value of port devices box.
120
      def store
1✔
121
        @settings.ports = selected_items
×
122
      end
123

124
      # Validates created bonding. Currently just prevent the user to create a
125
      # bond with more than one interface sharing the same physical port id
126
      #
127
      # @return true if valid or user decision if not
128
      def validate
1✔
129
        physical_ports = repeated_physical_port_ids(selected_items)
3✔
130

131
        if !physical_ports.empty?
3✔
132
          return false unless continue_with_duplicates?(physical_ports)
1✔
133
        end
134

135
        if @settings.require_adaptation?(selected_items || [])
2✔
136
          return Yast::Popup.ContinueCancel(
137
            _(
138
              "At least one selected device is already configured.\n" \
139
                "Adapt the configuration for bonding?\n"
140
            )
UNCOV
141
          )
×
142
        elsif @settings.invalid_naming_schema?(selected_items || [])
2✔
143
          return Yast::Popup.ContinueCancel(
144
            _(
145
              "At least one selected device is using a MAC address for renaming the device.\n" \
146
                "Would you like to change the renaming mechanism to BusID?\n"
147
            )
NEW
148
          )
×
149
        end
150

151
        true
2✔
152
      end
153

154
      def value
1✔
155
        # TODO: it is multiselection, so does it make sense?
156
        Yast::UI.QueryWidget(:bond_ports_items, :CurrentItem)
×
157
      end
158

159
      def selected_items
1✔
160
        Yast::UI.QueryWidget(:bond_ports_items, :SelectedItems) || []
3✔
161
      end
162

163
      def ui_items
1✔
164
        Yast::UI.QueryWidget(:bond_ports_items, :Items) || []
×
165
      end
166

167
      def value_index
1✔
168
        ui_items.index { |i| i[0] == Id(value) }
×
169
      end
170

171
      def enable_position_buttons
1✔
172
        if value_index
×
173
          Yast::UI.ChangeWidget(:bond_ports_up, :Enabled, value_index > 0)
×
174
          Yast::UI.ChangeWidget(:bond_ports_down, :Enabled, value_index < ui_items.size - 1)
×
175
        else
176
          Yast::UI.ChangeWidget(:bond_ports_up, :Enabled, false)
×
177
          Yast::UI.ChangeWidget(:bond_ports_down, :Enabled, false)
×
178
        end
179
      end
180

181
      # A helper for sort devices by name. It justify at right with 0's numeric parts of given
182
      # device name until 5 digits.
183
      #
184
      # TODO: should not be in CWM
185
      # ==== Examples
186
      #
187
      #   justify_dev_name("eth0") # => "eth00000"
188
      #   justify_dev_name("eth111") # => "eth00111"
189
      #   justify_dev_name("enp0s25") # => "enp00000s00025"
190
      #
191
      # @param name [String] device name
192
      # @return [String] given name with numbers justified at right
193
      def justify_dev_name(name)
1✔
194
        splited_dev_name = name.scan(/\p{Alpha}+|\p{Digit}+/)
×
195
        splited_dev_name.map! do |d|
196
          if d =~ /\p{Digit}+/
×
197
            d.rjust(5, "0")
×
198
          else
199
            d
×
200
          end
201
        end.join
×
202
      end
203

204
      # Given a list of device names returns a hash of physical port ids mapping
205
      # device names if at least two devices shared the same physical port id
206
      # TODO: backend method
207
      #
208
      # NOTE: term port is slightly overloaded here. Name of method refers to
209
      # physical ports of a NIC card (one card can have multiple "plugs" - ports).
210
      # On the other hand param name refers to pure virtual bonding ports (network
211
      # devices provided by the system which are virtualy tighted together into a
212
      # virtual bond device)
213
      #
214
      # @param b_ports [Array<String>] bond ports = devices included in the bond
215
      # @return [Hash{String => Array<String>}]
216
      #   maps physical ports to non-singleton arrays of bond ports
217
      def repeated_physical_port_ids(b_ports)
1✔
218
        physical_port_ids = {}
3✔
219

220
        b_ports.each do |b_port|
3✔
221
          next unless physical_port_id?(b_port)
17✔
222

223
          p_port = physical_port_id(b_port)
15✔
224
          ps = physical_port_ids[p_port] ||= []
15✔
225
          ps << b_port
15✔
226
        end
227

228
        physical_port_ids.select! { |_k, v| v.size > 1 }
6✔
229

230
        physical_port_ids
3✔
231
      end
232

233
      # Given a map of duplicated port ids with device names, aks the user if he
234
      # would like to continue or not.
235
      #
236
      # @param physical_ports [Hash{String => Array<String>}] hash of duplicated physical port ids
237
      # mapping to an array of device names
238
      # @return [Boolean] true if continue with duplicates, otherwise false
239
      def continue_with_duplicates?(physical_ports)
1✔
240
        message = physical_ports.map do |p_port, b_ports|
1✔
241
          wrap_text("PhysicalPortID (#{p_port}): #{b_ports.join(", ")}")
1✔
242
        end.join("\n")
243

244
        Yast::Popup.YesNoHeadline(
1✔
245
          Yast::Label.WarningMsg,
246
          # Translators: Warn the user about not desired effect
247
          _("The interfaces selected share the same physical port and bonding " \
248
            "them \nmay not have the desired effect of redundancy.\n\n%s\n\n" \
249
            "Really continue?\n") % message
250
        )
251
      end
252
    end
253
  end
254
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