Class: Yast::BootCommonClass

Inherits:
Module
  • Object
show all
Defined in:
src/modules/BootCommon.rb

Constant Summary

SUPPORTED_BOOTLOADERS =
[
  "none", # allow user to manage bootloader itself
  "grub2",
  "grub2-efi"
]

Instance Method Summary (collapse)

Instance Method Details

- (Object) Export

Export bootloader settings to a map

Returns:

  • bootloader settings



158
159
160
161
162
163
164
165
166
167
168
# File 'src/modules/BootCommon.rb', line 158

def Export
  exp = {
    "global"     => remapGlobals(@globals),
    "device_map" => BootStorage.remapDeviceMap(BootStorage.device_mapping)
  }
  if @loader_type != "grub2"
    Ops.set(exp, "activate", @activate)
  end

  deep_copy(exp)
end

- (Object) getBootloaders

List bootloaders available for configured architecture

Returns:

  • a list of bootloaders



489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
# File 'src/modules/BootCommon.rb', line 489

def getBootloaders
  if Mode.config
    # default means bootloader use what it think is the best
    return SUPPORTED_BOOTLOADERS + ["default"]
  end
  ret = [getLoaderType(false)]
  if Arch.i386 || Arch.x86_64 || Arch.s390 || Arch.ppc
    ret << "grub2"
  end
  if Arch.x86_64
    ret << "grub2-efi"
  end
  ret = Builtins.add(ret, "none")
  # avoid double entry for selected one
  ret.uniq
end

- (String) getLoaderType(recheck)

Get currently used bootloader, detect if not set yet

Parameters:

  • recheck (Boolean)

    boolean force checking bootloader

Returns:

  • (String)

    botloader type



380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'src/modules/BootCommon.rb', line 380

def getLoaderType(recheck)
  return @loader_type if !recheck && @loader_type
  # read bootloader to use from disk
  if Mode.update || Mode.normal || Mode.repair
    @loader_type = SCR.Read(path(".sysconfig.bootloader.LOADER_TYPE"))
    if @loader_type && !@loader_type.empty?
      @loader_type = "grub2" if @loader_type == "s390"
      Builtins.y2milestone(
        "Sysconfig bootloader is %1, using",
        @loader_type
      )
      @loader_type = SupportedLoader(@loader_type)
      Builtins.y2milestone(
        "Sysconfig bootloader is %1, using",
        @loader_type
      )
      setCurrentLoaderAttribs(@loader_type)
      return @loader_type
    end
  end
  # detect bootloader
  @loader_type = SCR.Read(path(".probe.boot_arch"))
  # s390,ppc and also old grub now uses grub2 (fate #315753)
  @loader_type = "grub2" if ["s390", "ppc", "grub"].include? @loader_type

  Builtins.y2milestone("Bootloader detection returned %1", @loader_type)
  if (Arch.i386 || Arch.x86_64) && Linuxrc.InstallInf("EFI") == "1"
    # use grub2-efi as default bootloader for x86_64/i386 EFI
    @loader_type = "grub2-efi"
  end

  @loader_type = SupportedLoader(@loader_type)
  Builtins.y2milestone("Detected bootloader %1", @loader_type)
  setCurrentLoaderAttribs(@loader_type)
  @loader_type
end

- (Object) getSystemSecureBootStatus(recheck)



462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
# File 'src/modules/BootCommon.rb', line 462

def getSystemSecureBootStatus(recheck)
  return @secure_boot if !recheck && !@secure_boot.nil?

  if Mode.update || Mode.normal || Mode.repair
    sb = SCR.Read(path(".sysconfig.bootloader.SECURE_BOOT"))

    if sb && !sb.empty?
      @secure_boot = sb == "yes"
      return @secure_boot
    end
  end

  # propose secure boot always to true (bnc#872054), otherwise respect user choice
  @secure_boot = true if @secure_boot.nil?
  @secure_boot
end

- (Boolean) Import(settings)

Import settings from a map

Parameters:

  • settings (Hash)

    map of bootloader settings

Returns:

  • (Boolean)

    true on success



173
174
175
176
177
178
179
180
181
182
# File 'src/modules/BootCommon.rb', line 173

def Import(settings)
  settings = deep_copy(settings)
  @globals = Ops.get_map(settings, "global", {})

  if @loader_type != "grub2"
    @activate = Ops.get_boolean(settings, "activate", false)
  end
  BootStorage.device_mapping = Ops.get_map(settings, "device_map", {})
  true
