Class: Installation::Clients::UmountFinishClient
- Inherits:
-
FinishClient
- Object
- FinishClient
- Installation::Clients::UmountFinishClient
- Includes:
- Yast::Logger
- Defined in:
- src/lib/installation/clients/umount_finish.rb
Overview
Finish client to unmount all mounts to the target
Constant Summary collapse
- BTRFS_FS_TREE =
[String] Name used by btrfs tools to name the filesystem tree.
"(FS_TREE)".freeze
Instance Method Summary collapse
- #close_scr_on_target ⇒ Object protected
-
#default_subvolume_as_ro(filesystem) ⇒ Object
protected
Set the "read-only" property for the root subvolume.
-
#dump_file(filename) ⇒ Object
protected
Dump a file in human-readable form to the log.
-
#initialize ⇒ UmountFinishClient
constructor
Constructor.
-
#log_running_processes(mount_points) ⇒ Object
protected
run "fuser" to get the details about open files.
- #modes ⇒ Object protected
-
#new_filesystem?(filesystem) ⇒ Boolean
protected
Check whether the given filesystem is going to be created.
- #remove_target_etc_mtab ⇒ Object protected
-
#ro_btrfs_filesystem?(filesystem) ⇒ Boolean
protected
Check whether the given filesystem is read-only BTRFS.
-
#run_standalone ⇒ Object
This can be used when invoking this file directly with ruby ./umount_finish.rb.
-
#set_btrfs_defaults_as_ro ⇒ Object
For btrfs filesystems that should be read-only, set the root subvolume to read-only and change the /etc/fstab entry accordingly.
- #title ⇒ Object protected
-
#umount_target_mounts ⇒ Object
protected
Unmount all mounts to the target (typically using the /mnt prefix).
-
#unmount_summary(leftover_paths) ⇒ Object
protected
Write a summary of the unmount operations to the log.
-
#write ⇒ Object
protected
Perform the final actions in the target system.
Constructor Details
#initialize ⇒ UmountFinishClient
Constructor
26 27 28 29 30 31 |
# File 'src/lib/installation/clients/umount_finish.rb', line 26 def initialize super textdomain "installation" Yast.import "FileUtils" @running_standalone = false end |
Instance Method Details
#close_scr_on_target ⇒ Object (protected)
122 123 124 |
# File 'src/lib/installation/clients/umount_finish.rb', line 122 def close_scr_on_target WFM.SCRClose(Installation.scr_handle) end |
#default_subvolume_as_ro(filesystem) ⇒ Object (protected)
Set the "read-only" property for the root subvolume. This has to be done as long as the target root filesystem is still mounted.
165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'src/lib/installation/clients/umount_finish.rb', line 165 def default_subvolume_as_ro(filesystem) output = Yast::Execute.on_target( "btrfs", "subvolume", "get-default", filesystem.mount_point.path, stdout: :capture ) default_subvolume = output.strip.split.last # no btrfs_default_subvolume and no snapshots default_subvolume = "" if default_subvolume == BTRFS_FS_TREE subvolume_path = filesystem.btrfs_subvolume_mount_point(default_subvolume) log.info("Setting root subvol read-only property on #{subvolume_path}") Yast::Execute.on_target("btrfs", "property", "set", subvolume_path, "ro", "true") end |
#dump_file(filename) ⇒ Object (protected)
Dump a file in human-readable form to the log. Do not add the y2log header to each line so it can be easily used.
105 106 107 108 |
# File 'src/lib/installation/clients/umount_finish.rb', line 105 def dump_file(filename) content = File.read(filename) log.info("\n\n#{filename}:\n\n#{content}\n") end |
#log_running_processes(mount_points) ⇒ Object (protected)
run "fuser" to get the details about open files
182 183 184 185 186 187 188 189 190 191 192 |
# File 'src/lib/installation/clients/umount_finish.rb', line 182 def log_running_processes(mount_points) paths = mount_points.join(" ") fuser = begin # (the details are printed on STDERR, redirect it) `LC_ALL=C fuser -v -m #{paths} 2>&1` rescue StandardError => e "fuser failed: #{e}" end log.warn("\n\nRunning processes using #{mount_points}:\n#{fuser}\n") end |
#modes ⇒ Object (protected)
49 50 51 52 53 |
# File 'src/lib/installation/clients/umount_finish.rb', line 49 def modes # FIXME: better use 'nil' for all modes? Then we could rely on the base # class implementation which returns nil by default. [:installation, :live_installation, :update, :autoinst] end |
#new_filesystem?(filesystem) ⇒ Boolean (protected)
Check whether the given filesystem is going to be created
198 199 200 |
# File 'src/lib/installation/clients/umount_finish.rb', line 198 def new_filesystem?(filesystem) !filesystem.exists_in_probed? end |
#remove_target_etc_mtab ⇒ Object (protected)
110 111 112 113 114 115 116 117 118 119 120 |
# File 'src/lib/installation/clients/umount_finish.rb', line 110 def remove_target_etc_mtab # symlink points to /proc, keep it (bnc#665437) return if FileUtils.IsLink("/etc/mtab") # remove [Installation::destdir]/etc/mtab which was faked for %post # scripts in inst_rpmcopy SCR.Execute(path(".target.remove"), "/etc/mtab") # hotfix: recreating /etc/mtab as symlink (bnc#725166) SCR.Execute(path(".target.bash"), "ln -s /proc/self/mounts /etc/mtab") end |
#ro_btrfs_filesystem?(filesystem) ⇒ Boolean (protected)
Check whether the given filesystem is read-only BTRFS
206 207 208 |
# File 'src/lib/installation/clients/umount_finish.rb', line 206 def ro_btrfs_filesystem?(filesystem) filesystem.is?(:btrfs) && filesystem.mount_point && filesystem..include?("ro") end |
#run_standalone ⇒ Object
This can be used when invoking this file directly with ruby ./umount_finish.rb
36 37 38 39 40 |
# File 'src/lib/installation/clients/umount_finish.rb', line 36 def run_standalone @running_standalone = true Installation.destdir = "/mnt" if Installation.destdir == "/" write end |
#set_btrfs_defaults_as_ro ⇒ Object
For btrfs filesystems that should be read-only, set the root subvolume to read-only and change the /etc/fstab entry accordingly.
Since we had to install RPMs to the target, we could not set it to read-only right away; but now we can, and we have to.
This must be done as long as the target root is still mounted (because the btrfs command requires that), but after the last write access to it (because it will be read only afterwards).
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'src/lib/installation/clients/umount_finish.rb', line 137 def set_btrfs_defaults_as_ro # This operation needs root privileges, but it's also generally not a # good idea to do this even if you have the privileges: In that case, # it would change your root subvolume to read-only which is not a good # idea when just invoking this standalone for testing in a development # environment. return if @running_standalone devicegraph = Y2Storage::StorageManager.instance.staging ro_btrfs_filesystems = devicegraph.filesystems.select do |fs| new_filesystem?(fs) && ro_btrfs_filesystem?(fs) end ro_btrfs_filesystems.each { |f| default_subvolume_as_ro(f) } end |
#title ⇒ Object (protected)
44 45 46 47 |
# File 'src/lib/installation/clients/umount_finish.rb', line 44 def title # progress step title _("Unmounting all mounted devices...") end |
#umount_target_mounts ⇒ Object (protected)
Unmount all mounts to the target (typically using the /mnt prefix).
This uses an Installation::Unmounter object which reads /proc/mounts. Relying on y2storage would be risky here since other processes like snapper or libzypp may have mounted filesystems without y2storage knowing about it.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'src/lib/installation/clients/umount_finish.rb', line 75 def umount_target_mounts dump_file("/proc/partitions") dump_file("/proc/mounts") unmounter = ::Installation::Unmounter.new(Installation.destdir) log.info("Paths to unmount: #{unmounter.unmount_paths}") return if unmounter.mounts.empty? begin unmounter.execute rescue Cheetah::ExecutionFailed => e # Typically permissions problem log.error(e.) end unmounter.clear unmounter.read_mounts_file("/proc/mounts") unmount_summary(unmounter.unmount_paths) end |
#unmount_summary(leftover_paths) ⇒ Object (protected)
Write a summary of the unmount operations to the log.
93 94 95 96 97 98 99 100 101 |
# File 'src/lib/installation/clients/umount_finish.rb', line 93 def unmount_summary(leftover_paths) if leftover_paths.empty? log.info("All unmounts successful.") else log.warn("Leftover paths that could not be unmounted: #{leftover_paths}") log_running_processes(leftover_paths) dump_file("/proc/mounts") end end |
#write ⇒ Object (protected)
Perform the final actions in the target system
56 57 58 59 60 61 62 63 64 65 66 |
# File 'src/lib/installation/clients/umount_finish.rb', line 56 def write log.info("Starting umount_finish.rb") remove_target_etc_mtab set_btrfs_defaults_as_ro # No write access to the target after this! close_scr_on_target umount_target_mounts log.info("umount_finish.rb done") true end |