volume_visualizer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,26 @@
1
+ module VolumeVisualizer
2
+ class DataSizeString < String
3
+ ABBREV_MAP = {
4
+ "B" => 1024**0,
5
+ "K" => 1024**1,
6
+ "M" => 1024**2,
7
+ "G" => 1024**3,
8
+ "T" => 1024**4,
9
+ "P" => 1024**5,
10
+ "E" => 1024**6,
11
+ "Z" => 1024**7
12
+ }
13
+
14
+ def last_char
15
+ to_s[length - 1]
16
+ end
17
+
18
+ def multiplier
19
+ ABBREV_MAP[last_char] || 1
20
+ end
21
+
22
+ def bytes
23
+ (to_f * multiplier).to_i
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module VolumeVisualizer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ module VolumeVisualizer
2
+ module ZFS
3
+ ATTRS = [ :name, :available, :used, :referenced, :used_by_snapshots,
4
+ :used_by_dataset, :used_by_children, :compress_ratio, :type ]
5
+ NON_BYTE_ATTRS = [ :name, :compress_ratio, :type ]
6
+ end
7
+ end
8
+
9
+ require 'volume_visualizer/zfs/base'
10
+ require 'volume_visualizer/zfs/pool'
11
+ require 'volume_visualizer/zfs/filesystem'
12
+
@@ -0,0 +1,54 @@
1
+ module VolumeVisualizer
2
+ module ZFS
3
+ class Base
4
+ attr_reader :filesystems, :root, :name
5
+
6
+ def initialize(name, data)
7
+ @name = name || "unknown volume"
8
+ @filesystems = {}
9
+
10
+ data.each do |line|
11
+ line.chomp!
12
+ fs = ZFS::Filesystem.new(line)
13
+ next if fs.snapshot? && fs.zero?
14
+ if filesystems.empty?
15
+ @root = fs
16
+ else
17
+ parent = filesystems[ fs.parent_name ]
18
+ fs.parent = parent
19
+ parent.children << fs
20
+ end
21
+ filesystems[fs.name] = fs
22
+ end
23
+ end
24
+
25
+ def walk(nodes = [ root ], &block)
26
+ nodes.each do |node|
27
+ yield node
28
+ walk node.children, &block
29
+ end
30
+ end
31
+
32
+ def to_h
33
+ {
34
+ :name => name,
35
+ :type => :root,
36
+ :children => [
37
+ {
38
+ :name => "free space",
39
+ :size => root.available.bytes,
40
+ :size_human => root.available,
41
+ :type => "free"
42
+ },
43
+ root.to_h
44
+ ]
45
+ }
46
+ end
47
+
48
+ def to_json
49
+ to_h.to_json(:max_nesting => 50)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,75 @@
1
+ module VolumeVisualizer
2
+ module ZFS
3
+ class Filesystem
4
+ attr_accessor *ATTRS
5
+ attr_accessor :children, :parent
6
+
7
+ def initialize(string)
8
+ @children = []
9
+
10
+ params = string.split("\t")
11
+ ATTRS.each do |attr|
12
+ val = params.shift
13
+ unless NON_BYTE_ATTRS.include? attr
14
+ val = DataSizeString.new(val)
15
+ end
16
+ instance_variable_set "@#{attr.to_s}", val
17
+ end
18
+ end
19
+
20
+ def depth
21
+ depth = name.split("/").size
22
+ depth -= 1 unless snapshot?
23
+ depth
24
+ end
25
+
26
+ def parent_name
27
+ if snapshot?
28
+ name.split("@").first
29
+ else
30
+ File.dirname(name)
31
+ end
32
+ end
33
+
34
+ def snapshot?
35
+ type == "snapshot"
36
+ end
37
+
38
+ def zero?
39
+ used.bytes == 0
40
+ end
41
+
42
+ def dump
43
+ ATTRS.each do |attr|
44
+ puts "%18s %s" % [attr, self.send(attr)]
45
+ end
46
+ end
47
+
48
+ def to_h
49
+ hash = {
50
+ :name => name,
51
+ :type => type,
52
+ :size => used.bytes,
53
+ :size_human => used,
54
+ :type => type,
55
+ }
56
+ unless children.empty?
57
+ hash[:children] = [
58
+ {
59
+ :name => name + " (data)",
60
+ :type => "filesystem",
61
+ :size => referenced.bytes,
62
+ :size_human => referenced
63
+ }
64
+ ]
65
+ hash[:type] = "container"
66
+ children.each do |child|
67
+ hash[:children] << child.to_h
68
+ end
69
+ end
70
+
71
+ hash
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,26 @@
1
+ module VolumeVisualizer
2
+ module ZFS
3
+ class Pool
4
+ attr_reader :pool_name
5
+
6
+ def self.query_command(pool_name = "tank")
7
+ attrs = ATTRS.collect { |a| a.to_s.gsub("_","") }.join(",")
8
+ command = "zfs list -t all -H -r -o #{attrs} #{pool_name}"
9
+ if ENV["USER"] != "root"
10
+ command = "sudo " + command
11
+ else
12
+ command
13
+ end
14
+ end
15
+
16
+ def initialize(pool_name)
17
+ @pool_name = pool_name
18
+ end
19
+
20
+ def data
21
+ STDERR.puts "reading ZFS data"
22
+ File.popen(Pool.query_command pool_name).readlines
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'volume_visualizer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "volume_visualizer"
8
+ spec.version = VolumeVisualizer::VERSION
9
+ spec.authors = ["Rick Lee-Morlang"]
10
+ spec.email = ["<rick@lee-morlang.com>"]
11
+ spec.summary = %q{Visualize data distribution in your storage volumes.}
12
+ #spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = "https://github.com/rleemorlang/volume_visualizer"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency "thor"
25
+ spec.add_dependency "json"
26
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: volume_visualizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rick Lee-Morlang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - <rick@lee-morlang.com>
72
+ executables:
73
+ - vv
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - assets/index.html
83
+ - bin/vv
84
+ - example/data
85
+ - example/index.html
86
+ - example/screenshot.jpg
87
+ - example/screenshot_scaled.jpg
88
+ - example/volviz.json
89
+ - lib/volume_visualizer.rb
90
+ - lib/volume_visualizer/cli.rb
91
+ - lib/volume_visualizer/data_size_string.rb
92
+ - lib/volume_visualizer/version.rb
93
+ - lib/volume_visualizer/zfs.rb
94
+ - lib/volume_visualizer/zfs/base.rb
95
+ - lib/volume_visualizer/zfs/filesystem.rb
96
+ - lib/volume_visualizer/zfs/pool.rb
97
+ - volume_visualizer.gemspec
98
+ homepage: https://github.com/rleemorlang/volume_visualizer
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.2.2
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Visualize data distribution in your storage volumes.
122
+ test_files: []