end

- (Object) main



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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
82
83
84
85
86
87
88
89
90
91
92
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'src/modules/BootCommon.rb', line 33

def main
  Yast.import "Pkg"
  Yast.import "UI"

  textdomain "bootloader"

  Yast.import "Arch"
  Yast.import "HTML"
  Yast.import "Mode"
  Yast.import "PackageSystem"
  Yast.import "Storage"
  Yast.import "PackagesProposal"
  Yast.import "BootStorage"

  Yast.import "Linuxrc"


  # General bootloader settings

  # map of global options and values
  @globals = {}

  # list of section
  @sections = []

  # Saved change time from target map - proposal

  @cached_settings_base_data_change_time = nil


  # device to save loader stage 1 to
  # NOTE: this variable is being phased out. The boot_* keys in the globals map
  # are now used to remember the selected boot location. Thus, we now have a
  # list of selected loader devices. It can be generated from the information in
  # the boot_* keys and the global variables (Boot|Root|Extended)PartitionDevice
  # and mbrDisk by calling GetBootloaderDevices().
  #FIXME: need remove to read only loader location from perl-Bootloader
  @loader_device = nil

  # proposal helping variables

  # The kind of bootloader location that the user selected last time he went to
  # the dialog. Used as a hint next time a proposal is requested, so the
  # proposal can try to satisfy the user's previous preference.
  # NOTE: this variable is being phased out. The boot_* keys in the globals map
  # will be used to remember the last selected location.
  # Currently, valid values are: mbr, boot, root, mbr_md, none
  #FIXME: need remove to read only loader location from perl-Bootloader
  @selected_location = nil



  # These global variables and functions are needed in included files

  # Parameters of currently used bootloader
  @current_bootloader_attribs = {}

  # Parameters of all bootloaders
  @bootloader_attribs = {}

  # device holding MBR for bootloader
  @mbrDisk = ""

  # Backup original MBR before installing bootloader
  @backup_mbr = false

  # Activate bootloader partition during installation?
  @activate = false

  # action to do with pbmr flag on boot disk
  # values are :add, :remove or nil, means do nothing
  @pmbr_action = nil

  # were settings changed (== true)
  @changed = false

  # common variables

  # type of bootloader to configure/being configured
  # shall be one of "grub2", "grub2-efi"
  @loader_type = nil
  @secure_boot = nil

  # saving mode setting functions

  # map of save mode settings
  @write_settings = {}

  @additional_failsafe_params = ""


  # other variables

  # bootloader installation variables

  # Was the activate flag changed by user?
  @activate_changed = false
  # Save everything, not only changed settings
  @save_all = false

  # state variables

  # was the propose function called (== true)
  @was_proposed = false
  # Were module settings read (== true)
  @was_read = false
  # Was bootloader location changed? (== true)
  @location_changed = false

  # FATE#305008: Failover boot configurations for md arrays with redundancy
  # if true enable redundancy for md array
  @enable_md_array_redundancy = nil

  # help message and dscription definitions
  Yast.include self, "bootloader/routines/popups.rb"
  Yast.include self, "bootloader/routines/misc.rb"
  # FIXME: there are other archs than i386, this is not 'commmon'
  Yast.include self, "bootloader/routines/lilolike.rb"
  Yast.include self, "bootloader/routines/lib_iface.rb"
end

- (Object) Md2Partitions(md_device)

FIXME just backward compatible interface, call directly BootStorage



523
524
525
# File 'src/modules/BootCommon.rb', line 523

def Md2Partitions(md_device)
  BootStorage.Md2Partitions(md_device)
end

- (Object) Propose

Propose bootloader settings



229
230
231
232
233
# File 'src/modules/BootCommon.rb', line 229

def Propose
  Builtins.y2error("No generic propose function available")

  nil
end

- (Boolean) Read(reread, avoid_reading_device_map)

Read settings from disk internal data

Parameters:

  • reread (Boolean)

    boolean true to force reread settings from system

  • avoid_reading_device_map (Boolean)

    do not read new device map from file, use

Returns:

  • (Boolean)

    true on success



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'src/modules/BootCommon.rb', line 189

