linux_admin 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/linux_admin/common.rb +1 -1
- data/lib/linux_admin/disk.rb +80 -49
- data/lib/linux_admin/fstab.rb +34 -17
- data/lib/linux_admin/logical_volume.rb +5 -16
- data/lib/linux_admin/physical_volume.rb +6 -17
- data/lib/linux_admin/service.rb +11 -4
- data/lib/linux_admin/version.rb +1 -1
- data/lib/linux_admin/volume.rb +33 -0
- data/lib/linux_admin.rb +1 -0
- data/spec/common_spec.rb +5 -0
- data/spec/disk_spec.rb +30 -0
- metadata +3 -2
data/lib/linux_admin/common.rb
CHANGED
data/lib/linux_admin/disk.rb
CHANGED
@@ -7,8 +7,27 @@ require 'linux_admin/partition'
|
|
7
7
|
|
8
8
|
class LinuxAdmin
|
9
9
|
class Disk < LinuxAdmin
|
10
|
+
PARTED_FIELDS =
|
11
|
+
[:id, :start_sector, :end_sector,
|
12
|
+
:size, :partition_type, :fs_type]
|
13
|
+
|
10
14
|
attr_accessor :path
|
11
15
|
|
16
|
+
private
|
17
|
+
|
18
|
+
def str_to_bytes(val, unit)
|
19
|
+
case unit
|
20
|
+
when 'K' then
|
21
|
+
val.to_f.kilobytes
|
22
|
+
when 'M' then
|
23
|
+
val.to_f.megabytes
|
24
|
+
when 'G' then
|
25
|
+
val.to_f.gigabytes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
public
|
30
|
+
|
12
31
|
def self.local
|
13
32
|
Dir.glob('/dev/[vhs]d[a-z]').collect do |d|
|
14
33
|
Disk.new :path => d
|
@@ -25,14 +44,7 @@ class LinuxAdmin
|
|
25
44
|
out = run!(cmd(:fdisk), :params => {"-l" => nil}).output
|
26
45
|
out.each_line { |l|
|
27
46
|
if l =~ /Disk #{path}: ([0-9\.]*) ([KMG])B.*/
|
28
|
-
size =
|
29
|
-
when 'K' then
|
30
|
-
$1.to_f.kilobytes
|
31
|
-
when 'M' then
|
32
|
-
$1.to_f.megabytes
|
33
|
-
when 'G' then
|
34
|
-
$1.to_f.gigabytes
|
35
|
-
end
|
47
|
+
size = str_to_bytes($1, $2)
|
36
48
|
break
|
37
49
|
end
|
38
50
|
}
|
@@ -41,54 +53,65 @@ class LinuxAdmin
|
|
41
53
|
end
|
42
54
|
|
43
55
|
def partitions
|
44
|
-
@partitions ||=
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# requires sudo
|
50
|
-
out = run(cmd(:parted),
|
51
|
-
:params => { nil => [@path, 'print'] }).output
|
52
|
-
|
53
|
-
out.each_line do |l|
|
54
|
-
if l =~ /^ [0-9].*/
|
55
|
-
p = l.split
|
56
|
-
args = {:disk => self}
|
57
|
-
fields = [:id, :start_sector, :end_sector,
|
58
|
-
:size, :partition_type, :fs_type]
|
59
|
-
|
60
|
-
fields.each_index do |i|
|
61
|
-
val = p[i]
|
62
|
-
case fields[i]
|
63
|
-
when :start_sector, :end_sector, :size
|
64
|
-
if val =~ /([0-9\.]*)([KMG])B/
|
65
|
-
val = case $2
|
66
|
-
when 'K' then
|
67
|
-
$1.to_f.kilobytes
|
68
|
-
when 'M' then
|
69
|
-
$1.to_f.megabytes
|
70
|
-
when 'G' then
|
71
|
-
$1.to_f.gigabytes
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
when :id
|
76
|
-
val = val.to_i
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
args[fields[i]] = val
|
81
|
-
end
|
82
|
-
partitions << Partition.new(args)
|
56
|
+
@partitions ||=
|
57
|
+
parted_output.collect { |disk|
|
58
|
+
partition_from_parted(disk)
|
59
|
+
}
|
60
|
+
end
|
83
61
|
|
84
|
-
|
62
|
+
private
|
63
|
+
|
64
|
+
def parted_output
|
65
|
+
# TODO: Should this really catch non-zero RC, set output to the default "" and silently return [] ?
|
66
|
+
# If so, should other calls to parted also do the same?
|
67
|
+
# requires sudo
|
68
|
+
out = run(cmd(:parted),
|
69
|
+
:params => { nil => [@path, 'print'] }).output
|
70
|
+
split = []
|
71
|
+
out.each_line do |l|
|
72
|
+
if l =~ /^ [0-9].*/
|
73
|
+
split << l.split
|
85
74
|
end
|
75
|
+
end
|
76
|
+
split
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def partition_from_parted(output_disk)
|
81
|
+
args = {:disk => self}
|
82
|
+
PARTED_FIELDS.each_index do |i|
|
83
|
+
val = output_disk[i]
|
84
|
+
case PARTED_FIELDS[i]
|
85
|
+
when :start_sector, :end_sector, :size
|
86
|
+
if val =~ /([0-9\.]*)([KMG])B/
|
87
|
+
val = str_to_bytes($1, $2)
|
88
|
+
end
|
86
89
|
|
87
|
-
|
90
|
+
when :id
|
91
|
+
val = val.to_i
|
92
|
+
|
93
|
+
end
|
94
|
+
args[PARTED_FIELDS[i]] = val
|
88
95
|
end
|
96
|
+
|
97
|
+
Partition.new(args)
|
98
|
+
end
|
99
|
+
|
100
|
+
public
|
101
|
+
|
102
|
+
def create_partition_table(type = "msdos")
|
103
|
+
run!(cmd(:parted), :params => { nil => [path, "mklabel", type]})
|
104
|
+
end
|
105
|
+
|
106
|
+
def has_partition_table?
|
107
|
+
result = run(cmd(:parted), :params => { nil => [path, "print"]})
|
108
|
+
|
109
|
+
result_indicates_partition_table?(result)
|
89
110
|
end
|
90
111
|
|
91
112
|
def create_partition(partition_type, size)
|
113
|
+
create_partition_table unless has_partition_table?
|
114
|
+
|
92
115
|
id, start =
|
93
116
|
partitions.empty? ? [1, 0] :
|
94
117
|
[(partitions.last.id + 1),
|
@@ -118,5 +141,13 @@ class LinuxAdmin
|
|
118
141
|
|
119
142
|
self
|
120
143
|
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def result_indicates_partition_table?(result)
|
148
|
+
# parted exits with 1 but writes this oddly spelled error to stdout.
|
149
|
+
missing = (result.exit_status == 1 && result.output.include?("unrecognised disk label"))
|
150
|
+
!missing
|
151
|
+
end
|
121
152
|
end
|
122
153
|
end
|
data/lib/linux_admin/fstab.rb
CHANGED
@@ -13,6 +13,26 @@ class LinuxAdmin
|
|
13
13
|
attr_accessor :mount_options
|
14
14
|
attr_accessor :dumpable
|
15
15
|
attr_accessor :fsck_order
|
16
|
+
|
17
|
+
def initialize(args = {})
|
18
|
+
@device = args[:device]
|
19
|
+
@mount_point = args[:mount_point]
|
20
|
+
@fs_type = args[:fs_type]
|
21
|
+
@mount_options = args[:mount_options]
|
22
|
+
@dumpable = args[:dumpable]
|
23
|
+
@fsck_order = args[:fsck_order]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_line(fstab_line)
|
27
|
+
columns = fstab_line.chomp.split
|
28
|
+
FSTabEntry.new :device => columns[0],
|
29
|
+
:mount_point => columns[1],
|
30
|
+
:fs_type => columns[2],
|
31
|
+
:mount_options => columns[3],
|
32
|
+
:dumpable => columns[4].to_i,
|
33
|
+
:fsck_order => columns[5].to_i
|
34
|
+
|
35
|
+
end
|
16
36
|
end
|
17
37
|
|
18
38
|
class FSTab < LinuxAdmin
|
@@ -35,24 +55,21 @@ class LinuxAdmin
|
|
35
55
|
|
36
56
|
private
|
37
57
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
first_char = line.strip[0]
|
43
|
-
|
44
|
-
columns = line.split
|
45
|
-
entry = FSTabEntry.new
|
46
|
-
entry.device = columns[0]
|
47
|
-
entry.mount_point = columns[1]
|
48
|
-
entry.fs_type = columns[2]
|
49
|
-
entry.mount_options = columns[3]
|
50
|
-
entry.dumpable = columns[4].to_i
|
51
|
-
entry.fsck_order = columns[5].to_i
|
52
|
-
@entries << entry
|
53
|
-
end
|
58
|
+
def read
|
59
|
+
contents = File.read('/etc/fstab')
|
60
|
+
contents = contents.lines.to_a
|
61
|
+
contents.reject! { |line|
|
62
|
+
first_char = line.strip[0]
|
63
|
+
first_char == '#' || first_char =~ /\s/
|
54
64
|
}
|
55
|
-
|
65
|
+
contents
|
66
|
+
end
|
67
|
+
|
68
|
+
def refresh
|
69
|
+
@entries =
|
70
|
+
read.collect { |line|
|
71
|
+
FSTabEntry.from_line line
|
72
|
+
}
|
56
73
|
end
|
57
74
|
end
|
58
75
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Licensed under the MIT License
|
5
5
|
|
6
6
|
class LinuxAdmin
|
7
|
-
class LogicalVolume <
|
7
|
+
class LogicalVolume < Volume
|
8
8
|
# logical volume name
|
9
9
|
attr_accessor :name
|
10
10
|
|
@@ -51,22 +51,11 @@ class LinuxAdmin
|
|
51
51
|
|
52
52
|
def self.scan
|
53
53
|
@lvs ||= begin
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
out.each_line do |line|
|
60
|
-
fields = line.split(':')
|
61
|
-
vgname = fields[1]
|
62
|
-
vg = vgs.find { |vg| vg.name == vgname }
|
63
|
-
|
64
|
-
lvs << LogicalVolume.new(:name => fields[0],
|
65
|
-
:volume_group => vg,
|
66
|
-
:sectors => fields[6].to_i)
|
54
|
+
scan_volumes(cmd(:lvdisplay)) do |fields, vg|
|
55
|
+
LogicalVolume.new(:name => fields[0],
|
56
|
+
:volume_group => vg,
|
57
|
+
:sectors => fields[6].to_i)
|
67
58
|
end
|
68
|
-
|
69
|
-
lvs
|
70
59
|
end
|
71
60
|
end
|
72
61
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Licensed under the MIT License
|
5
5
|
|
6
6
|
class LinuxAdmin
|
7
|
-
class PhysicalVolume <
|
7
|
+
class PhysicalVolume < Volume
|
8
8
|
# physical volume device name
|
9
9
|
attr_accessor :device_name
|
10
10
|
|
@@ -51,22 +51,11 @@ class LinuxAdmin
|
|
51
51
|
|
52
52
|
def self.scan
|
53
53
|
@pvs ||= begin
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
out.each_line do |line|
|
60
|
-
fields = line.split(':')
|
61
|
-
vgname = fields[1]
|
62
|
-
vg = vgs.find { |vg| vg.name == vgname}
|
63
|
-
|
64
|
-
pvs << PhysicalVolume.new(:device_name => fields[0],
|
65
|
-
:volume_group => vg,
|
66
|
-
:size => fields[2].to_i)
|
67
|
-
end
|
68
|
-
|
69
|
-
pvs
|
54
|
+
scan_volumes(cmd(:pvdisplay)) do |fields, vg|
|
55
|
+
PhysicalVolume.new(:device_name => fields[0],
|
56
|
+
:volume_group => vg,
|
57
|
+
:size => fields[2].to_i)
|
58
|
+
end
|
70
59
|
end
|
71
60
|
end
|
72
61
|
end
|
data/lib/linux_admin/service.rb
CHANGED
@@ -7,6 +7,15 @@ class LinuxAdmin
|
|
7
7
|
class Service < LinuxAdmin
|
8
8
|
attr_accessor :id
|
9
9
|
|
10
|
+
private
|
11
|
+
|
12
|
+
def systemctl(cmd)
|
13
|
+
run!(cmd(:systemctl),
|
14
|
+
:params => { nil => [cmd, "#{id}.service"] })
|
15
|
+
end
|
16
|
+
|
17
|
+
public
|
18
|
+
|
10
19
|
def initialize(id)
|
11
20
|
@id = id
|
12
21
|
end
|
@@ -17,14 +26,12 @@ class LinuxAdmin
|
|
17
26
|
end
|
18
27
|
|
19
28
|
def enable
|
20
|
-
|
21
|
-
:params => { nil => ["enable", "#{id}.service"] })
|
29
|
+
systemctl 'enable'
|
22
30
|
self
|
23
31
|
end
|
24
32
|
|
25
33
|
def disable
|
26
|
-
|
27
|
-
:params => { nil => ["disable", "#{id}.service"] })
|
34
|
+
systemctl 'disable'
|
28
35
|
self
|
29
36
|
end
|
30
37
|
|
data/lib/linux_admin/version.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
# LinuxAdmin Logical Volume Representation
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Red Hat Inc.
|
4
|
+
# Licensed under the MIT License
|
5
|
+
|
6
|
+
class LinuxAdmin
|
7
|
+
class Volume < LinuxAdmin
|
8
|
+
private
|
9
|
+
|
10
|
+
def self.process_volume_display_line(line)
|
11
|
+
groups = VolumeGroup.scan
|
12
|
+
fields = line.split(':')
|
13
|
+
vgname = fields[1]
|
14
|
+
vg = groups.find { |vg| vg.name == vgname }
|
15
|
+
return fields, vg
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def self.scan_volumes(cmd)
|
21
|
+
volumes = []
|
22
|
+
|
23
|
+
out = run!(cmd, :params => { '-c' => nil}).output
|
24
|
+
|
25
|
+
out.each_line do |line|
|
26
|
+
fields, vg = process_volume_display_line(line)
|
27
|
+
volumes << yield(fields, vg)
|
28
|
+
end
|
29
|
+
|
30
|
+
volumes
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/linux_admin.rb
CHANGED
@@ -16,6 +16,7 @@ require 'linux_admin/partition'
|
|
16
16
|
require 'linux_admin/distro'
|
17
17
|
require 'linux_admin/system'
|
18
18
|
require 'linux_admin/fstab'
|
19
|
+
require 'linux_admin/volume'
|
19
20
|
require 'linux_admin/logical_volume'
|
20
21
|
require 'linux_admin/physical_volume'
|
21
22
|
require 'linux_admin/volume_group'
|
data/spec/common_spec.rb
CHANGED
@@ -47,6 +47,11 @@ describe LinuxAdmin::Common do
|
|
47
47
|
subject.send(run_method, "true", :params => modified_params)
|
48
48
|
end
|
49
49
|
|
50
|
+
it "sanitizes fixnum array params" do
|
51
|
+
subject.should_receive(:launch).once.with("true 1", {})
|
52
|
+
subject.send(run_method, "true", :params => { nil => [1]})
|
53
|
+
end
|
54
|
+
|
50
55
|
it "as empty hash" do
|
51
56
|
subject.should_receive(:launch).once.with("true", {})
|
52
57
|
subject.send(run_method, "true", :params => {})
|
data/spec/disk_spec.rb
CHANGED
@@ -106,6 +106,7 @@ eos
|
|
106
106
|
@disk.instance_variable_set(:@partitions,
|
107
107
|
[LinuxAdmin::Partition.new(:id => 1,
|
108
108
|
:end_sector => 1024)])
|
109
|
+
@disk.stub(:has_partition_table? => true)
|
109
110
|
end
|
110
111
|
|
111
112
|
it "uses parted" do
|
@@ -139,6 +140,35 @@ eos
|
|
139
140
|
@disk.create_partition 'primary', 1024
|
140
141
|
}.should change{@disk.partitions.size}.by(1)
|
141
142
|
end
|
143
|
+
|
144
|
+
it "creates partition table if missing" do
|
145
|
+
@disk.stub(:has_partition_table? => false)
|
146
|
+
@disk.should_receive(:create_partition_table)
|
147
|
+
@disk.should_receive(:run!)
|
148
|
+
@disk.create_partition 'primary', 1024
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#has_partition_table?" do
|
153
|
+
it "positive case" do
|
154
|
+
disk = LinuxAdmin::Disk.new :path => '/dev/hda'
|
155
|
+
disk.should_receive(:run).and_return(double(:output => "", :exit_status => 0))
|
156
|
+
disk.should have_partition_table
|
157
|
+
end
|
158
|
+
|
159
|
+
it "negative case" do
|
160
|
+
disk = LinuxAdmin::Disk.new :path => '/dev/hda'
|
161
|
+
output = "\e[?1034h\r\rError: /dev/sdb: unrecognised disk label\n"
|
162
|
+
disk.should_receive(:run).and_return(double(:output => output, :exit_status => 1))
|
163
|
+
disk.should_not have_partition_table
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
it "#create_partition_table" do
|
168
|
+
disk = LinuxAdmin::Disk.new :path => '/dev/hda'
|
169
|
+
options = {:params => {nil => ["/dev/hda", "mklabel", "msdos"]}}
|
170
|
+
disk.should_receive(:run!).with(disk.cmd(:parted), options)
|
171
|
+
disk.create_partition_table
|
142
172
|
end
|
143
173
|
|
144
174
|
describe "#clear!" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linux_admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-08-
|
15
|
+
date: 2013-08-22 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bundler
|
@@ -184,6 +184,7 @@ files:
|
|
184
184
|
- lib/linux_admin/service.rb
|
185
185
|
- lib/linux_admin/system.rb
|
186
186
|
- lib/linux_admin/version.rb
|
187
|
+
- lib/linux_admin/volume.rb
|
187
188
|
- lib/linux_admin/volume_group.rb
|
188
189
|
- lib/linux_admin/yum.rb
|
189
190
|
- linux_admin.gemspec
|