Class: Yast2::FsSnapshot

Inherits:
Object
  • Object
show all
Includes:
Yast::Logger
Defined in:
library/system/src/lib/yast2/fs_snapshot.rb

Overview

Class for managing filesystem snapshots. It's important to note that this class is intended to be used during installation/update so it uses the Snapper's CLI because the DBus interface is not available at that time.

Constant Summary collapse

FIND_CONFIG_CMD =
"/usr/bin/snapper --no-dbus --root=%{root} list-configs | grep \"^root \" >/dev/null".freeze
CREATE_SNAPSHOT_CMD =
"/usr/lib/snapper/installation-helper --step 5 --root-prefix=%{root} --snapshot-type %{snapshot_type} --description \"%{description}\"".freeze
LIST_SNAPSHOTS_CMD =
"LANG=en_US.UTF-8 /usr/bin/snapper --no-dbus --root=%{root} list".freeze
VALID_LINE_REGEX =
/\A\w+\s+\| \d+/
CLEANUP_STRATEGY =

Predefined snapshot cleanup strategies (the user can define custom ones, too)

{ number: "number", timeline: "timeline" }.freeze

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(number, snapshot_type, previous_number, timestamp, user, cleanup_algo, description) ⇒ FsSnapshot

FsSnapshot constructor

This method is not intended to be called by users of FsSnapshot class. Instead, class methods must be used.

Parameters:

  • number (Fixnum)

    Snapshot's number.

  • snapshot_type (Symbol)

    Snapshot's type: :pre, :post or :single.

  • previous_number (Fixnum)

    Previous snapshot's number.

  • timestamp (DateTime)

    Timestamp

  • user (String)

    Snapshot's owner username.

  • cleanup_algo (String)

    Clean-up algorithm.

  • description (String)

    Snapshot's description.



98
99
100
101
102
103
104
105
106
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 98

def initialize(number, snapshot_type, previous_number, timestamp, user, cleanup_algo, description)
  @number = number
  @snapshot_type = snapshot_type
  @previous_number = previous_number
  @timestamp = timestamp
  @user = user
  @cleanup_algo = cleanup_algo
  @description = description
end

Class Attribute Details

.configure_on_install=(value) ⇒ Object (writeonly)

See Also:

  • #configure_on_install?


166
167
168
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 166

def configure_on_install=(value)
  @configure_on_install = value
end

Instance Attribute Details

#cleanup_algoObject (readonly)

Returns the value of attribute cleanup_algo



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def cleanup_algo
  @cleanup_algo
end

#descriptionObject (readonly)

Returns the value of attribute description



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def description
  @description
end

#numberObject (readonly)

Returns the value of attribute number



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def number
  @number
end

#previous_numberObject (readonly)

Returns the value of attribute previous_number



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def previous_number
  @previous_number
end

#snapshot_typeObject (readonly)

Returns the value of attribute snapshot_type



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def snapshot_type
  @snapshot_type
end

#timestampObject (readonly)

Returns the value of attribute timestamp



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def timestamp
  @timestamp
end

#userObject (readonly)

Returns the value of attribute user



82
83
84
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 82

def user
  @user
end

Class Method Details

.allArray<FsSnapshot>

Returns all snapshots

It raises an exception if Snapper is not configured.

Returns:

  • (Array<FsSnapshot>)

    All snapshots that exist in the system.

Raises:



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 251

def all
  raise SnapperNotConfigured unless configured?

  out = Yast::SCR.Execute(
    Yast::Path.new(".target.bash_output"),
    format(LIST_SNAPSHOTS_CMD, root: target_root)
  )
  lines = out["stdout"].lines.grep(VALID_LINE_REGEX) # relevant lines from output.
  log.info("Retrieving snapshots list: #{LIST_SNAPSHOTS_CMD} returned: #{out}")
  lines.each_with_object([]) do |line, snapshots|
    data = line.split("|").map(&:strip)
    next if data[1] == "0" # Ignores 'current' snapshot (id = 0) because it's not a real snapshot
    begin
      timestamp = DateTime.parse(data[3])
    rescue ArgumentError
      log.warn("Error when parsing date/time: #{timestamp}")
      timestamp = nil
    end
    previous_number = data[2] == "" ? nil : data[2].to_i
    snapshots << new(data[1].to_i, data[0].to_sym, previous_number, timestamp,
      data[4], data[5].to_sym, data[6])
  end
end

.configure_on_install?Boolean

Whether Snapper should be configured at the end of installation

Returns:

  • (Boolean)


161
162
163
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 161

def configure_on_install?
  !!@configure_on_install
end

.configure_snapperObject

Performs the final steps to configure snapper for the root filesystem on a fresh installation.

First part of the configuration must have been already done while the root filesystem is created.

