Class: OsCtl::Lib::Zfs::Dataset
- Inherits:
-
Object
- Object
- OsCtl::Lib::Zfs::Dataset
- Includes:
- Utils::Log, Utils::System
- Defined in:
- lib/libosctl/zfs/dataset.rb
Overview
Class representing a single ZFS dataset
Instance Attribute Summary collapse
-
#base ⇒ String
readonly
Base name, i.e.
-
#name ⇒ String
readonly
Full dataset name.
-
#pool ⇒ String
readonly
Zpool name.
-
#properties ⇒ Hash<String, String>
readonly
Dataset properties, only loaded properties are present.
Instance Method Summary collapse
-
#base_name ⇒ String
Return the last component of the dataset name.
-
#children ⇒ Array<Zfs::Dataset>
Return all direct children.
- #create!(**opts) ⇒ Object
- #create_private!(**opts) ⇒ Object
-
#descendants ⇒ Array<Zfs::Dataset>
Return all direct and indirect children.
- #destroy!(**opts) ⇒ Object
- #exist? ⇒ Boolean
-
#export ⇒ Hash
Export to client.
-
#initialize(name, base: '', properties: {}, cache: nil) ⇒ Dataset
constructor
A new instance of Dataset.
- #is_pool? ⇒ Boolean
-
#list(**opts) ⇒ Array<Zfs::Dataset>
List descendant datasets and read selected properties.
-
#mount(recursive: false) ⇒ Object
Ensure the dataset is mounted.
-
#mounted?(recursive: false) ⇒ Boolean
Check if the dataset is mounted.
- #mountpoint ⇒ String
- #on_pool?(pool) ⇒ Boolean
-
#parent ⇒ Zfs::Dataset
Return the direct parent.
-
#parents ⇒ Array<Zfs::Dataset>
Return all parent datasets, up to the root.
- #private_path ⇒ String
-
#relative_name ⇒ String
Return the dataset name relative to the base.
-
#relative_parent ⇒ Zfs::Dataset?
Return the dataset's parent relative to the base.
-
#relative_parents ⇒ Array<Zfs::Dataset>
Return the parents up to the base.
- #root? ⇒ Boolean
- #snapshots ⇒ Array<Zfs::Snapshot>
- #subdataset_of?(dataset) ⇒ Boolean
- #to_s ⇒ Object
-
#unmount(recursive: false) ⇒ Object
Ensure the dataset is unmounted.
Methods included from Utils::System
#find_executable!, #read_process_output, #repeat_on_failure, #syscmd, #syscmd_argv, #write_stdin, #zfs
Methods included from Utils::Log
Constructor Details
#initialize(name, base: '', properties: {}, cache: nil) ⇒ Dataset
Returns a new instance of Dataset.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/libosctl/zfs/dataset.rb', line 31 def initialize(name, base: '', properties: {}, cache: nil) @name = name @pool = name.split('/').first @base = base @properties = properties if properties['mountpoint'] @mountpoint = properties['mountpoint'] elsif cache ds = cache[name] if ds && ds.properties['mountpoint'] @mountpoint = ds.properties['mountpoint'] end end end |
Instance Attribute Details
#base ⇒ String (readonly)
Base name, i.e. path that this dataset is relative to
23 24 25 |
# File 'lib/libosctl/zfs/dataset.rb', line 23 def base @base end |
#name ⇒ String (readonly)
Full dataset name
11 12 13 |
# File 'lib/libosctl/zfs/dataset.rb', line 11 def name @name end |
#pool ⇒ String (readonly)
Zpool name
15 16 17 |
# File 'lib/libosctl/zfs/dataset.rb', line 15 def pool @pool end |
#properties ⇒ Hash<String, String> (readonly)
Dataset properties, only loaded properties are present
19 20 21 |
# File 'lib/libosctl/zfs/dataset.rb', line 19 def properties @properties end |
Instance Method Details
#base_name ⇒ String
Return the last component of the dataset name
264 265 266 |
# File 'lib/libosctl/zfs/dataset.rb', line 264 def base_name name.split('/').last end |
#children ⇒ Array<Zfs::Dataset>
Return all direct children
248 249 250 251 252 |
# File 'lib/libosctl/zfs/dataset.rb', line 248 def children ret = list(depth: 1) ret.shift # remove the current dataset ret end |
#create!(**opts) ⇒ Object
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/libosctl/zfs/dataset.rb', line 69 def create!(**opts) zfs_opts = [] zfs_opts << '-p' if opts[:parents] (opts[:properties] || {}).each do |k, v| zfs_opts << '-o' << "#{k}=#{v}" end zfs(:create, zfs_opts.join(' '), name) end |
#create_private!(**opts) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/libosctl/zfs/dataset.rb', line 83 def create_private!(**opts) if opts[:parents] parents.each do |ds| break if Dir.exist?(ds.private_path) ds.create_private! end end Dir.mkdir(private_path, 0o750) end |
#descendants ⇒ Array<Zfs::Dataset>
Return all direct and indirect children
256 257 258 259 260 |
# File 'lib/libosctl/zfs/dataset.rb', line 256 def descendants ret = list ret.shift # remove the current dataset ret end |
#destroy!(**opts) ⇒ Object
97 98 99 |
# File 'lib/libosctl/zfs/dataset.rb', line 97 def destroy!(**opts) zfs(:destroy, opts[:recursive] ? '-r' : nil, name) end |
#exist? ⇒ Boolean
102 103 104 |
# File 'lib/libosctl/zfs/dataset.rb', line 102 def exist? zfs(:get, '-o value name', name, valid_rcs: [1]).success? end |
#export ⇒ Hash
Export to client
318 319 320 321 322 |
# File 'lib/libosctl/zfs/dataset.rb', line 318 def export ret = { 'name' => relative_name, 'dataset' => name } ret.update(properties) ret end |
#is_pool? ⇒ Boolean
57 58 59 |
# File 'lib/libosctl/zfs/dataset.rb', line 57 def is_pool? !@name.include?('/') end |
#list(**opts) ⇒ Array<Zfs::Dataset>
List descendant datasets and read selected properties
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 153 154 155 156 157 158 159 160 161 |
# File 'lib/libosctl/zfs/dataset.rb', line 119 def list(**opts) include_self = opts.fetch(:include_self, true) zfs_opts = [ '-r', '-H', '-p', '-o', 'name,property,value', '-t', opts[:type] || 'filesystem' ] zfs_opts << '-d' << opts[:depth] if opts[:depth] properties = [] properties.concat(opts[:properties]) if opts[:properties] properties << 'name' if properties.empty? properties.uniq! zfs_opts << properties.map(&:to_s).join(',') ret = [] last = nil zfs(:get, zfs_opts.join(' '), name).output.strip.split("\n").each do |line| name, property, value = line.split next if !include_self && name == self.name if !last || last.name != name ret << last unless last.nil? last = if opts[:create] opts[:create].call(name) else self.class.new(name, base:) end end next if property == 'name' last.properties[property] = value end ret << last unless last.nil? ret end |
#mount(recursive: false) ⇒ Object
Ensure the dataset is mounted
178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/libosctl/zfs/dataset.rb', line 178 def mount(recursive: false) zfs( :list, "-H -o name,mounted -t filesystem #{recursive ? '-r' : ''}", name ).output.split("\n").each do |line| ds, mounted = line.split next if mounted == 'yes' zfs(:mount, nil, ds) rescue Exceptions::SystemCommandFailed => e raise unless e.output.include?('filesystem already mounted') end end |
#mounted?(recursive: false) ⇒ Boolean
Check if the dataset is mounted
212 213 214 215 216 217 218 |
# File 'lib/libosctl/zfs/dataset.rb', line 212 def mounted?(recursive: false) zfs( :get, "-H #{recursive ? '-r' : ''} -t filesystem -o value mounted", name ).output.split("\n").all? { |v| v == 'yes' } end |
#mountpoint ⇒ String
164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/libosctl/zfs/dataset.rb', line 164 def mountpoint if @mountpoint @mountpoint elsif properties['mountpoint'] @mountpoint = properties['mountpoint'] else @mountpoint = zfs(:get, '-H -o value mountpoint', name).output.strip end end |
#on_pool?(pool) ⇒ Boolean
53 54 55 |
# File 'lib/libosctl/zfs/dataset.rb', line 53 def on_pool?(pool) @pool == pool end |
#parent ⇒ Zfs::Dataset
Return the direct parent
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/libosctl/zfs/dataset.rb', line 222 def parent parts = name.split('/') if parts.count == 1 nil else self.class.new(parts[0..-2].join('/'), base:) end end |
#parents ⇒ Array<Zfs::Dataset>
Return all parent datasets, up to the root
235 236 237 238 239 240 241 242 243 244 |
# File 'lib/libosctl/zfs/dataset.rb', line 235 def parents ret = [] parts = name.split('/')[0..-2] parts.each_with_index do |_v, i| ret << self.class.new(parts[0..i].join('/'), base:) end ret.reverse! end |
#private_path ⇒ String
107 108 109 |
# File 'lib/libosctl/zfs/dataset.rb', line 107 def private_path File.join(mountpoint, 'private') end |
#relative_name ⇒ String
Return the dataset name relative to the base
270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/libosctl/zfs/dataset.rb', line 270 def relative_name return @relative_name if @relative_name @relative_name = if base == name '/' elsif !name.start_with?("#{base}/") raise "invalid base '#{base}' for '#{name}'" else name[(base.length + 1)..] end end |
#relative_parent ⇒ Zfs::Dataset?
Return the dataset's parent relative to the base
286 287 288 289 290 291 292 293 294 |
# File 'lib/libosctl/zfs/dataset.rb', line 286 def relative_parent ret = parent @relative_parent = if ret.nil? || ret.name.length < @base.length nil else ret end end |
#relative_parents ⇒ Array<Zfs::Dataset>
Return the parents up to the base
298 299 300 |
# File 'lib/libosctl/zfs/dataset.rb', line 298 def relative_parents parents.take_while { |ds| ds.name.length >= @base.length } end |
#root? ⇒ Boolean
303 304 305 |
# File 'lib/libosctl/zfs/dataset.rb', line 303 def root? name == base || !name.index('/') end |
#snapshots ⇒ Array<Zfs::Snapshot>
308 309 310 311 312 313 314 |
# File 'lib/libosctl/zfs/dataset.rb', line 308 def snapshots list( type: 'snapshot', depth: 1, create: ->(name) { Zfs::Snapshot.new(self, name.split('@')[1]) } ) end |
#subdataset_of?(dataset) ⇒ Boolean
62 63 64 |
# File 'lib/libosctl/zfs/dataset.rb', line 62 def subdataset_of?(dataset) name.start_with?("#{dataset.name}/") end |
#to_s ⇒ Object
48 49 50 |
# File 'lib/libosctl/zfs/dataset.rb', line 48 def to_s name end |
#unmount(recursive: false) ⇒ Object
Ensure the dataset is unmounted
195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/libosctl/zfs/dataset.rb', line 195 def unmount(recursive: false) zfs( :list, "-H -o name,mounted -t filesystem #{recursive ? '-r' : ''}", name ).output.split("\n").reverse_each do |line| ds, mounted = line.split next if mounted != 'yes' zfs(:unmount, nil, ds) rescue Exceptions::SystemCommandFailed => e raise unless e.output.include?('not currently mounted') end end |