ruby-lvm 0.0.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.
- data/History.txt +6 -0
- data/Manifest.txt +27 -0
- data/README.txt +59 -0
- data/Rakefile +14 -0
- data/Todo.txt +10 -0
- data/examples/create_snapshot.rb +16 -0
- data/examples/error_handling.rb +9 -0
- data/examples/show_volumes.rb +26 -0
- data/helpers/generate_field_data.rb +117 -0
- data/lib/lvm/attrib/lvs.yaml +88 -0
- data/lib/lvm/attrib/pvs.yaml +46 -0
- data/lib/lvm/attrib/vgs.yaml +55 -0
- data/lib/lvm/external.rb +41 -0
- data/lib/lvm/lv.rb +19 -0
- data/lib/lvm/lvmanager.rb +95 -0
- data/lib/lvm/lvs.rb +143 -0
- data/lib/lvm/lvseg.rb +14 -0
- data/lib/lvm/proc.rb +39 -0
- data/lib/lvm/pv.rb +15 -0
- data/lib/lvm/pvmanager.rb +22 -0
- data/lib/lvm/pvs.rb +109 -0
- data/lib/lvm/pvseg.rb +14 -0
- data/lib/lvm/vg.rb +15 -0
- data/lib/lvm/vgmanager.rb +68 -0
- data/lib/lvm/vgs.rb +123 -0
- data/lib/lvm.rb +39 -0
- data/test/test_lvm.rb +0 -0
- data.tar.gz.sig +0 -0
- metadata +116 -0
- metadata.gz.sig +0 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,27 @@
|
|
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_volumes.rb
|
9
|
+
helpers/generate_field_data.rb
|
10
|
+
lib/lvm.rb
|
11
|
+
lib/lvm/attrib/lvs.yaml
|
12
|
+
lib/lvm/attrib/pvs.yaml
|
13
|
+
lib/lvm/attrib/vgs.yaml
|
14
|
+
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
|
27
|
+
test/test_lvm.rb
|
data/README.txt
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
= ruby-lvm
|
2
|
+
|
3
|
+
* http://ruby-lvm.rubyforge.org
|
4
|
+
* mailto:matt@bravenet.com
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
This is a wrapper for the LVM2 administration utility, lvm. Its primary
|
9
|
+
function it to convert physical volumes, logical volumes and volume groups
|
10
|
+
into easy to use ruby objects. It also provides a simple wrapper for typical
|
11
|
+
create/delete/etc operations.
|
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.
|
19
|
+
|
20
|
+
== FEATURES/PROBLEMS:
|
21
|
+
|
22
|
+
* Not finished, is that a problem?
|
23
|
+
|
24
|
+
== SYNOPSIS:
|
25
|
+
|
26
|
+
FIX (code sample of usage)
|
27
|
+
|
28
|
+
== REQUIREMENTS:
|
29
|
+
|
30
|
+
* popen4
|
31
|
+
|
32
|
+
== INSTALL:
|
33
|
+
|
34
|
+
* sudo gem install ruby-lvm
|
35
|
+
|
36
|
+
== LICENSE:
|
37
|
+
|
38
|
+
(The MIT License)
|
39
|
+
|
40
|
+
Copyright (c) 2008 Matthew Kent, Bravenet Web Services Inc.
|
41
|
+
|
42
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
43
|
+
a copy of this software and associated documentation files (the
|
44
|
+
'Software'), to deal in the Software without restriction, including
|
45
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
46
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
47
|
+
permit persons to whom the Software is furnished to do so, subject to
|
48
|
+
the following conditions:
|
49
|
+
|
50
|
+
The above copyright notice and this permission notice shall be
|
51
|
+
included in all copies or substantial portions of the Software.
|
52
|
+
|
53
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
54
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
55
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
56
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
57
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
58
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
59
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
$:.unshift(File.dirname(__FILE__) + "/lib")
|
6
|
+
require 'lvm'
|
7
|
+
|
8
|
+
Hoe.new('ruby-lvm', LVMWrapper::VERSION) do |p|
|
9
|
+
p.developer('Matthew Kent', 'matt@bravenet.com')
|
10
|
+
p.extra_deps << ['open4', '>= 0.9.6']
|
11
|
+
p.remote_rdoc_dir = ''
|
12
|
+
end
|
13
|
+
|
14
|
+
# vim: syntax=Ruby
|
data/Todo.txt
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
= to do
|
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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
$: << File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
5
|
+
require 'lvm'
|
6
|
+
require 'lvm/lvmanager'
|
7
|
+
require 'lvm/pvmanager'
|
8
|
+
require 'lvm/vgmanager'
|
9
|
+
|
10
|
+
lvm = LVMWrapper::LVM.new(:command => "/usr/bin/sudo /sbin/lvm")
|
11
|
+
lv = LVMWrapper::LogicalVolumeManager.new(lvm)
|
12
|
+
|
13
|
+
lv.remove(:vgname => "sys.vg", :name => "demo_snap")
|
14
|
+
lv.snapshot(:origin => "sys.vg/tmp.lv", :name => "demo_snap", :size => "10k")
|
15
|
+
|
16
|
+
p lv.list("sys.vg/demo_snap")
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
$: << File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
5
|
+
require 'lvm'
|
6
|
+
require 'lvm/lvmanager'
|
7
|
+
require 'lvm/pvmanager'
|
8
|
+
require 'lvm/vgmanager'
|
9
|
+
|
10
|
+
lvm = LVMWrapper::LVM.new(:command => "/usr/bin/sudo /sbin/lvm")
|
11
|
+
lv = LVMWrapper::LogicalVolumeManager.new(lvm)
|
12
|
+
vg = LVMWrapper::VolumeGroupManager.new(lvm)
|
13
|
+
pv = LVMWrapper::PhysicalVolumeManager.new(lvm)
|
14
|
+
|
15
|
+
pv.list.each do |p|
|
16
|
+
puts "- pv #{p.name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
puts ""
|
20
|
+
|
21
|
+
vg.list.each do |v|
|
22
|
+
puts "- vg #{v.name}"
|
23
|
+
lv.list(v.name).each do |l|
|
24
|
+
puts "-- lv #{l.name}"
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# collect all lvm reporting columns and format to our liking for inclusion in
|
4
|
+
# the library
|
5
|
+
#
|
6
|
+
# ruby generate_field_data.rb ~/iscsi_work/LVM2.2.02.36
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
LVM_COLUMNS = "/lib/report/columns.h"
|
11
|
+
|
12
|
+
CONVERSION_MAP = {
|
13
|
+
# Only types we can really trust
|
14
|
+
"uint32" => "Integer",
|
15
|
+
"int32" => "Integer",
|
16
|
+
# These were determined by reading the code, they invoke _(u)int32_disp right away
|
17
|
+
"pvmdas" => "Integer",
|
18
|
+
"vgmdas" => "Integer",
|
19
|
+
"lvcount" => "Integer",
|
20
|
+
"lvsegcount" => "Integer",
|
21
|
+
"segstartpe" => "Integer",
|
22
|
+
# listed to return STR?
|
23
|
+
"lvkmaj" => "Integer",
|
24
|
+
"lvkmin" => "Integer",
|
25
|
+
"snpercent" => "Float",
|
26
|
+
"copypercent" => "Float",
|
27
|
+
# size32/64, these do unit formatting unless overridden on command line. We
|
28
|
+
# typically want them in bytes so we can convert them to Integers safely
|
29
|
+
"size32" => "Integer",
|
30
|
+
"size64" => "Integer",
|
31
|
+
# These types return size32/size64 as well
|
32
|
+
"lvkreadahead" => "Integer",
|
33
|
+
"pvsize" => "Integer",
|
34
|
+
"devsize" => "Integer",
|
35
|
+
"pvfree" => "Integer",
|
36
|
+
"pvused" => "Integer",
|
37
|
+
"pvmdafree" => "Integer",
|
38
|
+
"vgsize" => "Integer",
|
39
|
+
"vgfree" => "Integer",
|
40
|
+
"vgmda_free" => "Integer",
|
41
|
+
"chunksize" => "Integer",
|
42
|
+
"segstart" => "Integer",
|
43
|
+
"segsize" => "Integer",
|
44
|
+
"vgmdafree" => "Integer",
|
45
|
+
# Weird one, can be "auto" or size32
|
46
|
+
"lvreadahead" => "String"
|
47
|
+
}
|
48
|
+
|
49
|
+
lvm_source = ARGV[0]
|
50
|
+
|
51
|
+
lvs = []
|
52
|
+
vgs = []
|
53
|
+
pvs = []
|
54
|
+
File.readlines(lvm_source + LVM_COLUMNS).each do |line|
|
55
|
+
chunked = line.split(", ")
|
56
|
+
|
57
|
+
app = chunked[0]
|
58
|
+
general_type = chunked[2]
|
59
|
+
specific_type = chunked[6]
|
60
|
+
field = chunked[7]
|
61
|
+
# description = chunked[8]
|
62
|
+
|
63
|
+
attribute = field
|
64
|
+
attribute_type = nil
|
65
|
+
|
66
|
+
if app.nil? || general_type.nil? || specific_type.nil? || field.nil?
|
67
|
+
next
|
68
|
+
end
|
69
|
+
|
70
|
+
attribute.gsub!('"', '')
|
71
|
+
|
72
|
+
if general_type == "NUM"
|
73
|
+
attribute_type = CONVERSION_MAP[specific_type]
|
74
|
+
if attribute_type.nil?
|
75
|
+
puts "oops, missing hanlding of attribute '#{attribute}' which says its going to return a '#{specific_type}'"
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
else
|
79
|
+
attribute_type = "String"
|
80
|
+
end
|
81
|
+
#XXX man page says we can skip the lv_ prefixes! and seg_!
|
82
|
+
if app == "FIELD(LVS" || app == "FIELD(SEGS"
|
83
|
+
lvs << { :option => attribute, :type_hint => attribute_type, :method => attribute.sub(%r{^lv_}, '') }
|
84
|
+
elsif app == "FIELD(PVS" || app == "FIELD(PVSEGS"
|
85
|
+
pvs << { :option => attribute, :type_hint => attribute_type, :method => attribute.sub(%r{^pv_}, '') }
|
86
|
+
elsif app == "FIELD(VGS"
|
87
|
+
vgs << { :option => attribute, :type_hint => attribute_type, :method => attribute.sub(%r{^vg_}, '') }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
lvs.sort! {|x,y| x[:option] <=> y[:option]}
|
92
|
+
pvs.sort! {|x,y| x[:option] <=> y[:option]}
|
93
|
+
vgs.sort! {|x,y| x[:option] <=> y[:option]}
|
94
|
+
|
95
|
+
File.open("lvs.yaml", "w") do |f|
|
96
|
+
f.write "# these are column to object attribute mappings \n"
|
97
|
+
f.write "# generated by #{$0} based on \n"
|
98
|
+
f.write "# #{lvm_source}/lib/report/columns.h\n"
|
99
|
+
f.write(lvs.to_yaml)
|
100
|
+
end
|
101
|
+
puts "Wrote data to lvs.yaml"
|
102
|
+
|
103
|
+
File.open("pvs.yaml", "w") do |f|
|
104
|
+
f.write "# these are column to object attribute mappings \n"
|
105
|
+
f.write "# generated by #{$0} based on \n"
|
106
|
+
f.write "# #{lvm_source}/lib/report/columns.h\n"
|
107
|
+
f.write(pvs.to_yaml)
|
108
|
+
end
|
109
|
+
puts "Wrote data to pvs.yaml"
|
110
|
+
|
111
|
+
File.open("vgs.yaml", "w") do |f|
|
112
|
+
f.write "# these are column to object attribute mappings \n"
|
113
|
+
f.write "# generated by #{$0} based on \n"
|
114
|
+
f.write "# #{lvm_source}/lib/report/columns.h\n"
|
115
|
+
f.write(vgs.to_yaml)
|
116
|
+
end
|
117
|
+
puts "Wrote data to vgs.yaml"
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# these are column to object attribute mappings
|
2
|
+
# generated by generate_field_data.rb based on
|
3
|
+
# /home/iscsidev/LVM2.2.02.26/lib/report/columns.h
|
4
|
+
---
|
5
|
+
- :method: chunk_size
|
6
|
+
:option: chunk_size
|
7
|
+
:type_hint: Integer
|
8
|
+
- :method: chunksize
|
9
|
+
:option: chunksize
|
10
|
+
:type_hint: Integer
|
11
|
+
- :method: copy_percent
|
12
|
+
:option: copy_percent
|
13
|
+
:type_hint: Float
|
14
|
+
- :method: devices
|
15
|
+
:option: devices
|
16
|
+
:type_hint: String
|
17
|
+
- :method: attr
|
18
|
+
:option: lv_attr
|
19
|
+
:type_hint: String
|
20
|
+
- :method: kernel_major
|
21
|
+
:option: lv_kernel_major
|
22
|
+
:type_hint: String
|
23
|
+
- :method: kernel_minor
|
24
|
+
:option: lv_kernel_minor
|
25
|
+
:type_hint: String
|
26
|
+
- :method: major
|
27
|
+
:option: lv_major
|
28
|
+
:type_hint: Integer
|
29
|
+
- :method: minor
|
30
|
+
:option: lv_minor
|
31
|
+
:type_hint: Integer
|
32
|
+
- :method: name
|
33
|
+
:option: lv_name
|
34
|
+
:type_hint: String
|
35
|
+
- :method: size
|
36
|
+
:option: lv_size
|
37
|
+
:type_hint: Integer
|
38
|
+
- :method: tags
|
39
|
+
:option: lv_tags
|
40
|
+
:type_hint: String
|
41
|
+
- :method: uuid
|
42
|
+
:option: lv_uuid
|
43
|
+
:type_hint: String
|
44
|
+
- :method: mirror_log
|
45
|
+
:option: mirror_log
|
46
|
+
:type_hint: String
|
47
|
+
- :method: modules
|
48
|
+
:option: modules
|
49
|
+
:type_hint: String
|
50
|
+
- :method: move_pv
|
51
|
+
:option: move_pv
|
52
|
+
:type_hint: String
|
53
|
+
- :method: origin
|
54
|
+
:option: origin
|
55
|
+
:type_hint: String
|
56
|
+
- :method: region_size
|
57
|
+
:option: region_size
|
58
|
+
:type_hint: Integer
|
59
|
+
- :method: regionsize
|
60
|
+
:option: regionsize
|
61
|
+
:type_hint: Integer
|
62
|
+
- :method: seg_count
|
63
|
+
:option: seg_count
|
64
|
+
:type_hint: Integer
|
65
|
+
- :method: seg_size
|
66
|
+
:option: seg_size
|
67
|
+
:type_hint: Integer
|
68
|
+
- :method: seg_start
|
69
|
+
:option: seg_start
|
70
|
+
:type_hint: Integer
|
71
|
+
- :method: seg_tags
|
72
|
+
:option: seg_tags
|
73
|
+
:type_hint: String
|
74
|
+
- :method: segtype
|
75
|
+
:option: segtype
|
76
|
+
:type_hint: String
|
77
|
+
- :method: snap_percent
|
78
|
+
:option: snap_percent
|
79
|
+
:type_hint: Float
|
80
|
+
- :method: stripe_size
|
81
|
+
:option: stripe_size
|
82
|
+
:type_hint: Integer
|
83
|
+
- :method: stripes
|
84
|
+
:option: stripes
|
85
|
+
:type_hint: Integer
|
86
|
+
- :method: stripesize
|
87
|
+
:option: stripesize
|
88
|
+
:type_hint: Integer
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# these are column to object attribute mappings
|
2
|
+
# generated by generate_field_data.rb based on
|
3
|
+
# /home/iscsidev/LVM2.2.02.26/lib/report/columns.h
|
4
|
+
---
|
5
|
+
- :method: dev_size
|
6
|
+
:option: dev_size
|
7
|
+
:type_hint: Integer
|
8
|
+
- :method: pe_start
|
9
|
+
:option: pe_start
|
10
|
+
:type_hint: Integer
|
11
|
+
- :method: attr
|
12
|
+
:option: pv_attr
|
13
|
+
:type_hint: String
|
14
|
+
- :method: fmt
|
15
|
+
:option: pv_fmt
|
16
|
+
:type_hint: String
|
17
|
+
- :method: free
|
18
|
+
:option: pv_free
|
19
|
+
:type_hint: Integer
|
20
|
+
- :method: name
|
21
|
+
:option: pv_name
|
22
|
+
:type_hint: String
|
23
|
+
- :method: pe_alloc_count
|
24
|
+
:option: pv_pe_alloc_count
|
25
|
+
:type_hint: Integer
|
26
|
+
- :method: pe_count
|
27
|
+
:option: pv_pe_count
|
28
|
+
:type_hint: Integer
|
29
|
+
- :method: size
|
30
|
+
:option: pv_size
|
31
|
+
:type_hint: Integer
|
32
|
+
- :method: tags
|
33
|
+
:option: pv_tags
|
34
|
+
:type_hint: String
|
35
|
+
- :method: used
|
36
|
+
:option: pv_used
|
37
|
+
:type_hint: Integer
|
38
|
+
- :method: uuid
|
39
|
+
:option: pv_uuid
|
40
|
+
:type_hint: String
|
41
|
+
- :method: pvseg_size
|
42
|
+
:option: pvseg_size
|
43
|
+
:type_hint: Integer
|
44
|
+
- :method: pvseg_start
|
45
|
+
:option: pvseg_start
|
46
|
+
:type_hint: Integer
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# these are column to object attribute mappings
|
2
|
+
# generated by generate_field_data.rb based on
|
3
|
+
# /home/iscsidev/LVM2.2.02.26/lib/report/columns.h
|
4
|
+
---
|
5
|
+
- :method: lv_count
|
6
|
+
:option: lv_count
|
7
|
+
:type_hint: Integer
|
8
|
+
- :method: max_lv
|
9
|
+
:option: max_lv
|
10
|
+
:type_hint: Integer
|
11
|
+
- :method: max_pv
|
12
|
+
:option: max_pv
|
13
|
+
:type_hint: Integer
|
14
|
+
- :method: pv_count
|
15
|
+
:option: pv_count
|
16
|
+
:type_hint: Integer
|
17
|
+
- :method: snap_count
|
18
|
+
:option: snap_count
|
19
|
+
:type_hint: Integer
|
20
|
+
- :method: attr
|
21
|
+
:option: vg_attr
|
22
|
+
:type_hint: String
|
23
|
+
- :method: extent_count
|
24
|
+
:option: vg_extent_count
|
25
|
+
:type_hint: Integer
|
26
|
+
- :method: extent_size
|
27
|
+
:option: vg_extent_size
|
28
|
+
:type_hint: Integer
|
29
|
+
- :method: fmt
|
30
|
+
:option: vg_fmt
|
31
|
+
:type_hint: String
|
32
|
+
- :method: free
|
33
|
+
:option: vg_free
|
34
|
+
:type_hint: Integer
|
35
|
+
- :method: free_count
|
36
|
+
:option: vg_free_count
|
37
|
+
:type_hint: Integer
|
38
|
+
- :method: name
|
39
|
+
:option: vg_name
|
40
|
+
:type_hint: String
|
41
|
+
- :method: seqno
|
42
|
+
:option: vg_seqno
|
43
|
+
:type_hint: Integer
|
44
|
+
- :method: size
|
45
|
+
:option: vg_size
|
46
|
+
:type_hint: Integer
|
47
|
+
- :method: sysid
|
48
|
+
:option: vg_sysid
|
49
|
+
:type_hint: String
|
50
|
+
- :method: tags
|
51
|
+
:option: vg_tags
|
52
|
+
:type_hint: String
|
53
|
+
- :method: uuid
|
54
|
+
:option: vg_uuid
|
55
|
+
:type_hint: String
|
data/lib/lvm/external.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'open4'
|
3
|
+
|
4
|
+
module LVMWrapper
|
5
|
+
class External
|
6
|
+
class ExternalFailure < RuntimeError; end
|
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
|
21
|
+
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"
|
30
|
+
end
|
31
|
+
|
32
|
+
if block_given?
|
33
|
+
return output.each { |l| yield l }
|
34
|
+
else
|
35
|
+
return output.join
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end # class
|
41
|
+
end # module
|
data/lib/lvm/lv.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module LVMWrapper
|
2
|
+
class LogicalVolume
|
3
|
+
def initialize(args)
|
4
|
+
@attributes = args
|
5
|
+
|
6
|
+
# so many attributes.. we let the caller define them :)
|
7
|
+
meta = class << self; self; end
|
8
|
+
args.each_key do |name|
|
9
|
+
meta.send(:define_method, name) { @attributes[name] }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# helper methods
|
14
|
+
def open?
|
15
|
+
@attributes[:device_open]
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class
|
19
|
+
end # module
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'lvm/lv'
|
2
|
+
require 'lvm/lvs'
|
3
|
+
|
4
|
+
module LVMWrapper
|
5
|
+
class LogicalVolumeManager
|
6
|
+
|
7
|
+
def initialize(lvm)
|
8
|
+
@lvm = lvm
|
9
|
+
end
|
10
|
+
|
11
|
+
# lvchange Change the attributes of logical volume(s)
|
12
|
+
# lvconvert Change logical volume layout
|
13
|
+
# lvdisplay Display information about a logical volume
|
14
|
+
# lvextend Add space to a logical volume
|
15
|
+
#*lvmchange With the device mapper, this is obsolete and
|
16
|
+
# does nothing.
|
17
|
+
#*lvmdiskscan List devices that may be used as physical
|
18
|
+
# volumes
|
19
|
+
#*lvmsadc Collect activity data
|
20
|
+
#*lvmsar Create activity report
|
21
|
+
# lvreduce Reduce the size of a logical volume
|
22
|
+
# lvrename Rename a logical volume
|
23
|
+
# lvresize Resize a logical volume
|
24
|
+
# lvscan List all logical volumes in
|
25
|
+
# all volume groups
|
26
|
+
|
27
|
+
# We take the options listed by 'lvm <cmd>' as symbols and pass them as is
|
28
|
+
# to lvm. We let LVM opt parsing handle any issues.
|
29
|
+
def create(args)
|
30
|
+
vgname = args[:vgname] || nil
|
31
|
+
pvpath = args[:pvpath]
|
32
|
+
|
33
|
+
raise ArgumentError if vgname.nil?
|
34
|
+
|
35
|
+
args.delete(:vgname)
|
36
|
+
args.delete(:pvpath)
|
37
|
+
|
38
|
+
@lvm.cmd("lvcreate #{args_to_long_opts(args)} #{vgname} #{pvpath}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove(args)
|
42
|
+
lvname = args[:name] || nil
|
43
|
+
vgname = args[:vgname] || nil
|
44
|
+
|
45
|
+
raise ArgumentError if (lvname.nil? or vgname.nil?)
|
46
|
+
|
47
|
+
args.delete(:name)
|
48
|
+
args.delete(:vgname)
|
49
|
+
|
50
|
+
@lvm.cmd("lvremove --force #{args_to_long_opts(args)} #{vgname}/#{lvname}")
|
51
|
+
end
|
52
|
+
|
53
|
+
def snapshot(args)
|
54
|
+
origin = args[:origin] || nil
|
55
|
+
|
56
|
+
raise ArgumentError if origin.nil?
|
57
|
+
|
58
|
+
args.delete(:origin)
|
59
|
+
|
60
|
+
@lvm.cmd("lvcreate --snapshot #{args_to_long_opts(args)} #{origin}")
|
61
|
+
end
|
62
|
+
|
63
|
+
# ruby hash of key values to long options
|
64
|
+
def args_to_long_opts(args)
|
65
|
+
opts = []
|
66
|
+
args.each do |key,value|
|
67
|
+
opts << "--#{key.to_s} #{value}"
|
68
|
+
end
|
69
|
+
opts.join(" ")
|
70
|
+
end
|
71
|
+
|
72
|
+
def lookup(lvname,vgname)
|
73
|
+
raw_data = @lvm.cmd("#{LVS.command} #{vgname}/#{lvname}")
|
74
|
+
LVS.parse(raw_data)[0]
|
75
|
+
end
|
76
|
+
|
77
|
+
def [](lvname,vgname)
|
78
|
+
lookup(lvname,vgname)
|
79
|
+
end
|
80
|
+
|
81
|
+
def list(vgname)
|
82
|
+
raw_data = @lvm.cmd("#{LVS.command} #{vgname}")
|
83
|
+
lvs = LVS.parse(raw_data)
|
84
|
+
if block_given?
|
85
|
+
lvs.each do |lv|
|
86
|
+
yield lv
|
87
|
+
end
|
88
|
+
else
|
89
|
+
lvs
|
90
|
+
end
|
91
|
+
end
|
92
|
+
alias lvs list
|
93
|
+
|
94
|
+
end # class
|
95
|
+
end # module
|