This part here is what is left to do after the package installation in the target system is complete.

Raises:



148
149
150
151
152
153
154
155
156
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 148

def configure_snapper
  raise SnapperNotConfigurable if !Yast::Mode.installation || non_switched_installation?
  @configured = nil

  installation_helper_step_4
  write_snapper_config
  update_etc_sysconfig_yast2
  setup_snapper_quota
end

.configured?true, false

Determines whether snapper is configured or not

Returns:

  • (true, false)

    true if it's configured; false otherwise.



125
126
127
128
129
130
131
132
133
134
135
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 125

def configured?
  return @configured unless @configured.nil?

  out = Yast::SCR.Execute(
    Yast::Path.new(".target.bash_output"),
    format(FIND_CONFIG_CMD, root: target_root)
  )

  log.info("Checking if Snapper is configured: \"#{FIND_CONFIG_CMD}\" returned: #{out}")
  @configured = out["exit"] == 0
end

.create_post(description, previous_number, cleanup: nil, important: false) ⇒ FsSnapshot

Creates a new 'post' snapshot unless disabled by user

Each 'post' snapshot corresponds with a 'pre' one.

Parameters:

  • description (String)

    Snapshot's description.

  • previous_number (Fixnum)

    Number of the previous snapshot

  • cleanup (String)

    Cleanup strategy (:number, :timeline, nil)

  • important (boolean)

    Add “important” to userdata?

Returns:

See Also:



233
234
235
236
237
238
239
240
241
242
243
244
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 233

def create_post(description, previous_number, cleanup: nil, important: false)
  return nil unless create_snapshot?(:around)

  previous = find(previous_number)

  if previous
    create(:post, description, previous: previous, cleanup: cleanup, important: important)
  else
    log.error "Previous filesystem snapshot was not found"
    raise PreviousSnapshotNotFound
  end
end

.create_pre(description, cleanup: nil, important: false) ⇒ FsSnapshot

Creates a new 'pre' snapshot

Parameters:

  • description (String)

    Snapshot's description.

Returns:

See Also:



215
216
217
218
219
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 215

def create_pre(description, cleanup: nil, important: false)
  return nil unless create_snapshot?(:around)

  create(:pre, description, cleanup: cleanup, important: important)
end

.create_single(description, cleanup: nil, important: false) ⇒ FsSnapshot

Creates a new 'single' snapshot unless disabled by user

Parameters:

  • description (String)

    Snapshot's description.

  • cleanup (String)

    Cleanup strategy (:number, :timeline, nil)

  • important (boolean)

    Add “important” to userdata?

Returns:

See Also:



202
203
204
205
206
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 202

def create_single(description, cleanup: nil, important: false)
  return nil unless create_snapshot?(:single)

  create(:single, description, cleanup: cleanup, important: important)
end

.create_snapshot?(snapshot_type) ⇒ Boolean

Returns whether creating the given snapshot type is allowed Information is taken from Linuxrc (DISABLE_SNAPSHOTS)

* "all" - all snapshot types are temporarily disabled
* "around" - before and after calling YaST
* "single" - single snapshot at a given point

Parameters:

  • one (Symbol)

    of :around (for :post and :pre snapshots) or :single

Returns:

  • (Boolean)

    if snapshot should be created



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 176

def create_snapshot?(snapshot_type)
  disable_snapshots = Yast::Linuxrc.value_for(Yast::LinuxrcClass::DISABLE_SNAPSHOTS)

  # Feature is not defined on Linuxrc commandline
  return true if disable_snapshots.nil? || disable_snapshots.empty?

  disable_snapshots = disable_snapshots.downcase.tr("-_.", "").split(",")

  if [:around, :single].include?(snapshot_type)
    return false if disable_snapshots.include?("all")
    return !disable_snapshots.include?(snapshot_type.to_s)
  else
    raise ArgumentError, "Unsupported snapshot type #{snapshot_type.inspect}, " \
          "supported are :around and :single"
  end
end

.find(number) ⇒ FsSnapshot?

Finds a snapshot by its number

It raises an exception if Snapper is not configured.

Parameters:

  • nubmer (Fixnum)

    Number of the snapshot to search for.

Returns:

  • (FsSnapshot, nil)

    The snapshot with the number number if found. Otherwise, it returns nil.

See Also:



283
284
285
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 283

def find(number)
  all.find { |s| s.number == number }
end

Instance Method Details

#previousFsSnapshot?

Returns the previous snapshot

Returns:

  • (FsSnapshot, nil)

    Object representing the previous snapshot.



113
114
115
# File 'library/system/src/lib/yast2/fs_snapshot.rb', line 113

def previous
  @previous ||= @previous_number ? FsSnapshot.find(@previous_number) : nil
end