ruby-lvm 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +10 -2
  3. data/Manifest.txt +18 -17
  4. data/README.txt +22 -9
  5. data/Rakefile +3 -2
  6. data/Todo.txt +7 -8
  7. data/examples/create_snapshot.rb +20 -8
  8. data/examples/error_handling.rb +8 -2
  9. data/examples/show_lvm_config.rb +40 -0
  10. data/lib/lvm.rb +67 -24
  11. data/lib/lvm/external.rb +25 -30
  12. data/lib/lvm/logical_volume.rb +9 -0
  13. data/lib/lvm/logical_volume_segment.rb +5 -0
  14. data/lib/lvm/logical_volumes.rb +37 -0
  15. data/lib/lvm/physical_volume.rb +5 -0
  16. data/lib/lvm/physical_volume_segment.rb +5 -0
  17. data/lib/lvm/physical_volumes.rb +37 -0
  18. data/lib/lvm/userland.rb +5 -0
  19. data/lib/lvm/volume_group.rb +5 -0
  20. data/lib/lvm/volume_groups.rb +46 -0
  21. data/lib/lvm/volumes.rb +16 -0
  22. data/lib/lvm/wrapper.rb +53 -0
  23. data/lib/lvm/wrapper/constants.rb +11 -0
  24. data/lib/lvm/wrapper/lvs.rb +127 -0
  25. data/lib/lvm/wrapper/lvsseg.rb +59 -0
  26. data/lib/lvm/wrapper/pvs.rb +84 -0
  27. data/lib/lvm/wrapper/pvsseg.rb +57 -0
  28. data/lib/lvm/wrapper/vgs.rb +112 -0
  29. metadata +109 -90
  30. metadata.gz.sig +0 -0
  31. data/examples/show_volumes.rb +0 -26
  32. data/helpers/generate_field_data.rb +0 -117
  33. data/lib/lvm/attrib/lvs.yaml +0 -88
  34. data/lib/lvm/attrib/pvs.yaml +0 -46
  35. data/lib/lvm/attrib/vgs.yaml +0 -55
  36. data/lib/lvm/lv.rb +0 -19
  37. data/lib/lvm/lvmanager.rb +0 -95
  38. data/lib/lvm/lvs.rb +0 -143
  39. data/lib/lvm/lvseg.rb +0 -14
  40. data/lib/lvm/proc.rb +0 -39
  41. data/lib/lvm/pv.rb +0 -15
  42. data/lib/lvm/pvmanager.rb +0 -22
  43. data/lib/lvm/pvs.rb +0 -109
  44. data/lib/lvm/pvseg.rb +0 -14
  45. data/lib/lvm/vg.rb +0 -15
  46. data/lib/lvm/vgmanager.rb +0 -68
  47. data/lib/lvm/vgs.rb +0 -123
data.tar.gz.sig CHANGED
Binary file
@@ -1,6 +1,14 @@
1
- === 0.0.1 / 2008-05-28
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.
2
9
 
3
- * Initial release
10
+ === 0.0.1 / 2008-05-28
4
11
 
12
+ * 1 major enhancement
5
13
  * Birthday!
6
14
  * Test release.
@@ -5,23 +5,24 @@ Rakefile
5
5
  Todo.txt
6
6
  examples/create_snapshot.rb
7
7
  examples/error_handling.rb
8
- examples/show_volumes.rb
9
- helpers/generate_field_data.rb
8
+ examples/show_lvm_config.rb
10
9
  lib/lvm.rb
11
- lib/lvm/attrib/lvs.yaml
12
- lib/lvm/attrib/pvs.yaml
13
- lib/lvm/attrib/vgs.yaml
14
10
  lib/lvm/external.rb
15
- lib/lvm/lv.rb
16
- lib/lvm/lvmanager.rb
17
- lib/lvm/lvs.rb
18
- lib/lvm/lvseg.rb
19
- lib/lvm/proc.rb
20
- lib/lvm/pv.rb
21
- lib/lvm/pvmanager.rb
22
- lib/lvm/pvs.rb
23
- lib/lvm/pvseg.rb
24
- lib/lvm/vg.rb
25
- lib/lvm/vgmanager.rb
26
- lib/lvm/vgs.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
27
28
  test/test_lvm.rb
