ruby-lvm 0.0.1 → 0.1.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.
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