Class: Snapsync::PartitionsMonitor
- Inherits:
-
Object
- Object
- Snapsync::PartitionsMonitor
- Defined in:
- lib/snapsync/partitions_monitor.rb
Instance Attribute Summary collapse
-
#dirty ⇒ Object
readonly
Returns the value of attribute dirty.
- #known_partitions ⇒ Hash<String, Dev> readonly
- #monitored_partitions ⇒ Set<String> readonly
- #partition_table ⇒ Hash<String, DBus::ProxyObjectInterface> readonly
-
#udisk ⇒ Object
readonly
Returns the value of attribute udisk.
Instance Method Summary collapse
- #dirty! ⇒ Object
- #dirty? ⇒ Boolean
-
#each_partition_with_filesystem {|the, the| ... } ⇒ Object
Yields the udev objects representing block devices that support an underlying filesystem.
- #emit_added(uuid, fs) ⇒ Object
- #emit_removed(uuid) ⇒ Object
-
#initialize(machine = nil) ⇒ PartitionsMonitor
constructor
A new instance of PartitionsMonitor.
- #monitor_for(partition_uuid) ⇒ Object
- #mountpoint_of_uuid(partition_uuid) ⇒ Object
- #mountpoints(fs) ⇒ Array<String>
-
#partition_of(dir) ⇒ String, ...
Uuid dir rel.
- #partition_uuid_for_dir(dir) ⇒ Object
- #poll ⇒ Object
Constructor Details
#initialize(machine = nil) ⇒ PartitionsMonitor
Returns a new instance of PartitionsMonitor.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 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 55 56 57 58 59 60 61 |
# File 'lib/snapsync/partitions_monitor.rb', line 16 def initialize(machine = nil) if machine.nil? dbus = DBus::SystemBus.instance else sock_path = '/tmp/snapsync_%04d_remote.sock' % rand(10000) ready = Concurrent::AtomicBoolean.new(false) @ssh_thr = Thread.new do machine.dup_ssh do |ssh| @ssh = ssh if Snapsync.SSH_DEBUG log = Logger.new(STDOUT) log.level = Logger::DEBUG ssh.logger = log ssh.logger.sev_threshold=Logger::Severity::DEBUG end ssh.forward.local_socket(sock_path, '/var/run/dbus/system_bus_socket') ObjectSpace.define_finalizer(@ssh, proc { File.delete sock_path }) ready.make_true ssh.loop { true } end end while ready.false? sleep 0.001 end dbus = DBus::RemoteBus.new "unix:path=#{sock_path}" end @udisk = dbus.service('org.freedesktop.UDisks2') udisk.introspect @dirty = Concurrent::AtomicBoolean.new(false) # udisk.on_signal('InterfacesAdded') do # dirty! # end # udisk.on_signal('InterfacesRemoved') do # dirty! # end @monitored_partitions = Set.new @known_partitions = Hash.new @partition_table = Hash.new end |
Instance Attribute Details
#dirty ⇒ Object (readonly)
Returns the value of attribute dirty.
5 6 7 |
# File 'lib/snapsync/partitions_monitor.rb', line 5 def dirty @dirty end |
#known_partitions ⇒ Hash<String, Dev> (readonly)
10 11 12 |
# File 'lib/snapsync/partitions_monitor.rb', line 10 def known_partitions @known_partitions end |
#monitored_partitions ⇒ Set<String> (readonly)
8 9 10 |
# File 'lib/snapsync/partitions_monitor.rb', line 8 def monitored_partitions @monitored_partitions end |
#partition_table ⇒ Hash<String, DBus::ProxyObjectInterface> (readonly)
13 14 15 |
# File 'lib/snapsync/partitions_monitor.rb', line 13 def partition_table @partition_table end |
#udisk ⇒ Object (readonly)
Returns the value of attribute udisk.
3 4 5 |
# File 'lib/snapsync/partitions_monitor.rb', line 3 def udisk @udisk end |
Instance Method Details
#dirty! ⇒ Object
113 114 115 |
# File 'lib/snapsync/partitions_monitor.rb', line 113 def dirty! dirty.set end |
#dirty? ⇒ Boolean
117 118 119 |
# File 'lib/snapsync/partitions_monitor.rb', line 117 def dirty? dirty.set? end |
#each_partition_with_filesystem {|the, the| ... } ⇒ Object
Yields the udev objects representing block devices that support an underlying filesystem
182 183 184 185 186 187 188 189 190 |
# File 'lib/snapsync/partitions_monitor.rb', line 182 def each_partition_with_filesystem return enum_for(__method__) if !block_given? udisk.root['org']['freedesktop']['UDisks2']['block_devices'].each do |device_name, _| dev = udisk.object("/org/freedesktop/UDisks2/block_devices/#{device_name}") if dev.has_iface?('org.freedesktop.UDisks2.Block') && dev.has_iface?('org.freedesktop.UDisks2.Filesystem') yield(device_name, dev) end end end |
#emit_added(uuid, fs) ⇒ Object
171 172 |
# File 'lib/snapsync/partitions_monitor.rb', line 171 def emit_added(uuid, fs) end |
#emit_removed(uuid) ⇒ Object
174 175 |
# File 'lib/snapsync/partitions_monitor.rb', line 174 def emit_removed(uuid) end |
#monitor_for(partition_uuid) ⇒ Object
79 80 81 |
# File 'lib/snapsync/partitions_monitor.rb', line 79 def monitor_for(partition_uuid) monitored_partitions << partition_uuid.to_str end |
#mountpoint_of_uuid(partition_uuid) ⇒ Object
73 74 75 76 77 |
# File 'lib/snapsync/partitions_monitor.rb', line 73 def mountpoint_of_uuid(partition_uuid) mounts = mountpoints(known_partitions[partition_uuid]) raise "Ambiguous mountpoints: #{mounts}" if mounts.length > 1 mounts[0] end |
#mountpoints(fs) ⇒ Array<String>
65 66 67 68 69 70 71 |
# File 'lib/snapsync/partitions_monitor.rb', line 65 def mountpoints(fs) raise "Not mounted?" if fs.nil? mount_points = fs['MountPoints'].map do |str| str[0..-2].pack("U*") end return mount_points end |
#partition_of(dir) ⇒ String, ...
Returns uuid dir rel.
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 |
# File 'lib/snapsync/partitions_monitor.rb', line 84 def partition_of(dir) rel = Pathname.new("") dir = dir. while !dir.mountpoint? rel = dir.basename + rel dir = dir.dirname end # Collect partitions list from udisk parts = [] each_partition_with_filesystem do |name, dev| partition = dev['org.freedesktop.UDisks2.Block'] uuid = partition['IdUUID'] fs = dev['org.freedesktop.UDisks2.Filesystem'] mount_points = fs['MountPoints'].map do |str| str[0..-2].pack("U*") end parts.push([name, uuid, mount_points]) end # Find any partition that is a parent of the folder we are looking at parts.each do |name, uuid, mount_points| if mount_points.include?(dir.path_part) return uuid, dir, rel end end raise ArgumentError, "cannot guess the partition UUID of the mountpoint #{dir} for #{dir + rel}" end |
#partition_uuid_for_dir(dir) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/snapsync/partitions_monitor.rb', line 121 def partition_uuid_for_dir(dir) dir = dir. # Find the dir's mountpoint while !dir.mountpoint? dir = dir.parent end dir = dir.to_s each_partition_with_filesystem.find do |name, dev| fs = dev['org.freedesktop.UDisks2.Filesystem'] mp = fs['MountPoints'] # .map { |str| Pathname.new(str) } mp.include?(dir) end end |
#poll ⇒ Object
137 138 139 140 141 142 143 144 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 |
# File 'lib/snapsync/partitions_monitor.rb', line 137 def poll udisk.introspect dirty.make_false all = Hash.new each_partition_with_filesystem do |name, dev| # @type [DBus::ProxyObjectInterface] partition = dev['org.freedesktop.UDisks2.Block'] # @type [String] uuid = partition['IdUUID'] if monitored_partitions.include?(uuid) fs = dev['org.freedesktop.UDisks2.Filesystem'] # If it is a btrfs raid, it will have multiple partitions with the same uuid, but only one will be # mounted. next if all.has_key?(uuid) and all[uuid]['MountPoints'].size > 0 all[uuid] = fs end end added = Hash.new (all.keys - known_partitions.keys).each do |uuid| fs = added[uuid] = all[uuid] emit_added(uuid, fs) end removed = (known_partitions.keys - all.keys) removed.each { |uuid| emit_removed(uuid) } @known_partitions = all return added, removed end |