data/README.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  = ruby-lvm
2
2
 
3
3
  * http://ruby-lvm.rubyforge.org
4
- * mailto:matt@bravenet.com
4
+ * mailto:mkent@magoazul.com
5
5
 
6
6
  == DESCRIPTION:
7
7
 
@@ -10,29 +10,42 @@ function it to convert physical volumes, logical volumes and volume groups
10
10
  into easy to use ruby objects. It also provides a simple wrapper for typical
11
11
  create/delete/etc operations.
12
12
 
13
- Unfortunately due to it's lack of a proper api this is as good as it gets for
14
- ruby integration for the forseeable future.
15
-
16
- See this thread
17
- http://www.redhat.com/archives/libvir-list/2007-March/msg00192.html for a
18
- similar discussion.
13
+ Due to a lack of LVM2 api this is a best effort attempt at ruby integration but
14
+ subject to complete replacement in the future.
19
15
 
20
16
  == FEATURES/PROBLEMS:
21
17
 
22
- * Not finished, is that a problem?
18
+ * Exposes all possible data from the lvs/vgs/pvs commands. Data is grouped
19
+ sensibly (I hope).
20
+ * Doesn't nicely wrap creation/deletion/etc operations, they must be created
21
+ by hand and passed as raw commands.
23
22
 
24
23
  == SYNOPSIS:
25
24
 
26
- FIX (code sample of usage)
25
+ require 'lvm'
26
+
27
+ LVM::LVM.new({:command => "/usr/bin/sudo /sbin/lvm"}) do |lvm|
28
+ puts "lvm version: #{lvm.version}\n"
29
+
30
+ lvm.volume_groups.each do |vg|
31
+ puts "vg: #{vg.name}"
32
+ end
33
+ end
27
34
 
28
35
  == REQUIREMENTS:
29
36
 
37
+ * ruby-lvm-attributes
30
38
  * popen4
31
39
 
32
40
  == INSTALL:
33
41
 
34
42
  * sudo gem install ruby-lvm
35
43
 
44
+ == FEEDBACK:
45
+
46
+ Please feel free to submit patches or constructive criticism, I'm still pretty
47
+ new to ruby and object oriented programming in general.
48
+
36
49
  == LICENSE:
37
50
 
38
51
  (The MIT License)
data/Rakefile CHANGED
@@ -5,9 +5,10 @@ require 'hoe'
5
5
  $:.unshift(File.dirname(__FILE__) + "/lib")
6
6
  require 'lvm'
7
7
 
8
- Hoe.new('ruby-lvm', LVMWrapper::VERSION) do |p|
9
- p.developer('Matthew Kent', 'matt@bravenet.com')
8
+ Hoe.new('ruby-lvm', LVM::VERSION) do |p|
9
+ p.developer('Matthew Kent', 'mkent@magoazul.com')
10
10
  p.extra_deps << ['open4', '>= 0.9.6']
11
+ p.extra_deps << ['ruby-lvm-attrib', '>= 0.0.1']
11
12
  p.remote_rdoc_dir = ''
12
13
  end
13
14
 
data/Todo.txt CHANGED
@@ -1,10 +1,9 @@
1
1
  = to do
2
2
 
3
- == 0.1.0
4
- * improve auto generation of attributes, clean it up
5
- * don't bother wrapping lvm create/delete etc commands, too complex, just
6
- provide a standard lvm.raw('lvcreate foo'), that traps errors to do work at
7
- this level for now
8
- * proper documentation
9
- * basic test suite
10
- * compatibility check and warning, pass flag to shutup
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?
@@ -1,16 +1,28 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
+ # Demonstration of the creation of an lvm snapshot, using sudo, and reading its
4
+ # attributes.
5
+
3
6
  $: << File.dirname(__FILE__) + "/../lib"
4
7
 
5
8
  require 'lvm'
6
- require 'lvm/lvmanager'
7
- require 'lvm/pvmanager'
8
- require 'lvm/vgmanager'
9
9
 
10
- lvm = LVMWrapper::LVM.new(:command => "/usr/bin/sudo /sbin/lvm")
11
- lv = LVMWrapper::LogicalVolumeManager.new(lvm)
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
12
19
 
