module Frachtraum
Constants
- BALLOTX
- BYTES_IN_GB
- BYTES_IN_GiB
- BYTES_IN_KB
these define a KB as 1000 bits, according to the SI prefix
- BYTES_IN_KiB
Kibibyte, Mebibyte, Gibibyte, etc… all the IEC sizes
- BYTES_IN_MB
- BYTES_IN_MiB
- BYTES_IN_TB
- BYTES_IN_TiB
- CHECKMARK
- COMPRESSION
- CONFIG_FILE
- ENCRYPTION
- KEYLENGTH
- MOUNTPOINT
- OUTPUT_DOTS_LEN
- REQUIRED_TOOLS_BSD
- REQUIRED_TOOLS_LINUX
- REQUIRED_TOOLS_OSX
Maybe this will come in time, but it is not a priority. There is some literature on disk encryption from the command line: krypted.com/mac-security/encrypting-os-x-mountain-lion/
- TIMEMACHINE_TARGETS
- VERSION
- VOLUMES
Public Class Methods
attach(password, volume=nil)
click to toggle source
# File lib/frachtraum.rb, line 73 def attach(password, volume=nil) case RUBY_PLATFORM when /bsd/ then attach_bsd password, volume when /linux/ then attach_linux password, volume #when /darwin/ then attach_osx password, volume else abort "OS not supported" end end
capacity()
click to toggle source
# File lib/frachtraum.rb, line 83 def capacity() total_used = 0 total_avail = 0 Frachtraum::VOLUMES.each do |volume| used = %x( zfs get -o value -Hp used #{volume} 2>&1 ) avail = %x( zfs get -o value -Hp available #{volume} 2>&1 ) total_used += (used =="" ? 0 : used).to_i # / 1000 # 1024 total_avail += (avail=="" ? 0 : avail).to_i # / 1000 # 1024 end total = total_used + total_avail return {:total => total, :avail => total_avail, :used => total_used} end
pretty_IEC_bytes(bytes)
click to toggle source
# File lib/frachtraum.rb, line 64 def pretty_IEC_bytes(bytes) return "%.1f TiB" % (bytes.to_f / BYTES_IN_TiB) if bytes > BYTES_IN_TiB return "%.1f GiB" % (bytes.to_f / BYTES_IN_GiB) if bytes > BYTES_IN_GiB return "%.1f MiB" % (bytes.to_f / BYTES_IN_MiB) if bytes > BYTES_IN_MiB return "%.1f KiB" % (bytes.to_f / BYTES_IN_KiB) if bytes > BYTES_IN_KiB return "#{bytes} B" end
pretty_SI_bytes(bytes)
click to toggle source
# File lib/frachtraum.rb, line 55 def pretty_SI_bytes(bytes) return "%.1f TB" % (bytes.to_f / BYTES_IN_TB) if bytes > BYTES_IN_TB return "%.1f GB" % (bytes.to_f / BYTES_IN_GB) if bytes > BYTES_IN_GB return "%.1f MB" % (bytes.to_f / BYTES_IN_MB) if bytes > BYTES_IN_MB return "%.1f KB" % (bytes.to_f / BYTES_IN_KB) if bytes > BYTES_IN_KB return "#{bytes} B" end
report()
click to toggle source
# File lib/frachtraum.rb, line 100 def report() report_table = {} reported_values = [:used,:available,:compression,:compressratio] (Frachtraum::VOLUMES + Frachtraum::TIMEMACHINE_TARGETS).each do |dataset| volume_info = {} # fetch the values if zfs_volume_exists?(dataset) reported_values.each do |repval| volume_info[repval] = %x( zfs get -o value -Hp #{repval.to_s} #{dataset} ) end else reported_values.each {|repval| volume_info[repval] = "N/A" } end # calculate a total size for each volume volume_info[:total] = if volume_info[:used]=="N/A" || volume_info[:available]=="N/A" "N/A" else (volume_info[:used].to_i + volume_info[:available].to_i) end volume_info[:usage] = if volume_info[:total] == 0 "0 %" elsif volume_info[:used]=="N/A" || volume_info[:total]=="N/A" "N/A" elsif volume_info[:available].to_i == 0 "100 %" else (100 * volume_info[:used].to_f / volume_info[:total].to_f ).to_i.to_s + " %" end report_table[dataset] = volume_info end return report_table end
run_system_test()
click to toggle source
# File lib/frachtraum.rb, line 173 def run_system_test() tool_list = [] case RUBY_PLATFORM when /bsd/ then tool_list = REQUIRED_TOOLS_BSD when /linux/ then tool_list = REQUIRED_TOOLS_LINUX #when /darwin/ then tool_list = REQUIRED_TOOLS_OSX else abort "OS not supported" end tool_list.each { |tool| find_executable tool } # find_executable seems to create such file in case executable is not found File.delete 'mkmf.log' if File.exists?('mkmf.log') end
setupdisk(dev, label, password, compression, encryption, keylength, mountpoint)
click to toggle source
# File lib/frachtraum.rb, line 144 def setupdisk(dev, label, password, compression, encryption, keylength, mountpoint) abort "untested procedure -- won't continue" case RUBY_PLATFORM when /bsd/ then setupdisk_bsd dev, label, password, compression, encryption, keylength, mountpoint when /linux/ then setupdisk_linux dev, label, password, compression, encryption, keylength, mountpoint #when /darwin/ then setupdisk_osx dev, label, password, compression, encryption, keylength, mountpoint else abort "OS not supported" end end
sweep(volume)
click to toggle source
# File lib/frachtraum.rb, line 157 def sweep(volume) target_volumes = volume.nil? ? Frachtraum::VOLUMES : volume # TODO abort "sweeping not supported yet" target_volumes.each do |volume| if zfs_volume_exists?(volume) # TODO end end end
zfs_volume_exists?(dataset)
click to toggle source
# File lib/frachtraum.rb, line 190 def zfs_volume_exists?(dataset) output = %x( zfs get -H mounted #{dataset} 2>&1 ) case output when /yes/ return true when /dataset does not exist/, /permission denied/ return false else abort "can't handle output of zfs_volume_exists?: #{output}" end end
Public Instance Methods
attach_bsd(password, volume=nil)
click to toggle source
# File lib/frachtraum/bsd.rb, line 5 def attach_bsd(password, volume=nil) # if we provided a specific depot, run procedure only on that one volumes = volume.nil? ? Frachtraum::VOLUMES : [ volume ] # first of all, decrypt and mount all depots volumes.each do |v| print "decrypting #{v}...".ljust(OUTPUT_DOTS_LEN,".") output = %x( echo #{password} | geli attach -d -j - /dev/label/#{v} 2>&1 ) if $?.success? output = %x( zfs mount #{v} 2>&1 ) if $?.success? then puts Rainbow(CHECKMARK).green else puts Rainbow("#{BALLOTX}\n#{output}").red end else puts Rainbow("#{BALLOTX}\n#{output}").red end end # volumes.each # mount timemachine targets as well Frachtraum::TIMEMACHINE_TARGETS.each do |tmtarget| print "mounting #{tmtarget}...".ljust(OUTPUT_DOTS_LEN,".") output = %x( zfs mount #{tmtarget} 2>&1 ) if $?.success? then puts Rainbow(CHECKMARK).green else puts Rainbow("#{BALLOTX}\n#{output}").red end end # restart samba so it reports the correct pool size print "restarting samba server...".ljust(OUTPUT_DOTS_LEN,".") output = %x( /usr/local/etc/rc.d/samba restart 2>&1 ) if $?.success? then puts Rainbow(CHECKMARK).green else puts Rainbow("#{BALLOTX}\n#{output}").red end end
attach_linux(password, volume)
click to toggle source
# File lib/frachtraum/linux.rb, line 5 def attach_linux(password, volume) # TODO abort "not yet implemented" end
attach_osx(password, volume)
click to toggle source
# File lib/frachtraum/osx.rb, line 11 def attach_osx(password, volume) # TODO abort "not yet implemented" end
exec_cmd(msg, cmd)
click to toggle source
# File lib/frachtraum.rb, line 37 def exec_cmd(msg, cmd) print msg Open3.popen2e(cmd) do |stdin, stdout_err, wait_thr| puts line while line = stdout_err.gets exit_status = wait_thr.value if exit_status.success? puts Rainbow("done").green else abort Rainbow("FAILED!").red + " --> #{stdout_err}" end end end
setupdisk_bsd(dev, label, password, compression, encryption, keylength, mountpoint)
click to toggle source
# File lib/frachtraum/bsd.rb, line 41 def setupdisk_bsd(dev, label, password, compression, encryption, keylength, mountpoint) # TODO password promt, confirmation question, etc.. abort "implementation not ready yet" exec_cmd "destroying previous partitioning on /dev/#{dev}...", "dd if=/dev/zero of=/dev/#{dev} bs=512 count=1" exec_cmd "creating gpart container on /dev/#{dev}...", "gpart create -s GPT #{dev}" exec_cmd "labeling /dev/#{dev} with '#{label}'...", "glabel label -v #{label} /dev/#{dev}" exec_cmd "initialising /dev/#{dev} as password protected GEOM provider with #{encryption} encryption...", "echo #{password} | geli init -s #{keylength} -e #{encryption} -J - /dev/label/#{label}" exec_cmd "attaching /dev/label/#{label} as GEOM provider, creating device /dev/label/#{label}.eli...", "echo #{password} | geli attach -d -j - /dev/label/#{label}" exec_cmd "creating zpool #{mountpoint}/#{label} on encrypted device /dev/label/#{label}.eli...", "zpool create -m #{mountpoint}/#{label} #{label} /dev/label/#{label}.eli" exec_cmd "setting compression '#{compression}' for new zfs on #{mountpoint}/#{label}...", "zfs set compression=#{compression} #{label}" exec_cmd "setting permissions...", "chmod -R 775 #{mountpoint}/#{label}" puts "setup finished" end
setupdisk_linux(dev, label, password, compression, encryption, keylength, mountpoint)
click to toggle source
# File lib/frachtraum/linux.rb, line 10 def setupdisk_linux(dev, label, password, compression, encryption, keylength, mountpoint) # TODO abort "not yet implemented" end
setupdisk_osx(dev, label, password, compression, encryption, keylength, mountpoint)
click to toggle source
# File lib/frachtraum/osx.rb, line 16 def setupdisk_osx(dev, label, password, compression, encryption, keylength, mountpoint) # TODO abort "not yet implemented" end
Private Instance Methods
attach(password, volume=nil)
click to toggle source
# File lib/frachtraum.rb, line 73 def attach(password, volume=nil) case RUBY_PLATFORM when /bsd/ then attach_bsd password, volume when /linux/ then attach_linux password, volume #when /darwin/ then attach_osx password, volume else abort "OS not supported" end end
capacity()
click to toggle source
# File lib/frachtraum.rb, line 83 def capacity() total_used = 0 total_avail = 0 Frachtraum::VOLUMES.each do |volume| used = %x( zfs get -o value -Hp used #{volume} 2>&1 ) avail = %x( zfs get -o value -Hp available #{volume} 2>&1 ) total_used += (used =="" ? 0 : used).to_i # / 1000 # 1024 total_avail += (avail=="" ? 0 : avail).to_i # / 1000 # 1024 end total = total_used + total_avail return {:total => total, :avail => total_avail, :used => total_used} end
pretty_IEC_bytes(bytes)
click to toggle source
# File lib/frachtraum.rb, line 64 def pretty_IEC_bytes(bytes) return "%.1f TiB" % (bytes.to_f / BYTES_IN_TiB) if bytes > BYTES_IN_TiB return "%.1f GiB" % (bytes.to_f / BYTES_IN_GiB) if bytes > BYTES_IN_GiB return "%.1f MiB" % (bytes.to_f / BYTES_IN_MiB) if bytes > BYTES_IN_MiB return "%.1f KiB" % (bytes.to_f / BYTES_IN_KiB) if bytes > BYTES_IN_KiB return "#{bytes} B" end
pretty_SI_bytes(bytes)
click to toggle source
# File lib/frachtraum.rb, line 55 def pretty_SI_bytes(bytes) return "%.1f TB" % (bytes.to_f / BYTES_IN_TB) if bytes > BYTES_IN_TB return "%.1f GB" % (bytes.to_f / BYTES_IN_GB) if bytes > BYTES_IN_GB return "%.1f MB" % (bytes.to_f / BYTES_IN_MB) if bytes > BYTES_IN_MB return "%.1f KB" % (bytes.to_f / BYTES_IN_KB) if bytes > BYTES_IN_KB return "#{bytes} B" end
report()
click to toggle source
# File lib/frachtraum.rb, line 100 def report() report_table = {} reported_values = [:used,:available,:compression,:compressratio] (Frachtraum::VOLUMES + Frachtraum::TIMEMACHINE_TARGETS).each do |dataset| volume_info = {} # fetch the values if zfs_volume_exists?(dataset) reported_values.each do |repval| volume_info[repval] = %x( zfs get -o value -Hp #{repval.to_s} #{dataset} ) end else reported_values.each {|repval| volume_info[repval] = "N/A" } end # calculate a total size for each volume volume_info[:total] = if volume_info[:used]=="N/A" || volume_info[:available]=="N/A" "N/A" else (volume_info[:used].to_i + volume_info[:available].to_i) end volume_info[:usage] = if volume_info[:total] == 0 "0 %" elsif volume_info[:used]=="N/A" || volume_info[:total]=="N/A" "N/A" elsif volume_info[:available].to_i == 0 "100 %" else (100 * volume_info[:used].to_f / volume_info[:total].to_f ).to_i.to_s + " %" end report_table[dataset] = volume_info end return report_table end
run_system_test()
click to toggle source
# File lib/frachtraum.rb, line 173 def run_system_test() tool_list = [] case RUBY_PLATFORM when /bsd/ then tool_list = REQUIRED_TOOLS_BSD when /linux/ then tool_list = REQUIRED_TOOLS_LINUX #when /darwin/ then tool_list = REQUIRED_TOOLS_OSX else abort "OS not supported" end tool_list.each { |tool| find_executable tool } # find_executable seems to create such file in case executable is not found File.delete 'mkmf.log' if File.exists?('mkmf.log') end
setupdisk(dev, label, password, compression, encryption, keylength, mountpoint)
click to toggle source
# File lib/frachtraum.rb, line 144 def setupdisk(dev, label, password, compression, encryption, keylength, mountpoint) abort "untested procedure -- won't continue" case RUBY_PLATFORM when /bsd/ then setupdisk_bsd dev, label, password, compression, encryption, keylength, mountpoint when /linux/ then setupdisk_linux dev, label, password, compression, encryption, keylength, mountpoint #when /darwin/ then setupdisk_osx dev, label, password, compression, encryption, keylength, mountpoint else abort "OS not supported" end end
sweep(volume)
click to toggle source
# File lib/frachtraum.rb, line 157 def sweep(volume) target_volumes = volume.nil? ? Frachtraum::VOLUMES : volume # TODO abort "sweeping not supported yet" target_volumes.each do |volume| if zfs_volume_exists?(volume) # TODO end end end
zfs_volume_exists?(dataset)
click to toggle source
# File lib/frachtraum.rb, line 190 def zfs_volume_exists?(dataset) output = %x( zfs get -H mounted #{dataset} 2>&1 ) case output when /yes/ return true when /dataset does not exist/, /permission denied/ return false else abort "can't handle output of zfs_volume_exists?: #{output}" end end