linux_admin 0.2.0 → 0.2.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.
@@ -46,7 +46,7 @@ class LinuxAdmin
46
46
  return [] if params.blank?
47
47
  params.collect do |k, v|
48
48
  v = case v
49
- when Array; v.collect(&:shellescape)
49
+ when Array; v.collect {|i| i.to_s.shellescape}
50
50
  when NilClass; v
51
51
  else v.to_s.shellescape
52
52
  end
@@ -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 = case $2
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 ||= begin
45
- partitions = []
46
-
47
- # TODO: Should this really catch non-zero RC, set output to the default "" and silently return [] ?
48
- # If so, should other calls to parted also do the same?
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
- end
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
- partitions
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
@@ -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 refresh
39
- @entries = []
40
- f = File.read('/etc/fstab')
41
- f.each_line { |line|
42
- first_char = line.strip[0]
43
- if first_char != '#' && first_char !~ /\s/
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
- self
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 < LinuxAdmin
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
- vgs = VolumeGroup.scan
55
- lvs = []
56
-
57
- out = run!(cmd(:lvdisplay), :params => { '-c' => nil}).output
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 < LinuxAdmin
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
- vgs = VolumeGroup.scan
55
- pvs = []
56
-
57
- out = run!(cmd(:pvdisplay), :params => { '-c' => nil}).output
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
@@ -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
- run!(cmd(:systemctl),
21
- :params => { nil => ["enable", "#{id}.service"] })
29
+ systemctl 'enable'
22
30
  self
23
31
  end
24
32
 
25
33
  def disable
26
- run!(cmd(:systemctl),
27
- :params => { nil => ["disable", "#{id}.service"] })
34
+ systemctl 'disable'
28
35
  self
29
36
  end
30
37
 
@@ -1,3 +1,3 @@
1
1
  class LinuxAdmin
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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.0
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-16 00:00:00.000000000 Z
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