13
- lv.remove(:vgname => "sys.vg", :name => "demo_snap")
14
- lv.snapshot(:origin => "sys.vg/tmp.lv", :name => "demo_snap", :size => "10k")
20
+ lvm.raw("lvcreate --snapshot --size 10M --name #{snap} #{vol}")
21
+ lv = lvm.logical_volumes[snap]
15
22
 
16
- p lv.list("sys.vg/demo_snap")
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
@@ -1,9 +1,15 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
+ # Demonstration of the exception handling with raw commands.
4
+
3
5
  $: << File.dirname(__FILE__) + "/../lib"
4
6
 
5
7
  require 'lvm'
6
8
 
7
- lvm = LVMWrapper::LVM.new(:command => "/usr/bin/sudo /sbin/lvm", :debug => true)
9
+ lvm = LVM::LVM.new(:command => "/usr/bin/sudo /sbin/lvm")
8
10
 
9
- lvm.raw("--blah blah")
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
data/lib/lvm.rb CHANGED
@@ -1,39 +1,82 @@
1
1
  require 'lvm/external'
2
+ require 'lvm/userland'
3
+ require 'lvm/logical_volumes'
4
+ require 'lvm/volume_groups'
5
+ require 'lvm/physical_volumes'
2
6
 
3
- module LVMWrapper
4
- VERSION = '0.0.1'
5
- COMPAT_VERSION = '2.02.26-RHEL5'
7
+ module LVM
8
+ VERSION = '0.1.1'
6
9
 
7
10
  class LVM
8
- class LVM < Exception; end
9
-
10
- attr_accessor :command
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
+ ]
11
21
 
12
22
  DEFAULT_COMMAND = '/sbin/lvm'
13
23
 
14
- def initialize(args = {})
15
- @command = args[:command] || DEFAULT_COMMAND
16
- @debug = args[:debug] || false
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
17
46
  end
18
47
 
19
- def raw(args) #:nodoc:
20
- External.cmd(args)
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
21
58
  end
22
59
 
23
- def cmd(args)
24
- to_exec = "#{@command} #{args}"
25
- puts "Going to execute `#{to_exec}`" if @debug
26
- raw(to_exec)
60
+ def version
61
+ %r{^(.*?)(-| )}.match(userland.lvm_version)[1]
27
62
  end
28
63
 
29
- class<<self
30
- def raw(args)
31
- new(args).raw(args)
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
32
76
  end
33
- def cmd(args)
34
- new(args).raw(args)
35
- end
36
- end # self
37
77
 
38
- end # class
39
- end # module
78
+ return userland
79
+ end
80
+
81
+ end
82
+ end
@@ -1,41 +1,36 @@
1
1
  require 'rubygems'
2
2
  require 'open4'
3
3
 
4
- module LVMWrapper
5
- class External
4
+ module LVM
5
+ module External
6
6
  class ExternalFailure < RuntimeError; end
7
7
 
8
- class<<self
9
- # Execute a command, returning the resulting String of standard output.
10
- #
11
- # The block is optional. If given, it will be invoked for each line of
12
- # output.
13
- def cmd(cmd)
14
- output = []
15
- error = nil
16
- stat = Open4::popen4(cmd) do |pid, stdin, stdout, stderr|
17
- while line = stdout.gets
18
- output << line
19
- end
20
- error = stderr.read.strip
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
21
14
  end
22
- if stat.exited?
23
- if stat.exitstatus > 0
24
- raise ExternalFailure, "Fatal error, `#{cmd}` returned #{stat.exitstatus} with '#{error}'"
25
- end
26
- elsif stat.signaled?
27
- raise ExternalFailure, "Fatal error, `#{cmd}` got signal #{stat.termsig} and terminated"
28
- elsif stat.stopped?
29
- raise ExternalFailure, "Fatal error, `#{cmd}` got signal #{stat.stopsig} and is stopped"
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}'"
30
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
31
26
 
32
- if block_given?
33
- return output.each { |l| yield l }
34
- else
35
- return output.join
36
- end
27
+ if block_given?
28
+ return output.each { |l| yield l }
29
+ else
30
+ return output.join
37
31
  end
38
32
  end
33
+ module_function :cmd
39
34
 
40
- end # class
41
- end # module
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