def Read(reread, avoid_reading_device_map)
  bl = getLoaderType(false)
  return true if bl == "none"
  InitializeLibrary(reread, bl)
  ReadFiles(avoid_reading_device_map) if reread
  @sections = GetSections()
  @globals = GetGlobal()
  BootStorage.device_mapping = GetDeviceMap()

  # convert device names in device map to the kernel device names
  BootStorage.device_mapping = Builtins.mapmap(BootStorage.device_mapping) do |k, v|
    { ::Bootloader::DeviceMapping.to_mountby_device(k) => v }
  end

  # convert custom boot device names in globals to the kernel device names
  # also, for legacy bootloaders like LILO that still pass device names,
  # convert the stage1_dev
  @globals = Builtins.mapmap(@globals) do |k, v|
    if k == "stage1_dev" || Builtins.regexpmatch(k, "^boot_.*custom$")
      next { k => ::Bootloader::DeviceMapping.to_kernel_device(v) }
    else
      next { k => v }
    end
  end

  true
end

- (Object) Reset

Reset bootloader settings



218
219
220
221
222
223
224
225
226
# File 'src/modules/BootCommon.rb', line 218

def Reset
  @sections = []
  @globals = {}
  @activate = false
  @activate_changed = false
  @was_proposed = false

  nil
end

- (Boolean) Save(clean, init, flush)

Save all bootloader configuration files to the cache of the PlugLib PlugLib must be initialized properly !!!

Parameters:

  • clean (Boolean)

    boolean true if settings should be cleaned up (checking their correctness, supposing all files are on the disk)

  • init (Boolean)

    boolean true to init the library

  • flush (Boolean)

    boolean true to flush settings to the disk

Returns:

  • (Boolean)

    true if success



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'src/modules/BootCommon.rb', line 242

def Save(clean, init, flush)
  ret = true

  bl = getLoaderType(false)

  InitializeLibrary(init, bl)

  return true if bl == "none"

  # bnc#589433 -  Install grub into root (/) partition gives error
  @globals.delete("boot_custom") if @globals["boot_custom"] == ""

  # FIXME: give mountby information to perl-Bootloader (or define some
  # better interface), so that perl-Bootloader can use mountby device names
  # for these devices instead. Tracked in bug #248162.

  # convert custom boot device names in globals to the device names
  # indicated by "mountby"
  # also, for legacy bootloaders like LILO that still pass device names,
  # convert the stage1_dev
  my_globals = Builtins.mapmap(@globals) do |k, v|
    if k == "stage1_dev" || Builtins.regexpmatch(k, "^boot_.*custom$")
      next { k => ::Bootloader::DeviceMapping.to_mountby_device(v) }
    else
      next { k => v }
    end
  end

  # convert device names in device map to the device names indicated by
  # "mountby"

  Builtins.y2milestone(
    "device map before mapping %1",
    BootStorage.device_mapping
  )
  my_device_mapping = Builtins.mapmap(BootStorage.device_mapping) do |k, v|
    { ::Bootloader::DeviceMapping.to_mountby_device(k) => v }
  end
  Builtins.y2milestone("device map after mapping %1", my_device_mapping)

  if VerifyMDArray()
    if !@enable_md_array_redundancy
      my_globals.delete("boot_md_mbr")
    elsif !my_globals["boot_md_mbr"]
      my_globals["boot_md_mbr"] = BootStorage.addMDSettingsToGlobals
    end
  else
    my_globals.delete("boot_md_mbr")
  end

  Builtins.y2milestone("SetSecureBoot %1", @secure_boot)
  ret &&= SetSecureBoot(@secure_boot)
  ret &&= DefineMultipath(BootStorage.multipath_mapping)
  ret &&= SetDeviceMap(my_device_mapping)
  ret &&= SetSections(@sections)
  ret &&= SetGlobal(my_globals)
  ret &&= CommitSettings() if flush

  # write settings to /etc/sysconfig/bootloader
  WriteToSysconf(false)

  ret
end

- (Object) setCurrentLoaderAttribs(loader_type)

Set attributes of specified bootloader to variable containing attributes of currently used bootloader, call its initializer

Parameters:

  • loader_type (String)

    string loader type to initialize



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'src/modules/BootCommon.rb', line 343

def setCurrentLoaderAttribs(loader_type)
  Builtins.y2milestone("Setting attributes for bootloader %1", loader_type)
  if !loader_type
    Builtins.y2error("Setting loader type to nil, this is wrong")
    return
  end

  # FIXME: this should be blInitializer in switcher.ycp for code cleanness
  # and understandability
  boot_initializer = Ops.get(@bootloader_attribs, [loader_type, "initializer"])
  if boot_initializer
    Builtins.y2milestone("Running bootloader initializer")
    boot_initializer.call
    Builtins.y2milestone("Initializer finished")
  else
    Builtins.y2error("No initializer found for >>%1<<", loader_type)
    @current_bootloader_attribs = {}
  end

  @current_bootloader_attribs = Builtins.union(
    @current_bootloader_attribs,
    Builtins.eval(Ops.get(@bootloader_attribs, loader_type, {}))
  )

  nil
