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
@@ -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
+