Class: Y2Network::Widgets::BondPort

Inherits:
CWM::CustomWidget
  • Object
show all
Includes:
UI::TextHelpers, PortItems
Defined in:
src/lib/y2network/widgets/bond_port.rb

Instance Method Summary collapse

Methods included from PortItems

#physical_port_id, #physical_port_id?, #port_items_from

Constructor Details

#initialize(settings) ⇒ BondPort

Returns a new instance of BondPort.



36
37
38
39
40
# File 'src/lib/y2network/widgets/bond_port.rb', line 36

def initialize(settings)
  super()
  textdomain "network"
  @settings = settings
end

Instance Method Details

#contentsObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'src/lib/y2network/widgets/bond_port.rb', line 42

def contents
  Frame(
    _("Bond Ports and Order"),
    VBox(
      MultiSelectionBox(Id(:bond_ports_items), Opt(:notify), "", []),
      HBox(
        # TRANSLATORS: this means "move this line upwards"
        PushButton(Id(:bond_ports_up), Opt(:disabled), _("Up")),
        # TRANSLATORS: this means "move this line downwards"
        PushButton(Id(:bond_ports_down), Opt(:disabled), _("Down"))
      )
    )
  )
end

#continue_with_duplicates?(physical_ports) ⇒ Boolean

Given a map of duplicated port ids with device names, aks the user if he would like to continue or not.

mapping to an array of device names

Parameters:

  • physical_ports (Hash{String => Array<String>})

    hash of duplicated physical port ids

Returns:

  • (Boolean)

    true if continue with duplicates, otherwise false



231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'src/lib/y2network/widgets/bond_port.rb', line 231

def continue_with_duplicates?(physical_ports)
  message = physical_ports.map do |p_port, b_ports|
    wrap_text("PhysicalPortID (#{p_port}): #{b_ports.join(", ")}")
  end.join("\n")

  Yast::Popup.YesNoHeadline(
    Yast::Label.WarningMsg,
    # Translators: Warn the user about not desired effect
    _("The interfaces selected share the same physical port and bonding " \
      "them \nmay not have the desired effect of redundancy.\n\n%s\n\n" \
      "Really continue?\n") % message
  )
end

#enable_position_buttonsObject



163
164
165
166
167
168
169
170
171
# File 'src/lib/y2network/widgets/bond_port.rb', line 163

def enable_position_buttons
  if value_index
    Yast::UI.ChangeWidget(:bond_ports_up, :Enabled, value_index > 0)
    Yast::UI.ChangeWidget(:bond_ports_down, :Enabled, value_index < ui_items.size - 1)
  else
    Yast::UI.ChangeWidget(:bond_ports_up, :Enabled, false)
    Yast::UI.ChangeWidget(:bond_ports_down, :Enabled, false)
  end
end

#handle(event) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'src/lib/y2network/widgets/bond_port.rb', line 57

def handle(event)
  if event["EventReason"] == "SelectionChanged"
    enable_position_buttons
  elsif event["EventReason"] == "Activated" && event["WidgetClass"] == :PushButton
    items = ui_items || []
    current = value.to_s
    index = value_index
    case event["ID"]
    when :bond_ports_up
      items[index], items[index - 1] = items[index - 1], items[index]
    when :bond_ports_down
      items[index], items[index + 1] = items[index + 1], items[index]
    else
      log.warn("unknown action #{event["ID"]}")
      return nil
    end
    Yast::UI.ChangeWidget(:bond_ports_items, :Items, items)
    Yast::UI.ChangeWidget(:bond_ports_items, :CurrentItem, current)
    enable_position_buttons
  else
    log.debug("event:#{event}")
  end

  nil
end

#helpObject



83
84
85
86
87
88
89
90
# File 'src/lib/y2network/widgets/bond_port.rb', line 83

def help
  # TODO: write it
  _(
    "<p>Select a devices for including into the bond.\n" \
    "Only devices with the device activation set to <b>Never</b> " \
    "and with <b>No Address Setup</b> are available.</p>"
  )
end

#initObject

Default function to init the value of port devices box for bonding.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'src/lib/y2network/widgets/bond_port.rb', line 93

