Class: ZFS::Snapshot

Inherits:
ZFS
  • Object
show all
Defined in:
lib/zfs.rb

Instance Attribute Summary

Attributes inherited from ZFS

#name, #path, #pool

Instance Method Summary collapse

Methods inherited from ZFS

#==, #[], #[]=, #children, #create, #destroy!, #exist?, #initialize, mounts, pools, property, #to_s

Constructor Details

This class inherits a constructor from ZFS

Instance Method Details

#+(path) ⇒ Object

Return sub-filesystem

Raises:



328
329
330
331
332
# File 'lib/zfs.rb', line 328

def +(path)
  raise InvalidName if path.match(/@/)

  parent + path + name.sub(/^.+@/, '@')
end

#clone!(clone, opts = {}) ⇒ Object

Clone snapshot

Raises:



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/zfs.rb', line 361

def clone!(clone, opts={})
  clone = clone.name if clone.is_a? ZFS

  raise AlreadyExists if ZFS(clone).exist?

  cmd = [ZFS.zfs_path].flatten + ['clone']
  cmd << '-p' if opts[:parents]
  cmd << name
  cmd << clone

  out, status = Open3.capture2e(*cmd)

  if status.success? and out.empty?
    return ZFS(clone)
  else
    raise Exception, "something went wrong"
  end
end

#parentObject

Just remove the snapshot-name



335
336
337
# File 'lib/zfs.rb', line 335

def parent
  ZFS(name.sub(/@.+/, ''))
end

#rename!(newname, opts = {}) ⇒ Object

Rename snapshot

Raises:



340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/zfs.rb', line 340

def rename!(newname, opts={})
  raise AlreadyExists if (parent + "@#{newname}").exist?

  newname = (parent + "@#{newname}").name

  cmd = [ZFS.zfs_path].flatten + ['rename']
  cmd << '-r' if opts[:children]
  cmd << name
  cmd << newname

  out, status = Open3.capture2e(*cmd)

  if status.success? and out.empty?
    initialize(newname)
    return self
  else
    raise Exception, "something went wrong"
  end
end

#send_to(dest, opts = {}) ⇒ Object

Send snapshot to another filesystem



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/zfs.rb', line 381

def send_to(dest, opts={})
  incr_snap = nil
  dest = ZFS(dest)

  if opts[:incremental] and opts[:intermediary]
    raise ArgumentError, "can't specify both :incremental and :intermediary"
  end

  incr_snap = opts[:incremental] || opts[:intermediary]
  if incr_snap
    if incr_snap.is_a? String and incr_snap.match(/^@/)
      incr_snap = self.parent + incr_snap
    else
      incr_snap = ZFS(incr_snap)
      raise ArgumentError, "incremental snapshot must be in the same filesystem as #{self}" if incr_snap.parent != self.parent
    end

    snapname = incr_snap.name.sub(/^.+@/, '@')

    raise NotFound, "destination must already exist when receiving incremental stream" unless dest.exist?
    raise NotFound, "snapshot #{snapname} must exist at #{self.parent}" if self.parent.snapshots.grep(incr_snap).empty?
    raise NotFound, "snapshot #{snapname} must exist at #{dest}" if dest.snapshots.grep(dest + snapname).empty?
  elsif opts[:use_sent_name]
    raise NotFound, "destination must already exist when using sent name" unless dest.exist?
  elsif dest.exist?
    raise AlreadyExists, "destination must not exist when receiving full stream"
  end

  dest = dest.name if dest.is_a? ZFS
  incr_snap = incr_snap.name if incr_snap.is_a? ZFS

  send_opts = ZFS.zfs_path.flatten + ['send']
  send_opts.concat ['-i', incr_snap] if opts[:incremental]
  send_opts.concat ['-I', incr_snap] if opts[:intermediary]
  send_opts << '-R' if opts[:replication]
  send_opts << name

  receive_opts = ZFS.zfs_path.flatten + ['receive']
  receive_opts << '-d' if opts[:use_sent_name]
  receive_opts << dest

  Open3.popen3(*receive_opts) do |rstdin, rstdout, rstderr, rthr|
    Open3.popen3(*send_opts) do |sstdin, sstdout, sstderr, sthr|
      while !sstdout.eof?
        rstdin.write(sstdout.read(16384))
      end
      raise "stink" unless sstderr.read == ''
    end
  end
end