di-ruby-lvm 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -0,0 +1,14 @@
1
+ === 0.1.1 / 2008-07-21
2
+
3
+ * 1 major enhancement
4
+ * A complete rewrite! We won't bother attempting to wrap complex lvm
5
+ operations, but instead provide LVM.raw() command. The wrapper now focuses
6
+ purely on translating lvm lv/vg/pv data into the most useful ruby objects
7
+ possible. The arguments passed to the underlying binaries have been broken
8
+ out into a ruby-lvm-attributes package.
9
+
10
+ === 0.0.1 / 2008-05-28
11
+
12
+ * 1 major enhancement
13
+ * Birthday!
14
+ * Test release.
@@ -0,0 +1,28 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ Todo.txt
6
+ examples/create_snapshot.rb
7
+ examples/error_handling.rb
8
+ examples/show_lvm_config.rb
9
+ lib/lvm.rb
10
+ lib/lvm/external.rb
11
+ lib/lvm/logical_volume.rb
12
+ lib/lvm/logical_volume_segment.rb
13
+ lib/lvm/logical_volumes.rb
14
+ lib/lvm/physical_volume.rb
15
+ lib/lvm/physical_volume_segment.rb
16
+ lib/lvm/physical_volumes.rb
17
+ lib/lvm/userland.rb
18
+ lib/lvm/volume_group.rb
19
+ lib/lvm/volume_groups.rb
20
+ lib/lvm/volumes.rb
21
+ lib/lvm/wrapper.rb
22
+ lib/lvm/wrapper/constants.rb
23
+ lib/lvm/wrapper/lvs.rb
24
+ lib/lvm/wrapper/lvsseg.rb
25
+ lib/lvm/wrapper/pvs.rb
26
+ lib/lvm/wrapper/pvsseg.rb
27
+ lib/lvm/wrapper/vgs.rb
28
+ test/test_lvm.rb
@@ -0,0 +1,77 @@
1
+ = ruby-lvm
2
+
3
+ * http://ruby-lvm.rubyforge.org
4
+ * mailto:mkent@magoazul.com
5
+
6
+ == DESCRIPTION:
7
+ This is a fork of the ruby-lvm gem found at git://rubyforge.org/ruby-lvm.git.
8
+ The primary difference from upstream is that it depends on
9
+ di-ruby-lvm-attributes instead of ruby-lvm-attributes. This adds support for lvm
10
+ version 2.02.66(2).
11
+
12
+
13
+ This is a wrapper for the LVM2 administration utility, lvm. Its primary
14
+ function it to convert physical volumes, logical volumes and volume groups
15
+ into easy to use ruby objects. It also provides a simple wrapper for typical
16
+ create/delete/etc operations.
17
+
18
+ Due to a lack of LVM2 api this is a best effort attempt at ruby integration but
19
+ subject to complete replacement in the future.
20
+
21
+ == FEATURES/PROBLEMS:
22
+
23
+ * Exposes all possible data from the lvs/vgs/pvs commands. Data is grouped
24
+ sensibly (I hope).
25
+ * Doesn't nicely wrap creation/deletion/etc operations, they must be created
26
+ by hand and passed as raw commands.
27
+
28
+ == SYNOPSIS:
29
+
30
+ require 'lvm'
31
+
32
+ LVM::LVM.new({:command => "/usr/bin/sudo /sbin/lvm"}) do |lvm|
33
+ puts "lvm version: #{lvm.version}\n"
34
+
35
+ lvm.volume_groups.each do |vg|
36
+ puts "vg: #{vg.name}"
37
+ end
38
+ end
39
+
40
+ == REQUIREMENTS:
41
+
42
+ * di-ruby-lvm-attributes
43
+ * popen4
44
+
45
+ == INSTALL:
46
+
47
+ * sudo gem install di-ruby-lvm
48
+
49
+ == FEEDBACK:
50
+
51
+ Please feel free to submit patches or constructive criticism, I'm still pretty
52
+ new to ruby and object oriented programming in general.
53
+
54
+ == LICENSE:
55
+
56
+ (The MIT License)
57
+
58
+ Copyright (c) 2008 Matthew Kent, Bravenet Web Services Inc.
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining
61
+ a copy of this software and associated documentation files (the
62
+ 'Software'), to deal in the Software without restriction, including
63
+ without limitation the rights to use, copy, modify, merge, publish,
64
+ distribute, sublicense, and/or sell copies of the Software, and to
65
+ permit persons to whom the Software is furnished to do so, subject to
66
+ the following conditions:
67
+
68
+ The above copyright notice and this permission notice shall be
69
+ included in all copies or substantial portions of the Software.
70
+
71
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
72
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
73
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
74
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
75
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
76
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
77
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,14 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.spec 'di-ruby-lvm' do |p|
7
+ p.developer('Greg Symons', 'gsymons@drillinginfo.com')
8
+ p.developer('Matthew Kent', 'mkent@magoazul.com')
9
+ p.extra_deps << ['open4', '>= 0.9.6']
10
+ p.extra_deps << ['di-ruby-lvm-attrib', '>= 0.0.2']
11
+ p.remote_rdoc_dir = ''
12
+ end
13
+
14
+ # vim:syntax=ruby
@@ -0,0 +1,9 @@
1
+ = to do
2
+
3
+ == 0.2.1
4
+ * basic test suite, how?
5
+
6
+ == 0.1.2
7
+ * test on more distributions!
8
+ * more documentation.
9
+ * debug mode, logger?
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Demonstration of the creation of an lvm snapshot, using sudo, and reading its
4
+ # attributes.
5
+
6
+ $: << File.dirname(__FILE__) + "/../lib"
7
+
8
+ require 'lvm'
9
+
10
+ vol = "sys.vg/tmp.lv"
11
+ snap = "demo_snap"
12
+
13
+ lvm = LVM::LVM.new(:command => "/usr/bin/sudo /sbin/lvm")
14
+
15
+ if lvm.logical_volumes[snap]
16
+ puts "#{snap} exists! Remove it"
17
+ exit(1)
18
+ end
19
+
20
+ lvm.raw("lvcreate --snapshot --size 10M --name #{snap} #{vol}")
21
+ lv = lvm.logical_volumes[snap]
22
+
23
+ out=<<msg
24
+ snapshot of #{vol}, #{snap}, created
25
+ - uuid: #{lv.uuid}
26
+ - major,minor: #{lv.kernel_major},#{lv.kernel_minor}
27
+ msg
28
+ puts out
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Demonstration of the exception handling with raw commands.
4
+
5
+ $: << File.dirname(__FILE__) + "/../lib"
6
+
7
+ require 'lvm'
8
+
9
+ lvm = LVM::LVM.new(:command => "/usr/bin/sudo /sbin/lvm")
10
+
11
+ begin
12
+ lvm.raw("--blah blah")
13
+ rescue LVM::External::ExternalFailure => error
14
+ puts "Raw operation failed with [#{error}]"
15
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # A more advanced demonstration displaying a complete overview of the current
4
+ # lvm configuration.
5
+
6
+ $: << File.dirname(__FILE__) + "/../lib"
7
+
8
+ require 'lvm'
9
+
10
+ LVM::LVM.new({:command => "/usr/bin/sudo /sbin/lvm"}) do |lvm|
11
+ puts "lvm version: #{lvm.version}\n"
12
+
13
+ puts "\nlogical view"
14
+ puts "------------"
15
+ lvm.volume_groups.each do |vg|
16
+ puts "vg: #{vg.name}"
17
+ vg.logical_volumes.each do |lv|
18
+ puts " lv: #{lv.name} #{lv.size}"
19
+ lv.segments.each do |lvseg|
20
+ puts " lvseg: #{lvseg.devices} ##{lv.segments.index(lvseg)} #{lvseg.start} - #{lvseg.finish} = #{lvseg.size}"
21
+ end
22
+ if lv.snapshot?
23
+ puts " snapshot origin: #{lv.origin}"
24
+ end
25
+ end
26
+ end
27
+
28
+ puts "\nphysical view"
29
+ puts "-------------"
30
+ lvm.volume_groups.each do |vg|
31
+ puts "vg: #{vg.name}"
32
+ vg.physical_volumes.each do |pv|
33
+ puts " pv: #{pv.name}"
34
+ pv.segments.each do |pvseg|
35
+ puts " pvseg: ##{pv.segments.index(pvseg)} #{pvseg.start} - #{pvseg.finish}"
36
+ end
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,82 @@
1
+ require 'lvm/external'
2
+ require 'lvm/userland'
3
+ require 'lvm/logical_volumes'
4
+ require 'lvm/volume_groups'
5
+ require 'lvm/physical_volumes'
6
+
7
+ module LVM
8
+ VERSION = '0.1.2'
9
+
10
+ class LVM
11
+ attr_reader :command
12
+ attr_reader :logical_volumes
13
+ attr_reader :volume_groups
14
+ attr_reader :physical_volumes
15
+
16
+ VALID_OPTIONS = [
17
+ :command,
18
+ :version,
19
+ :debug
20
+ ]
21
+
22
+ DEFAULT_COMMAND = '/sbin/lvm'
23
+
24
+ def initialize(options={})
25
+ # handy, thanks net-ssh!
26
+ invalid_options = options.keys - VALID_OPTIONS
27
+ if invalid_options.any?
28
+ raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}"
29
+ end
30
+
31
+ @command = options[:command] || DEFAULT_COMMAND
32
+
33
+ # default to loading attributes for the current version
34
+ options[:version] ||= version
35
+ options[:debug] ||= false
36
+
37
+ @logical_volumes = LogicalVolumes.new(options)
38
+ @volume_groups = VolumeGroups.new(options)
39
+ @physical_volumes = PhysicalVolumes.new(options)
40
+
41
+ if block_given?
42
+ yield self
43
+ else
44
+ return self
45
+ end
46
+ end
47
+
48
+ def raw(args)
49
+ output = []
50
+ External.cmd("#{@command} #{args}") do |line|
51
+ output << line
52
+ end
53
+ if block_given?
54
+ return output.each { |l| yield l }
55
+ else
56
+ return output.join
57
+ end
58
+ end
59
+
60
+ def version
61
+ %r{^(.*?)(-| )}.match(userland.lvm_version)[1]
62
+ end
63
+
64
+ # helper methods
65
+ def userland
66
+ userland = UserLand.new
67
+ raw('version') do |line|
68
+ case line
69
+ when %r{^\s+LVM version:\s+([0-9].*)$}
70
+ userland.lvm_version = $1
71
+ when %r{^\s+Library version:\s+([0-9].*)$}
72
+ userland.library_version = $1
73
+ when %r{^\s+Driver version:\s+([0-9].*)$}
74
+ userland.driver_version = $1
75
+ end
76
+ end
77
+
78
+ return userland
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'open4'
3
+
4
+ module LVM
5
+ module External
6
+ class ExternalFailure < RuntimeError; end
7
+
8
+ def cmd(cmd)
9
+ output = []
10
+ error = nil
11
+ stat = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
12
+ while line = stdout.gets
13
+ output << line
14
+ end
15
+ error = stderr.read.strip
16
+ end
17
+ if stat.exited?
18
+ if stat.exitstatus > 0
19
+ raise ExternalFailure, "Fatal error, `#{cmd}` returned #{stat.exitstatus} with '#{error}'"
20
+ end
21
+ elsif stat.signaled?
22
+ raise ExternalFailure, "Fatal error, `#{cmd}` got signal #{stat.termsig} and terminated"
23
+ elsif stat.stopped?
24
+ raise ExternalFailure, "Fatal error, `#{cmd}` got signal #{stat.stopsig} and is stopped"
25
+ end
26
+
27
+ if block_given?
28
+ return output.each { |l| yield l }
29
+ else
30
+ return output.join
31
+ end
32
+ end
33
+ module_function :cmd
34
+
35
+ end # module External
36
+ end # module LVM
@@ -0,0 +1,9 @@
1
+ require 'ostruct'
2
+
3
+ module LVM
4
+ class LogicalVolume < OpenStruct
5
+ # Helpers
6
+ def open?; device_open; end
7
+ def snapshot?; volume_type == :snapshot ? true : false; end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'ostruct'
2
+
3
+ module LVM
4
+ class LogicalVolumeSegment < OpenStruct; end
5
+ end
@@ -0,0 +1,37 @@
1
+ require 'lvm/volumes'
2
+ require 'lvm/wrapper/lvs'
3
+ require 'lvm/wrapper/lvsseg'
4
+
5
+ module LVM
6
+ class LogicalVolumes
7
+ include Enumerable
8
+
9
+ include Volumes
10
+ include Wrapper
11
+
12
+ def initialize(options)
13
+ @lvs = LVS.new(options)
14
+ @lvsseg = LVSSEG.new(options)
15
+ end
16
+
17
+ # Gather all information about logical volumes.
18
+ #
19
+ # See VolumeGroups.each for a better representation of LVM data.
20
+ def each
21
+ lvs = @lvs.list
22
+ lvsseg = @lvsseg.list
23
+
24
+ lvs.each do |lv|
25
+ lv.segments ||= []
26
+ lvsseg.each do |lvseg|
27
+ if lvseg.lv_uuid == lv.uuid
28
+ lv.segments << lvseg
29
+ end
30
+ end
31
+ end
32
+
33
+ return lvs.each {|l| yield l}
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,5 @@
1
+ require 'ostruct'
2
+
3
+ module LVM
4
+ class PhysicalVolume < OpenStruct; end
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'ostruct'
2
+
3
+ module LVM
4
+ class PhysicalVolumeSegment < OpenStruct; end
5
+ end
@@ -0,0 +1,37 @@
1
+ require 'lvm/volumes'
2
+ require 'lvm/wrapper/pvs'
3
+ require 'lvm/wrapper/pvsseg'
4
+
5
+ module LVM
6
+ class PhysicalVolumes
7
+ include Enumerable
8
+
9
+ include Volumes
10
+ include Wrapper
11
+
12
+ def initialize(options)
13
+ @pvs = PVS.new(options)
14
+ @pvsseg = PVSSEG.new(options)
15
+ end
16
+
17
+ # Gather all information about physical volumes.
18
+ #
19
+ # See VolumeGroups.each for a better representation of LVM data.
20
+ def each
21
+ pvs = @pvs.list
22
+ pvsseg = @pvsseg.list
23
+
24
+ pvs.each do |pv|
25
+ pv.segments ||= []
26
+ pvsseg.each do |pvseg|
27
+ if pvseg.pv_uuid == pv.uuid
28
+ pv.segments << pvseg
29
+ end
30
+ end
31
+ end
32
+
33
+ return pvs.each {|p| yield p}
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,5 @@
1
+ require 'ostruct'
2
+
3
+ module LVM
4
+ class UserLand < OpenStruct; end
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'ostruct'
2
+
3
+ module LVM
4
+ class VolumeGroup < OpenStruct; end
5
+ end
@@ -0,0 +1,46 @@
1
+ require 'lvm/volumes'
2
+ require 'lvm/logical_volumes'
3
+ require 'lvm/physical_volumes'
4
+ require 'lvm/wrapper/vgs'
5
+
6
+ module LVM
7
+ class VolumeGroups
8
+ include Enumerable
9
+
10
+ include Volumes
11
+ include Wrapper
12
+
13
+ def initialize(options)
14
+ @vgs = VGS.new(options)
15
+ @pvs = PhysicalVolumes.new(options)
16
+ @lvs = LogicalVolumes.new(options)
17
+ end
18
+
19
+ # Gather all information about volume groups and their underlying
20
+ # logical and physical volumes.
21
+ #
22
+ # This is the best representation of LVM data.
23
+ def each
24
+ vgs = @vgs.list
25
+
26
+ vgs.each do |vg|
27
+ vg.logical_volumes ||= []
28
+ @lvs.each do |lv|
29
+ if lv.vg_uuid == vg.uuid
30
+ vg.logical_volumes << lv
31
+ end
32
+ end
33
+ vg.physical_volumes ||= []
34
+ @pvs.each do |pv|
35
+ if pv.vg_uuid == vg.uuid
36
+ vg.physical_volumes << pv
37
+ end
38
+ end
39
+ end
40
+
41
+ return vgs.each {|v| yield v}
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,16 @@
1
+ module LVM
2
+ module Volumes
3
+
4
+ def [](name)
5
+ each {|o| return o if o.name == name}
6
+ return nil
7
+ end
8
+
9
+ def to_s
10
+ x = []
11
+ each {|o| x << o.name}
12
+ return x.join(" ")
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,53 @@
1
+ require 'lvm/attributes'
2
+ require 'lvm/external'
3
+ require 'lvm/wrapper/constants'
4
+
5
+ module LVM
6
+ module Wrapper
7
+ module Reporting
8
+ include Constants
9
+
10
+ # Breakdown return values into attribute => value hash suitable for
11
+ # OpenStruct
12
+ def process_line(expected_attributes, line) #:nodoc:
13
+ line.strip!
14
+ values = line.split(SEPERATOR)
15
+ # nil is easier
16
+ values.map! { |v| (v.empty?) ? nil : v }
17
+
18
+ attributes = {}
19
+ # values and expected attributes are in the same order
20
+ values.size.times do |i|
21
+ value = values[i]
22
+ attribute = expected_attributes[i]
23
+
24
+ name = attribute[:method].to_sym
25
+
26
+ # use hints for type conversion
27
+ case attribute[:type_hint]
28
+ when "String"
29
+ when "Integer"
30
+ value = value.to_i
31
+ when "Float"
32
+ value = value.to_f
33
+ end
34
+ attributes[name] = value
35
+ end
36
+
37
+ return attributes
38
+ end
39
+ module_function :process_line
40
+
41
+ def build_command(expected_attributes, base)
42
+ opts = []
43
+ expected_attributes.each do |a|
44
+ opts << a[:column]
45
+ end
46
+
47
+ return base % opts.join(",")
48
+ end
49
+ module_function :build_command
50
+
51
+ end # module Reporting
52
+ end # module Wrapper
53
+ end # module LVM
@@ -0,0 +1,11 @@
1
+ module LVM
2
+ module Wrapper
3
+ module Reporting
4
+ module Constants
5
+ SEPERATOR = '^'
6
+ BASE_ARGUMENTS = "--verbose --separator=#{SEPERATOR} --noheadings --nosuffix --units=b --unbuffered --options %s"
7
+ EMPTY = '-'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,127 @@
1
+ require 'lvm/wrapper'
2
+ require 'lvm/logical_volume'
3
+
4
+ module LVM
5
+ module Wrapper
6
+ class LVS
7
+ include Reporting
8
+
9
+ attr_reader :attributes
10
+ attr_reader :command
11
+
12
+ def initialize(options)
13
+ @attributes = Attributes.load(options[:version], ATTRIBUTES_FILE)
14
+ @command = "#{options[:command]} #{Reporting.build_command(attributes, BASE_COMMAND)}"
15
+ end
16
+
17
+ BASE_COMMAND = "lvs #{Reporting::BASE_ARGUMENTS}"
18
+ ATTRIBUTES_FILE = 'lvs.yaml'
19
+
20
+ # lv_attr attribute handling constants
21
+ # roughly by order referenced in lib/report/report.c:292 (_lvstatus_disp)
22
+ #
23
+ VOLUME_TYPE = {
24
+ 'p' => :pvmove,
25
+ 'c' => :conversion,
26
+ 'M' => :mirror_not_synced,
27
+ 'm' => :mirror,
28
+ 'i' => :mirror_image,
29
+ 'I' => :mirror_image_not_synced,
30
+ 'l' => :mirror_log,
31
+ 'v' => :virtual,
32
+ 'o' => :origin,
33
+ 's' => :snapshot,
34
+ 'S' => :invalid_snapshot,
35
+ # custom, empty is a standard volume
36
+ '-' => :normal
37
+ }
38
+ PERMISSIONS = {
39
+ 'w' => :writeable,
40
+ 'r' => :readonly,
41
+ # custom, from reading source
42
+ '-' => :locked_by_pvmove,
43
+ }
44
+ ALLOCATION_POLICY = {
45
+ 'c' => :contiguous,
46
+ 'l' => :cling,
47
+ 'n' => :normal,
48
+ 'a' => :anywhere,
49
+ 'i' => :inherited,
50
+ 'C' => :contiguous_locked,
51
+ 'L' => :cling_locked,
52
+ 'N' => :normal_locked,
53
+ 'A' => :anywhere_locked,
54
+ 'I' => :inherited_locked
55
+ }
56
+ FIXED_MINOR = {
57
+ # code says its a boolean
58
+ 'm' => true
59
+ }
60
+ STATE = {
61
+ 's' => :suspended,
62
+ 'a' => :active,
63
+ 'i' => :inactive_with_table,
64
+ 'd' => :inactive_without_table,
65
+ 'S' => :suspended_snapshot,
66
+ 'I' => :invalid_snapshot
67
+ }
68
+ DEVICE_OPEN = {
69
+ # code says its a boolean
70
+ 'o' => true
71
+ }
72
+
73
+ def list
74
+ output = External.cmd(@command)
75
+ data = parse(output)
76
+ if block_given?
77
+ return data.each { |obj| yield obj }
78
+ else
79
+ return data
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def parse_lv_attr(lv_attr) #:nodoc:
86
+ translated = {}
87
+ # translate them into nice symbols and a couple booleans
88
+ translated[:volume_type] = VOLUME_TYPE[lv_attr[0].chr]
89
+ translated[:permissions] = PERMISSIONS[lv_attr[1].chr]
90
+ translated[:allocation_policy] = ALLOCATION_POLICY[lv_attr[2].chr]
91
+ translated[:fixed_minor] = FIXED_MINOR[lv_attr[3].chr] ? true : false
92
+ translated[:state] = STATE[lv_attr[4].chr]
93
+ translated[:device_open] = DEVICE_OPEN[lv_attr[5].chr] ? true : false
94
+
95
+ return translated
96
+ end
97
+
98
+ # Parses the output of self.command
99
+ def parse(output) #:nodoc:
100
+ volumes = []
101
+
102
+ output.split("\n").each do |line|
103
+ args = Reporting.process_line(attributes, line)
104
+
105
+ # now we force some types to ints since we've requested them as bytes
106
+ # without a suffix
107
+ args[:size] = args[:size].to_i
108
+
109
+ # we resolve the attributes line to nicer symbols
110
+ args.merge!(parse_lv_attr(args[:attr]))
111
+
112
+ # finally build our object
113
+ volume = LogicalVolume.new(args)
114
+
115
+ if block_given?
116
+ yield volume
117
+ else
118
+ volumes << volume
119
+ end
120
+ end
121
+
122
+ return volumes
123
+ end # parse
124
+
125
+ end # class LVS
126
+ end # module Wrapper
127
+ end # module LVM
@@ -0,0 +1,59 @@
1
+ require 'lvm/wrapper'
2
+ require 'lvm/logical_volume_segment'
3
+
4
+ module LVM
5
+ module Wrapper
6
+ # segment output is very different in that its multi line, easier to treat as own command
7
+ class LVSSEG
8
+ include Reporting
9
+
10
+ attr_reader :attributes
11
+ attr_reader :command
12
+
13
+ def initialize(options)
14
+ @attributes = Attributes.load(options[:version], ATTRIBUTES_FILE)
15
+ @command = "#{options[:command]} #{Reporting.build_command(attributes, BASE_COMMAND)}"
16
+ end
17
+
18
+ BASE_COMMAND = "lvs #{Reporting::BASE_ARGUMENTS}"
19
+ ATTRIBUTES_FILE = 'lvsseg.yaml'
20
+
21
+ def list
22
+ output = External.cmd(@command)
23
+ data = parse(output)
24
+ if block_given?
25
+ return data.each { |obj| yield obj }
26
+ else
27
+ return data
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Parses the output of self.command
34
+ def parse(output)
35
+ volumes = []
36
+
37
+ output.split("\n").each do |line|
38
+ args = process_line(attributes, line)
39
+
40
+ args[:finish] = args[:start] + args[:size]
41
+
42
+ # finally build our object
43
+ volume = LogicalVolumeSegment.new(args)
44
+
45
+ if block_given?
46
+ yield volume
47
+ else
48
+ volumes << volume
49
+ end
50
+ end
51
+
52
+ return volumes
53
+ end # parse
54
+
55
+ end # class LVSSEG
56
+ end # module Wrapper
57
+ end # module LVM
58
+
59
+
@@ -0,0 +1,84 @@
1
+ require 'lvm/wrapper'
2
+ require 'lvm/physical_volume'
3
+
4
+ module LVM
5
+ module Wrapper
6
+ class PVS
7
+ include Reporting
8
+
9
+ attr_reader :attributes
10
+ attr_reader :command
11
+
12
+ def initialize(options)
13
+ @attributes = Attributes.load(options[:version], ATTRIBUTES_FILE)
14
+ @command = "#{options[:command]} #{Reporting.build_command(attributes, BASE_COMMAND)}"
15
+ end
16
+
17
+ BASE_COMMAND = "pvs #{Reporting::BASE_ARGUMENTS}"
18
+ ATTRIBUTES_FILE = 'pvs.yaml'
19
+
20
+ # pv_attr attribute handling constants
21
+ # roughly by order referenced in lib/report/report.c:360 (_pvstatus_disp)
22
+ #
23
+ ALLOCATABLE = {
24
+ # code says its a boolean
25
+ 'a' => true
26
+ }
27
+ EXPORTED = {
28
+ # code says its a boolean
29
+ 'x' => true
30
+ }
31
+
32
+ def list
33
+ output = External.cmd(@command)
34
+ data = parse(output)
35
+ if block_given?
36
+ return data.each { |obj| yield obj }
37
+ else
38
+ return data
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def parse_pv_attr(pv_attr) #:nodoc:
45
+ translated = {}
46
+ # translate them into nice symbols and a couple booleans
47
+ translated[:allocatable] = ALLOCATABLE[pv_attr[0].chr] ? true : false
48
+ translated[:exported] = EXPORTED[pv_attr[1].chr] ? true : false
49
+
50
+ return translated
51
+ end
52
+
53
+ # Parses the output of self.command
54
+ def parse(output)
55
+ volumes = []
56
+
57
+ output.split("\n").each do |line|
58
+ args = process_line(attributes, line)
59
+
60
+ # now we force some types to ints since we've requested them as bytes
61
+ # without a suffix
62
+ args[:size] = args[:size].to_i
63
+
64
+ # we resolve the attributes line to nicer symbols
65
+ args.merge!(parse_pv_attr(args[:attr]))
66
+
67
+ # finally build our object
68
+ volume = PhysicalVolume.new(args)
69
+
70
+ if block_given?
71
+ yield volume
72
+ else
73
+ volumes << volume
74
+ end
75
+ end
76
+
77
+ return volumes
78
+ end # parse
79
+
80
+ end # class PVS
81
+ end # module Wrapper
82
+ end # module LVM
83
+
84
+
@@ -0,0 +1,57 @@
1
+ require 'lvm/wrapper'
2
+ require 'lvm/physical_volume_segment'
3
+
4
+ module LVM
5
+ module Wrapper
6
+ # segment output is very different in that its multi line, easier to treat as own command
7
+ class PVSSEG
8
+ include Reporting
9
+
10
+ attr_reader :attributes
11
+ attr_reader :command
12
+
13
+ def initialize(options)
14
+ @attributes = Attributes.load(options[:version], ATTRIBUTES_FILE)
15
+ @command = "#{options[:command]} #{Reporting.build_command(attributes, BASE_COMMAND)}"
16
+ end
17
+
18
+ BASE_COMMAND = "pvs #{Reporting::BASE_ARGUMENTS}"
19
+ ATTRIBUTES_FILE = 'pvsseg.yaml'
20
+
21
+ def list
22
+ output = External.cmd(@command)
23
+ data = parse(output)
24
+ if block_given?
25
+ return data.each { |obj| yield obj }
26
+ else
27
+ return data
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Parses the output of self.command
34
+ def parse(output)
35
+ volumes = []
36
+
37
+ output.split("\n").each do |line|
38
+ args = process_line(attributes, line)
39
+
40
+ args[:finish] = args[:start] + args[:size]
41
+
42
+ # finally build our object
43
+ volume = PhysicalVolumeSegment.new(args)
44
+
45
+ if block_given?
46
+ yield volume
47
+ else
48
+ volumes << volume
49
+ end
50
+ end
51
+
52
+ return volumes
53
+ end # parse
54
+
55
+ end # class PVSSEG
56
+ end # module Wrapper
57
+ end # module LVM
@@ -0,0 +1,112 @@
1
+ require 'lvm/wrapper'
2
+ require 'lvm/volume_group'
3
+
4
+ module LVM
5
+ module Wrapper
6
+ class VGS
7
+ include Reporting
8
+
9
+ attr_reader :attributes
10
+ attr_reader :command
11
+
12
+ def initialize(options)
13
+ @attributes = Attributes.load(options[:version], ATTRIBUTES_FILE)
14
+ @command = "#{options[:command]} #{Reporting.build_command(attributes, BASE_COMMAND)}"
15
+ end
16
+
17
+ BASE_COMMAND = "vgs #{Reporting::BASE_ARGUMENTS}"
18
+ ATTRIBUTES_FILE = 'vgs.yaml'
19
+
20
+ # vg_attr attribute handling constants
21
+ # roughly by order referenced in lib/report/report.c:360 (_vgstatus_disp)
22
+ #
23
+ PERMISSIONS = {
24
+ 'w' => :writeable,
25
+ 'r' => :readonly,
26
+ }
27
+ RESIZEABLE = {
28
+ # code says its a boolean
29
+ 'z' => true
30
+ }
31
+ EXPORTED = {
32
+ # code says its a boolean
33
+ 'x' => true
34
+ }
35
+ PARTIAL = {
36
+ # code says its a boolean
37
+ 'p' => true
38
+ }
39
+ ALLOCATION_POLICY = {
40
+ 'c' => :contiguous,
41
+ 'l' => :cling,
42
+ 'n' => :normal,
43
+ 'a' => :anywhere,
44
+ 'i' => :inherited,
45
+ 'C' => :contiguous_locked,
46
+ 'L' => :cling_locked,
47
+ 'N' => :normal_locked,
48
+ 'A' => :anywhere_locked,
49
+ 'I' => :inherited_locked
50
+ }
51
+ CLUSTERED = {
52
+ # code says its a boolean
53
+ 'c' => true
54
+ }
55
+
56
+ def list
57
+ output = External.cmd(@command)
58
+ data = parse(output)
59
+ if block_given?
60
+ return data.each { |obj| yield obj }
61
+ else
62
+ return data
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def parse_vg_attr(vg_attr) #:nodoc:
69
+ translated = {}
70
+ # translate them into nice symbols and a couple booleans
71
+ translated[:permissions] = PERMISSIONS[vg_attr[0].chr]
72
+ translated[:resizeable] = RESIZEABLE[vg_attr[1].chr] ? true : false
73
+ translated[:exported] = EXPORTED[vg_attr[2].chr] ? true : false
74
+ translated[:partial] = PARTIAL[vg_attr[3].chr] ? true : false
75
+ translated[:allocation_policy] = ALLOCATION_POLICY[vg_attr[4].chr]
76
+ translated[:clustered] = CLUSTERED[vg_attr[5].chr] ? true : false
77
+
78
+ return translated
79
+ end
80
+
81
+ # Parses the output of self.command
82
+ def parse(output) #:nodoc:
83
+ volumes = []
84
+
85
+ output.split("\n").each do |line|
86
+ args = process_line(attributes, line)
87
+
88
+ # now we force some types to ints since we've requested them as bytes
89
+ # without a suffix
90
+ args[:size] = args[:size].to_i
91
+
92
+ # we resolve the attributes line to nicer symbols
93
+ args.merge!(parse_vg_attr(args[:attr]))
94
+
95
+ # finally build our object
96
+ volume = VolumeGroup.new(args)
97
+
98
+ if block_given?
99
+ yield volume
100
+ else
101
+ volumes << volume
102
+ end
103
+ end
104
+
105
+ return volumes
106
+ end # parse
107
+
108
+ end # class VGS
109
+ end # module Wrapper
110
+ end # module LVM
111
+
112
+
File without changes
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: di-ruby-lvm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Greg Symons
9
+ - Matthew Kent
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-06-05 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: open4
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 0.9.6
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 0.9.6
31
+ - !ruby/object:Gem::Dependency
32
+ name: di-ruby-lvm-attrib
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: 0.0.2
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 0.0.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: rdoc
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.10'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '3.10'
63
+ - !ruby/object:Gem::Dependency
64
+ name: hoe
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: '3.0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: '3.0'
79
+ description: ! 'This is a fork of the ruby-lvm gem found at git://rubyforge.org/ruby-lvm.git.
80
+
81
+ The primary difference from upstream is that it depends on
82
+
83
+ di-ruby-lvm-attributes instead of ruby-lvm-attributes. This adds support for lvm
84
+
85
+ version 2.02.66(2).
86
+
87
+
88
+
89
+ This is a wrapper for the LVM2 administration utility, lvm. Its primary
90
+
91
+ function it to convert physical volumes, logical volumes and volume groups
92
+
93
+ into easy to use ruby objects. It also provides a simple wrapper for typical
94
+
95
+ create/delete/etc operations.
96
+
97
+
98
+ Due to a lack of LVM2 api this is a best effort attempt at ruby integration but
99
+
100
+ subject to complete replacement in the future.'
101
+ email:
102
+ - gsymons@drillinginfo.com
103
+ - mkent@magoazul.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files:
107
+ - History.txt
108
+ - Manifest.txt
109
+ - README.txt
110
+ - Todo.txt
111
+ files:
112
+ - History.txt
113
+ - Manifest.txt
114
+ - README.txt
115
+ - Rakefile
116
+ - Todo.txt
117
+ - examples/create_snapshot.rb
118
+ - examples/error_handling.rb
119
+ - examples/show_lvm_config.rb
120
+ - lib/lvm.rb
121
+ - lib/lvm/external.rb
122
+ - lib/lvm/logical_volume.rb
123
+ - lib/lvm/logical_volume_segment.rb
124
+ - lib/lvm/logical_volumes.rb
125
+ - lib/lvm/physical_volume.rb
126
+ - lib/lvm/physical_volume_segment.rb
127
+ - lib/lvm/physical_volumes.rb
128
+ - lib/lvm/userland.rb
129
+ - lib/lvm/volume_group.rb
130
+ - lib/lvm/volume_groups.rb
131
+ - lib/lvm/volumes.rb
132
+ - lib/lvm/wrapper.rb
133
+ - lib/lvm/wrapper/constants.rb
134
+ - lib/lvm/wrapper/lvs.rb
135
+ - lib/lvm/wrapper/lvsseg.rb
136
+ - lib/lvm/wrapper/pvs.rb
137
+ - lib/lvm/wrapper/pvsseg.rb
138
+ - lib/lvm/wrapper/vgs.rb
139
+ - test/test_lvm.rb
140
+ - .gemtest
141
+ homepage: http://ruby-lvm.rubyforge.org
142
+ licenses: []
143
+ post_install_message:
144
+ rdoc_options:
145
+ - --main
146
+ - README.txt
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project: di-ruby-lvm
163
+ rubygems_version: 1.8.24
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: This is a fork of the ruby-lvm gem found at git://rubyforge.org/ruby-lvm.git
167
+ test_files:
168
+ - test/test_lvm.rb