Class: Yast::BootStorageClass

Inherits:
Module
  • Object
show all
Includes:
Logger
Defined in:
src/modules/BootStorage.rb

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Instance Attribute Details

- (Object) mbr_disk

Returns the value of attribute mbr_disk



28
29
30
# File 'src/modules/BootStorage.rb', line 28

def mbr_disk
  @mbr_disk
end

Instance Method Details

- (Object) available_swap_partitions

Get map of swap partitions

Returns:

  • a map where key is partition name and value its size in KB



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'src/modules/BootStorage.rb', line 274

def available_swap_partitions
  tm = Storage.GetTargetMap
  ret = {}
  tm.each_value do |v|
    partitions = v["partitions"] || []
    partitions.select! do |p|
      p["mount"] == "swap" && !p["delete"]
    end
    partitions.each do |s|
      # bnc#577127 - Encrypted swap is not properly set up as resume device
      dev = if s["crypt_device"] && !s["crypt_device"].empty?
        s["crypt_device"]
      else
        s["device"]
      end
      ret[dev] = s["size_k"] || 0
    end
  end

  log.info "Available swap partitions: #{ret}"
  ret
end

- (Boolean) bootloader_installable?

FIXME: merge with BootSupportCheck Check if the bootloader can be installed at all with current configuration

Returns:

  • (Boolean)

    true if it can



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'src/modules/BootStorage.rb', line 145

def bootloader_installable?
  return true if Mode.config
  return true if !Arch.i386 && !Arch.x86_64

  # the only relevant is the partition holding the /boot filesystem
  detect_disks
  Builtins.y2milestone(
    "Boot partition device: %1",
    BootStorage.BootPartitionDevice
  )
  dev = Storage.GetDiskPartition(BootStorage.BootPartitionDevice)
  Builtins.y2milestone("Disk info: %1", dev)
  # MD, but not mirroring is OK
  # FIXME: type detection by name deprecated
  if Ops.get_string(dev, "disk", "") == "/dev/md"
    tm = Storage.GetTargetMap
    md = Ops.get_map(tm, "/dev/md", {})
    parts = Ops.get_list(md, "partitions", [])
    info = {}
    Builtins.foreach(parts) do |p|
      if Ops.get_string(p, "device", "") ==
          BootStorage.BootPartitionDevice
        info = deep_copy(p)
      end
    end
    if Builtins.tolower(Ops.get_string(info, "raid_type", "")) != "raid1"
      Builtins.y2milestone(
        "Cannot install bootloader on RAID (not mirror)"
      )
      return false
    end

  # EVMS
  # FIXME: type detection by name deprecated
  elsif Builtins.search(BootPartitionDevice(), "/dev/evms/") == 0
    Builtins.y2milestone("Cannot install bootloader on EVMS")
    return false
  end

  true
end

- (Object) crypto_devices

Build map with encrypted partitions (even indirectly)

Returns:

  • map with encrypted partitions



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'src/modules/BootStorage.rb', line 299

def crypto_devices
  cryptos = {}
  tm = Yast::Storage.GetTargetMap || {}
  log.info "target map = #{tm}"

  # first, find the directly encrypted things
  # that is, target map has a 'crypt_device' key for it
  #
  # FIXME: can the device itself have a 'crypt_device' key?
  tm.each_value do |d|
    partitions = d["partitions"] || []
    partitions.each do |p|
      if p["crypt_device"]
        cryptos[p["device"]] = true
        cryptos[p["used_by_device"]] = true if p["used_by_device"]
      end
    end
  end

  log.info "crypto devices, step 1 = #{cryptos}"

  # second step: check if the encrypted things have itself partitions
  tm.each_value do |d|
    next if !cryptos[d["device"]]
    partitions = d["partitions"] || []
    partitions.each { |p| cryptos[p["device"]] = true }
  end

  log.info "crypto devices, final = #{cryptos}"

  cryptos
end

- (Object) detect_disks

Sets properly boot, root and mbr disk.



188
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'src/modules/BootStorage.rb', line 188

def detect_disks
  # Use cached value if already detected and cache still valid
  return if !@RootPartitionDevice.empty? && !storage_changed?
  # While calling "yast clone_system" and while cloning bootloader
  # in the AutoYaST module, libStorage has to be set to "normal"
  # mode in order to read mountpoints correctly.
  # (bnc#950105)
  old_mode = Mode.mode
  if Mode.config
    Mode.SetMode("normal")
    log.info "Initialize libstorage in readonly mode" # bnc#942360
    # Set StorageDevices flag disks_valid to true. So InitLibstorage
    # can scan valid disks. (bnc#1046738, bnc#1043132)
    StorageDevices.InitDone
    Storage.InitLibstorage(true)
  end

  # The AutoYaST config mode does access to the system.
  # bnc#942360

  mp = Storage.GetMountPoints

  mountdata_boot = mp["/boot"] || mp["/"]
  mountdata_root = mp["/"]

  log.info "mountPoints #{mp}"
  log.info "mountdata_boot #{mountdata_boot}"

  @RootPartitionDevice = mountdata_root ? mountdata_root.first || "" : ""
  raise ::Bootloader::NoRoot, "Missing '/' mount point" if @RootPartitionDevice.empty?

  # if /boot changed, re-configure location
  @BootPartitionDevice = mountdata_boot.first

  # get extended partition device (if exists)
  @ExtendedPartitionDevice = extended_partition_for(@BootPartitionDevice)

  @mbr_disk = find_mbr_disk

  @storage_timestamp = Storage.GetTargetChangeTime

  Mode.SetMode(old_mode) if old_mode == "autoinst_config"
end

- (Object) disk_with_boot_partition



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'src/modules/BootStorage.rb', line 247