end

- (Object) setLoaderType(bootloader)

set type of bootloader

Parameters:

  • bootloader (String)

    string type of bootloader



420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'src/modules/BootCommon.rb', line 420

def setLoaderType(bootloader)
  if !bootloader
    Builtins.y2milestone("Resetting the loader type")
    @loader_type = nil
  end
  Builtins.y2milestone("Setting bootloader to >>%1<<", bootloader)
  raise "Unsupported bootloader '#{bootloader}'" unless SUPPORTED_BOOTLOADERS.include?(bootloader)

  bootloader_packages = Ops.get_list(
    @bootloader_attribs,
    [bootloader, "required_packages"],
    []
  )

  # added kexec-tools fate# 303395
  # if kexec option is equal 0 or running live installation
  # doesn't install kexec-tools
  if !Mode.live_installation && Linuxrc.InstallInf("kexec_reboot") != "0"
    bootloader_packages = Builtins.add(bootloader_packages, "kexec-tools")
  end

  # we need perl-Bootloader-YAML API to communicate with pbl
  bootloader_packages << "perl-Bootloader-YAML"

  Builtins.y2milestone("Bootloader packages: %1", bootloader_packages)

  # don't configure package manager during autoinstallation preparing
  if Mode.normal
    PackageSystem.InstallAll(bootloader_packages)
  elsif Stage.initial
    bootloader_packages.each do |p|
      Builtins.y2milestone("Select bootloader package: %1", p)
      PackagesProposal.AddResolvables("yast2-bootloader", :package, [p])
    end
  end
  @loader_type = bootloader
  setCurrentLoaderAttribs(@loader_type)
  Builtins.y2milestone("Loader type set")

  nil
end

- (Object) setSystemSecureBootStatus(enable)



479
480
481
482
483
484
485
# File 'src/modules/BootCommon.rb', line 479

def setSystemSecureBootStatus(enable)
  Builtins.y2milestone("Set secure boot: %2 => %1", enable, @secure_boot)
  @location_changed = true if @secure_boot != enable # secure boot require reinstall of stage 1
  @secure_boot = enable

  nil
end

- (Object) Summary

Display bootloader summary

Returns:

  • a list of summary lines



307
308
309
310
311
312
313
314
315
316
317
# File 'src/modules/BootCommon.rb', line 307

def Summary
  bl = getLoaderType(false)
  if bl == "none"
    return [
      HTML.Colorize(getLoaderName(getLoaderType(false), :summary), "red")
    ]
  end

  # each Boot* should have own summary, that can differ
  raise "Not implemented for bootloader \"#{bl}\""
end

- (String) SupportedLoader(loader)

Check whether loader with specified name is supported

Parameters:

  • loader (String)

    string name of loader to check

Returns:

  • (String)

    the loader name if supported, “none” otherwise



373
374
375
# File 'src/modules/BootCommon.rb', line 373

def SupportedLoader(loader)
  SUPPORTED_BOOTLOADERS.include?(loader) ? loader : "none"
end

- (Object) Update

Update read settings to new version of configuration files



320
321
322
323
324
# File 'src/modules/BootCommon.rb', line 320

def Update
  Builtins.y2debug("No generic update function available")

  nil
end

- (Boolean) VerifyMDArray

FATE#305008: Failover boot configurations for md arrays with redundancy Verify if proposal includes md array with more diferent disks

Returns:

  • (Boolean)

    true if there is md array based on more disks



510
511
512
513
514
515
516
517
518
519
520
# File 'src/modules/BootCommon.rb', line 510

def VerifyMDArray
  if @globals["boot_md_mbr"]
    md_array = @globals["boot_md_mbr"]
    disks = md_array.split(",").reject(&:empty?)
    if Builtins.size(disks) > 1
      Builtins.y2milestone("boot_md_mbr includes disks: %1", disks)
      return true
    end
  end
  return false
end

- (Boolean) Write

Write bootloader settings to disk

Returns:

  • (Boolean)

    true on success



328
329
330
331
# File 'src/modules/BootCommon.rb', line 328

def Write
  Builtins.y2error("No generic write function available")
  false
end