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