def disk_with_boot_partition
  boot_device = BootPartitionDevice()

  if boot_device.empty?
    log.error "BootPartitionDevice and RootPartitionDevice are empty"
    return boot_device
  end

  p_dev = Storage.GetDiskPartition(boot_device)

  boot_disk_device = p_dev["disk"]

  if boot_disk_device && !boot_disk_device.empty?
    log.info "Boot device - disk: #{boot_disk_device}"
    return boot_disk_device
  end

  log.error("Finding boot disk failed!")
  ""
end

- (Boolean) encrypted_boot?

Returns:

  • (Boolean)


332
333
334
335
336
337
338
339
340
# File 'src/modules/BootStorage.rb', line 332

def encrypted_boot?
  dev = BootPartitionDevice()
  log.info "boot device = #{dev}"
  result = !!crypto_devices[dev]

  log.info "encrypted_boot? = #{result}"

  result
end

- (Object) extended_partition_for(device)

Get extended partition for given partition or disk



116
117
118
119
120
121
122
123
124
125
126
127
# File 'src/modules/BootStorage.rb', line 116

def extended_partition_for(device)
  disk_partition = Yast::Storage.GetDiskPartition(device)
  return nil unless disk_partition["disk"]

  target_map = Yast::Storage.GetTargetMap
  disk_map = target_map[disk_partition["disk"]] || {}
  partitions = disk_map["partitions"] || []
  ext_part = partitions.find { |p| p["type"] == :extended }
  return nil unless ext_part

  ext_part["device"]
end

- (Object) find_mbr_disk



129
130
131
132
133
134
135
136
137
138
139
140
# File 'src/modules/BootStorage.rb', line 129

def find_mbr_disk
  # use the disk with boot partition
  mp = Storage.GetMountPoints
  boot_disk = Ops.get_string(
    mp,
    ["/boot", 2],
    Ops.get_string(mp, ["/", 2], "")
  )
  log.info "Disk with boot partition: #{boot_disk}, using for MBR"

  boot_disk
end

- (Boolean) gpt_boot_disk?

Returns:

  • (Boolean)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'src/modules/BootStorage.rb', line 64

def gpt_boot_disk?
  require "bootloader/bootloader_factory"
  current_bl = ::Bootloader::BootloaderFactory.current

  # efi require gpt disk, so it is always one
  return true if current_bl.name == "grub2efi"
  # if bootloader do not know its location, then we do not care
  return false unless current_bl.respond_to?(:stage1)

  targets = current_bl.stage1.devices
  target_map = Yast::Storage.GetTargetMap
  boot_discs = targets.map { |d| Yast::Storage.GetDisk(target_map, d) }
  boot_discs.any? { |d| d["label"] == "gpt" }
end

- (Object) main



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'src/modules/BootStorage.rb', line 30

def main
  textdomain "bootloader"

  Yast.import "Storage"
  Yast.import "Arch"
  Yast.import "Mode"

  # string sepresenting device name of /boot partition
  # same as RootPartitionDevice if no separate /boot partition
  @BootPartitionDevice = ""

  # string representing device name of / partition
  @RootPartitionDevice = ""

  # string representing device name of extended partition
  @ExtendedPartitionDevice = ""

  # FATE#305008: Failover boot configurations for md arrays with redundancy
  # list <string> includes physical disks used for md raid

  @md_physical_disks = []

  # Timestamp to recognize if cached values are still valid
  @storage_timestamp = nil
end

- (Object) possible_locations_for_stage1

Returns list of partitions and disks. Requests current partitioning from yast2-storage and creates list of partition and disks usable for grub stage1



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
# File 'src/modules/BootStorage.rb', line 81

def possible_locations_for_stage1
  devices = Storage.GetTargetMap

  all_disks = devices.keys

  disks_for_stage1 = all_disks.select do |d|
    [:CT_DISK, :CR_DMRAID].include?(devices[d]["type"])
  end

  partitions = []

  devices.each do |k, v|
    next unless all_disks.include?(k)

    partitions.concat(v["partitions"] || [])
  end

  partitions.delete_if do |p|
    p["delete"]
  end

  partitions.select! do |p|
    [:primary, :extended, :logical, :sw_raid].include?(p["type"]) &&
      (p["used_fs"] || p["detected_fs"]) != :xfs &&
      ["Linux native", "Extended", "Linux RAID", "MD RAID", "DM RAID"].include?(p["fstype"])
  end

  res = partitions.map { |p| p["device"] || "" }
  res.concat(disks_for_stage1)
  res.delete_if(&:empty?)

  res
end

- (Object) prep_partitions



232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'src/modules/BootStorage.rb', line 232

def prep_partitions
  target_map = Storage.GetTargetMap

  partitions = target_map.reduce([]) do |parts, pair|
    parts.concat(pair[1]["partitions"] || [])
  end

  prep_partitions = partitions.select do |partition|
    [0x41, 0x108].include? partition["fsid"]
  end

  y2milestone "detected prep partitions #{prep_partitions.inspect}"
  prep_partitions.map { |p| p["device"] }
end

- (Boolean) separated_boot?

Returns:

  • (Boolean)


268
269
270
# File 'src/modules/BootStorage.rb', line 268

def separated_boot?
  BootPartitionDevice() != RootPartitionDevice()
end

- (Boolean) storage_changed?

Returns:

  • (Boolean)


56
57
58
# File 'src/modules/BootStorage.rb', line 56

def storage_changed?
  @storage_timestamp != Storage.GetTargetChangeTime
end

- (Boolean) storage_read?

Returns:

  • (Boolean)


60
61
62
# File 'src/modules/BootStorage.rb', line 60

def storage_read?
  !@storage_timestamp.nil?
end