def init
  ports = @settings.ports
  # TODO: use def items, but problem now is that port_items returns term and not array
  items = port_items_from(
    @settings.bondable_interfaces.map(&:name),
    ports,
    Yast::Lan.yast_config # ideally get it from builder?
  )

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

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

  Yast::UI.ChangeWidget(:bond_ports_items, :Items, items)

  Yast::UI.ChangeWidget(
    :bond_ports_items,
    :SelectedItems,
    ports
  )

  enable_position_buttons

  nil
end

#justify_dev_name(name) ⇒ String

A helper for sort devices by name. It justify at right with 0's numeric parts of given device name until 5 digits.

TODO: should not be in CWM ==== Examples

justify_dev_name("eth0") # => "eth00000" justify_dev_name("eth111") # => "eth00111" justify_dev_name("enp0s25") # => "enp00000s00025"

Parameters:

  • name (String)

    device name

Returns:

  • (String)

    given name with numbers justified at right



185
186
187
188
189
190
191
192
193
194
# File 'src/lib/y2network/widgets/bond_port.rb', line 185

def justify_dev_name(name)
  splited_dev_name = name.scan(/\p{Alpha}+|\p{Digit}+/)
  splited_dev_name.map! do |d|
    if d =~ /\p{Digit}+/
      d.rjust(5, "0")
    else
      d
    end
  end.join
end

#repeated_physical_port_ids(b_ports) ⇒ Hash{String => Array<String>}

Given a list of device names returns a hash of physical port ids mapping device names if at least two devices shared the same physical port id TODO: backend method

NOTE: term port is slightly overloaded here. Name of method refers to physical ports of a NIC card (one card can have multiple "plugs" - ports). On the other hand param name refers to pure virtual bonding ports (network devices provided by the system which are virtualy tighted together into a virtual bond device)

Parameters:

  • b_ports (Array<String>)

    bond ports = devices included in the bond

Returns:

  • (Hash{String => Array<String>})

    maps physical ports to non-singleton arrays of bond ports



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'src/lib/y2network/widgets/bond_port.rb', line 209

def repeated_physical_port_ids(b_ports)
  physical_port_ids = {}

  b_ports.each do |b_port|
    next unless physical_port_id?(b_port)

    p_port = physical_port_id(b_port)
    ps = physical_port_ids[p_port] ||= []
    ps << b_port
  end

  physical_port_ids.select! { |_k, v| v.size > 1 }

  physical_port_ids
end

#selected_itemsObject



151
152
153
# File 'src/lib/y2network/widgets/bond_port.rb', line 151

def selected_items
  Yast::UI.QueryWidget(:bond_ports_items, :SelectedItems) || []
end

#storeObject

Default function to store the value of port devices box.



121
122
123
# File 'src/lib/y2network/widgets/bond_port.rb', line 121

def store
  @settings.ports = selected_items
end

#ui_itemsObject



155
156
157
# File 'src/lib/y2network/widgets/bond_port.rb', line 155

def ui_items
  Yast::UI.QueryWidget(:bond_ports_items, :Items) || []
end

#validateObject

Validates created bonding. Currently just prevent the user to create a bond with more than one interface sharing the same physical port id

Returns:

  • true if valid or user decision if not



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'src/lib/y2network/widgets/bond_port.rb', line 129

def validate
  physical_ports = repeated_physical_port_ids(selected_items)

  return false if !physical_ports.empty? && !continue_with_duplicates?(physical_ports)

  if @settings.require_adaptation?(selected_items || [])
    Yast::Popup.ContinueCancel(
      _(
        "At least one selected device is already configured.\n" \
        "Adapt the configuration for bonding?\n"
      )
    )
  else
    true
  end
end

#valueObject



146
147
148
149
# File 'src/lib/y2network/widgets/bond_port.rb', line 146

def value
  # TODO: it is multiselection, so does it make sense?
  Yast::UI.QueryWidget(:bond_ports_items, :CurrentItem)
end

#value_indexObject



159
160
161
# File 'src/lib/y2network/widgets/bond_port.rb', line 159

def value_index
  ui_items.index { |i| i[0] == Id(value) }
end