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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +184 -0
- data/Rakefile +1 -0
- data/assets/index.html +320 -0
- data/bin/vv +8 -0
- data/example/data +1018 -0
- data/example/index.html +320 -0
- data/example/screenshot.jpg +0 -0
- data/example/screenshot_scaled.jpg +0 -0
- data/example/volviz.json +1 -0
- data/lib/volume_visualizer.rb +8 -0
- data/lib/volume_visualizer/cli.rb +165 -0
- data/lib/volume_visualizer/data_size_string.rb +26 -0
- data/lib/volume_visualizer/version.rb +3 -0
- data/lib/volume_visualizer/zfs.rb +12 -0
- data/lib/volume_visualizer/zfs/base.rb +54 -0
- data/lib/volume_visualizer/zfs/filesystem.rb +75 -0
- data/lib/volume_visualizer/zfs/pool.rb +26 -0
- data/volume_visualizer.gemspec +26 -0
- metadata +122 -0
@@ -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,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: []
|