tweek 0.9.9 → 1.0.0
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.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/bin/tweek +2 -2
- data/lib/tweek/{app.rb → file.rb} +28 -16
- data/lib/tweek/section.rb +107 -68
- data/lib/tweek/version.rb +1 -1
- data/lib/tweek.rb +62 -1
- data/settings/sample.set +27 -19
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7068bcfbf27d73e5c1a20c2f5d52671a8d0ce968
|
4
|
+
data.tar.gz: 8458e63c00fd12cc564a7e7aa3198aecfefe65b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c09dfbf71eca18073c90a87616d46084f2ec6572d659c5a23beaf9c1044e33d984030d30ac24ff74a4e871f066ddf994529373cfdbe3f69af018c06de22d2b84
|
7
|
+
data.tar.gz: 7c85c2be58f9a2de5383a7f5caa0c433d30678f6a46eb12e7a32191d0c91a65eba57858ef6bb7b07894659958ab9d98bb046836b179623f72c32b071182d890d
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ be recorded and checked against a file of settings. Think of it as a series of
|
|
5
5
|
configuration tests that can be executed, with the results being presented as a number of
|
6
6
|
passes and failures. The number of failures is returned as the exit code of the process
|
7
7
|
which allows it's use in scripts. This is particularly useful when checking multiple
|
8
|
-
machines
|
8
|
+
machines using a utility like `pssh` or `mush`.
|
9
9
|
|
10
10
|
Although existing configuration management systems such as Puppet, Chef or Ansible can
|
11
11
|
perform the same checks, they tend to require a high level of support infrastructure to be
|
@@ -118,7 +118,7 @@ For a discussion of which parameters are supported please see the sample setting
|
|
118
118
|
|
119
119
|
Parameter lines can be suffixed by the word `if` and one or more conditions. These are
|
120
120
|
used to limit the scope of the parameter check to those systems where the condition(s) hold
|
121
|
-
true. The list of conditions is
|
121
|
+
true. The list of conditions is logically AND'ed together. A condition takes the form:
|
122
122
|
|
123
123
|
```
|
124
124
|
[k|d|v] op value
|
@@ -126,10 +126,10 @@ true. The list of conditions is logicall AND'ed together. A condition takes the
|
|
126
126
|
|
127
127
|
Where:
|
128
128
|
* `k` is the Kernel Version, `d` is the Distro name, and `v` is the Distro version.
|
129
|
-
* The operator `op` can be: equality
|
129
|
+
* The operator `op` can be: equality `==`, regex equality `=~` or a version comparator as
|
130
130
|
per the [Rubygems](http://ruby-doc.org/stdlib-2.0.0/libdoc/rubygems/rdoc/Gem/Version.html) specification.
|
131
|
-
* The value is one of: a plain string in quotes (for equality), a regex between
|
132
|
-
delimiters, or a plain version string.
|
131
|
+
* The value is one of: a plain string in `'` quotes (for equality), a regex between `/`
|
132
|
+
delimiters, or a plain version string (eg. `4.3.1`).
|
133
133
|
|
134
134
|
NOTE: The determination of the current Distro, Distro Version and Kernel Version is done
|
135
135
|
using the `lsb_release` and `uname` commands. Since these may not be installed on all
|
data/bin/tweek
CHANGED
@@ -9,7 +9,7 @@ require 'rubygems'
|
|
9
9
|
require 'optparse'
|
10
10
|
require 'ostruct'
|
11
11
|
require 'tweek'
|
12
|
-
require 'tweek/
|
12
|
+
require 'tweek/file'
|
13
13
|
require 'tweek/version'
|
14
14
|
|
15
15
|
trap('INT') do
|
@@ -83,7 +83,7 @@ if kernel_ver.nil?
|
|
83
83
|
exit 2
|
84
84
|
end
|
85
85
|
end
|
86
|
-
cs = Tweek::
|
86
|
+
cs = Tweek::File.new(gflag, true, distro, distro_ver, kernel_ver)
|
87
87
|
if ARGV.empty?
|
88
88
|
fh = File.open(File.expand_path('../../settings/sample.set',__FILE__))
|
89
89
|
else
|
@@ -4,7 +4,7 @@ require 'ostruct'
|
|
4
4
|
require 'tweek'
|
5
5
|
require 'tweek/section'
|
6
6
|
|
7
|
-
class Tweek::
|
7
|
+
class Tweek::File
|
8
8
|
|
9
9
|
attr_reader :distro, :distro_version, :kernel_version
|
10
10
|
|
@@ -22,12 +22,6 @@ class Tweek::App
|
|
22
22
|
@tty = tty
|
23
23
|
end
|
24
24
|
|
25
|
-
# Define data-collection methods so we can easily stub them for tests
|
26
|
-
#
|
27
|
-
def self.bootline
|
28
|
-
@bootline ||= File.open("/proc/cmdline", &:read).chomp rescue 'nowt'
|
29
|
-
end
|
30
|
-
|
31
25
|
def generate type, e
|
32
26
|
return unless @gflag
|
33
27
|
case type
|
@@ -37,11 +31,21 @@ class Tweek::App
|
|
37
31
|
@generated.push "#{e.type} #{e.list} #{e.comment}"
|
38
32
|
when :entry
|
39
33
|
cond = e.cond.nil? ? "": " if #{e.cond}"
|
40
|
-
|
41
|
-
|
42
|
-
|
34
|
+
if e.actual.nil?
|
35
|
+
line = "#{e.param} = #{e.value}#{cond}"
|
36
|
+
note = "[condition not met]"
|
43
37
|
else
|
44
|
-
|
38
|
+
line = "#{e.param} = #{e.actual}#{cond}"
|
39
|
+
if e.value === e.actual
|
40
|
+
note = nil
|
41
|
+
else
|
42
|
+
note = "[expected #{e.value}]"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if e.comment.nil?
|
46
|
+
@generated.push (note ? line + " # " + note : line)
|
47
|
+
else
|
48
|
+
@generated.push (note ? line + " " + comment + " " + note : line + " " + comment)
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
@@ -65,6 +69,7 @@ class Tweek::App
|
|
65
69
|
|
66
70
|
def condfail cond
|
67
71
|
return false unless cond
|
72
|
+
cond.strip!
|
68
73
|
failures = 0
|
69
74
|
reqs = cond.split(/\s*,\s*/)
|
70
75
|
reqs.each do |req|
|
@@ -123,9 +128,13 @@ class Tweek::App
|
|
123
128
|
next
|
124
129
|
end
|
125
130
|
|
126
|
-
if /^\s*(.+?)\s*=\s*(.*?)\s*(
|
127
|
-
|
128
|
-
|
131
|
+
if /^\s*(.+?)\s*=\s*(.*?)\s*(\bif\b(.*))?$/ =~ line
|
132
|
+
if $4 and $4.strip.empty?
|
133
|
+
error "#{handle.lineno}: Missing condition after 'if'"
|
134
|
+
else
|
135
|
+
section.push OpenStruct.new( :lineno => handle.lineno, :param => $1, :value => $2,
|
136
|
+
:cond => $4, :comment => comment )
|
137
|
+
end
|
129
138
|
next
|
130
139
|
end
|
131
140
|
error "#{handle.lineno}: Unrecognized line: #{line}"
|
@@ -136,11 +145,14 @@ class Tweek::App
|
|
136
145
|
|
137
146
|
def results
|
138
147
|
STDERR.puts "\nDistro: #{@distro} Version: #{@distro_version} Kernel: #{@kernel_version}"
|
139
|
-
STDERR.puts "\n#{@nparams} parameters checked, #{@skips.size}
|
148
|
+
STDERR.puts "\n#{@nparams} parameters checked, #{@skips.size} conditions not met, #{@mismatches.size} mismatches, #{@warns.size} warnings, #{@errors.size} errors"
|
140
149
|
STDERR.puts "\n#{@errors.join("\n")}" unless @errors.empty?
|
141
150
|
STDERR.puts "\n#{@warns.join("\n")}" unless @warns.empty?
|
142
151
|
STDERR.puts "\n#{@mismatches.join("\n")}" unless @mismatches.empty?
|
143
|
-
@
|
152
|
+
if @gflag
|
153
|
+
@generated.unshift "# Generated at #{Time.now.strftime("%c %Z")}\n# Distro: #{@distro} Version: #{@distro_version} Kernel: #{@kernel_version}"
|
154
|
+
@generated.each { |l| STDOUT.puts l}
|
155
|
+
end
|
144
156
|
return @mismatches.size
|
145
157
|
end
|
146
158
|
end
|
data/lib/tweek/section.rb
CHANGED
@@ -63,7 +63,7 @@ class Tweek::Section < Array
|
|
63
63
|
|
64
64
|
devices.each do |blk|
|
65
65
|
each_entry (cs) do |entry|
|
66
|
-
entry.actual =
|
66
|
+
entry.actual = Tweek.blk_param(blk, entry.param)
|
67
67
|
if entry.param == 'scheduler'
|
68
68
|
entry.actual = entry.actual.slice(/\[(.*?)\]/,1) unless entry.actual == 'none'
|
69
69
|
end
|
@@ -74,7 +74,7 @@ class Tweek::Section < Array
|
|
74
74
|
|
75
75
|
when 'KERNEL' # KERNEL PARAMETERS
|
76
76
|
each_entry (cs) do |entry|
|
77
|
-
actual = /\b(#{entry.param})(=\S+)?\b/.match(Tweek
|
77
|
+
actual = /\b(#{entry.param})(=\S+)?\b/.match(Tweek.bootline)
|
78
78
|
case
|
79
79
|
when (entry.value == 'true' and actual)
|
80
80
|
observed = actual.to_s
|
@@ -99,7 +99,7 @@ class Tweek::Section < Array
|
|
99
99
|
|
100
100
|
when 'CLOCKSOURCE'
|
101
101
|
each_entry (cs) do |entry|
|
102
|
-
entry.actual=
|
102
|
+
entry.actual = Tweek.clocksource(entry.param)
|
103
103
|
cs.assert_equal entry.value, entry.actual, entry.param
|
104
104
|
cs.generate :entry, entry
|
105
105
|
end
|
@@ -107,7 +107,7 @@ class Tweek::Section < Array
|
|
107
107
|
when 'SYSCTL' # SYSCTL SETTINGS
|
108
108
|
each_entry (cs) do |entry|
|
109
109
|
file = entry.param.gsub(/\./,'/')
|
110
|
-
entry.actual =
|
110
|
+
entry.actual = Tweek.sysctl(file)
|
111
111
|
cs.assert_equal entry.value, entry.actual, entry.param
|
112
112
|
cs.generate :entry, entry
|
113
113
|
end
|
@@ -121,84 +121,39 @@ class Tweek::Section < Array
|
|
121
121
|
|
122
122
|
case entry.param
|
123
123
|
when 'driver'
|
124
|
-
|
125
|
-
cs.assert_equal entry.value, entry.actual, entry.param
|
124
|
+
entry.actual = Tweek.net_driver(netdev)
|
126
125
|
|
127
126
|
when 'irqs'
|
128
127
|
|
129
|
-
|
128
|
+
balpid = Tweek.balance_pid
|
130
129
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
case entry.value
|
142
|
-
when 'null','none','ignore'
|
143
|
-
next
|
144
|
-
|
145
|
-
when 'aws'
|
146
|
-
expected_rps = ("00000000," * 3) + "0000ff00"
|
147
|
-
expected_rss = ("00000000," * 3) + sprintf("%08x", 1<<ix)
|
148
|
-
|
149
|
-
when 'pin'
|
150
|
-
case ncores
|
151
|
-
when 32 # RPS on cores 10-15 and 18-31, RSS tied to 0-7
|
152
|
-
case ix
|
153
|
-
when 0..7
|
154
|
-
expected_rps = ("00000000," * 3) + "fffefe00"
|
155
|
-
expected_rss = ("00000000," * 3) + sprintf("%08x", 1<<(ix+1))
|
156
|
-
else
|
157
|
-
cs.warn "#{netdev} IRQ strategy '#{entry.value}' can't handle IRQ#{ix}"
|
158
|
-
end
|
159
|
-
|
160
|
-
when 64 # Split the work across the two nodes
|
161
|
-
case ix
|
162
|
-
when 0..3 # alloc on node 0 (cpus 0-3)
|
163
|
-
expected_rps = ("00000000," * 2) + "0000ffff," + "0000ffe0"
|
164
|
-
expected_rss = ("00000000," * 3) + sprintf("%08x", 1<<(ix+1))
|
165
|
-
when 4..7 # alloc on node 1 (
|
166
|
-
expected_rps = ("00000000," * 2) + "ffff0000," + "ffe00000"
|
167
|
-
expected_rss = ("00000000," * 3) + sprintf("%08x", 1<<(ix + 9))
|
168
|
-
else
|
169
|
-
cs.warn "#{netdev} IRQ strategy '#{entry.value}' can't handle IRQ#{ix}"
|
170
|
-
end
|
171
|
-
|
172
|
-
else
|
173
|
-
cs.error "#{entry.lineno}: Can't handle #{ncores} cores in IRQ strategy '#{entry.value}'"
|
174
|
-
end
|
175
|
-
|
176
|
-
else
|
177
|
-
cs.error "#{entry.lineno}: Unrecognized #{netdev} IRQ strategy '#{entry.value}'"
|
178
|
-
end
|
179
|
-
actual_rss = File.open("/proc/irq/#{irq}/smp_affinity",&:read).chomp rescue $!.message
|
180
|
-
actual_rps = File.open("/sys/class/net/#{netdev}/queues/rx-#{ix}/rps_cpus", &:read).chomp rescue $!.message
|
181
|
-
mismatches += cs.assert_equal expected_rss, actual_rss, "#{netdev}_irq_#{irq}_rss"
|
182
|
-
mismatches += cs.assert_equal expected_rps, actual_rps, "#{netdev}_irq_#{irq}_rps"
|
183
|
-
end
|
184
|
-
entry.actual = 'null' if mismatches > 0
|
130
|
+
if entry.value == 'balance'
|
131
|
+
entry.actual = balpid.zero? ? 'IRQ balance daemon not running' : 'balance'
|
132
|
+
else
|
133
|
+
if balpid.zero?
|
134
|
+
handle_irqs(netdev, cs, entry)
|
135
|
+
next
|
136
|
+
else
|
137
|
+
entry.actual = 'IRQ balance daemon running'
|
138
|
+
end
|
139
|
+
end
|
185
140
|
|
186
|
-
else #
|
141
|
+
else # treat the parameter as a name
|
187
142
|
begin
|
188
|
-
|
189
|
-
cs.assert_equal entry.value, entry.actual, entry.param
|
190
|
-
|
143
|
+
entry.actual = Tweek.net_param(netdev, entry.param)
|
191
144
|
rescue
|
192
145
|
cs.error "#{entry.lineno}: Network parameter #{entry.param} not handled: #{$!.message}"
|
193
146
|
next
|
194
147
|
end
|
195
148
|
end
|
149
|
+
|
150
|
+
cs.assert_equal entry.value, entry.actual, entry.param
|
196
151
|
cs.generate :entry, entry
|
197
152
|
end
|
198
153
|
end
|
199
154
|
|
200
155
|
when 'EXT4' # EXT4 filesystems info via `dumpe2fs -h /dev/#{device}`
|
201
|
-
mounted =
|
156
|
+
mounted = Tweek.mounted
|
202
157
|
mounts = Dir.glob(self.list.split(' '))
|
203
158
|
mounts.each do |mount|
|
204
159
|
unless this = mounted.select{|m| (mount == m[0] or mount == m[1]) and m[2] == 'ext4'}.first
|
@@ -223,8 +178,8 @@ class Tweek::Section < Array
|
|
223
178
|
cs.warn "#{self.lineno}: XFS device check skipped: no mountpoints found"
|
224
179
|
end
|
225
180
|
mounts.each do |mount|
|
226
|
-
xfsinfo =
|
227
|
-
|
181
|
+
xfsinfo = Tweek.xfsinfo(mount)
|
182
|
+
unless xfsinfo
|
228
183
|
cs.warn "No XFS filesystem at #{mount}"
|
229
184
|
each_entry (cs) { |entry| cs.generate :entry, entry }
|
230
185
|
next
|
@@ -248,5 +203,89 @@ class Tweek::Section < Array
|
|
248
203
|
end
|
249
204
|
|
250
205
|
end
|
206
|
+
|
207
|
+
def handle_irqs netdev, cs, entry
|
208
|
+
irqs = Tweek.irqs(netdev)
|
209
|
+
|
210
|
+
if irqs.empty?
|
211
|
+
cs.warn "#{netdev} IRQ check skipped: none found"
|
212
|
+
entry.actual = 'null'
|
213
|
+
cs.generate :entry, entry
|
214
|
+
return
|
215
|
+
end
|
216
|
+
|
217
|
+
ncores = Tweek.ncores
|
218
|
+
mismatches = 0
|
219
|
+
expected_rps = []
|
220
|
+
expected_rss = []
|
221
|
+
irqs.each_with_index do |irq, ix|
|
222
|
+
case entry.value
|
223
|
+
when 'null','none','ignore'
|
224
|
+
next
|
225
|
+
|
226
|
+
when 'aws'
|
227
|
+
case ncores
|
228
|
+
when 8..64
|
229
|
+
expected_rps << ("00000000," * 3) + "0000ff00"
|
230
|
+
expected_rss << ("00000000," * 3) + sprintf("%08x", 1<<ix)
|
231
|
+
when 1..8
|
232
|
+
expected_rps << "0000"
|
233
|
+
expected_rss << sprintf("%04x", 1<<ix)
|
234
|
+
else
|
235
|
+
cs.warn "#{netdev} IRQ strategy '#{entry.value}' can't handle #{ncores} cores"
|
236
|
+
return
|
237
|
+
end
|
238
|
+
|
239
|
+
when 'pin'
|
240
|
+
case ncores
|
241
|
+
when 1..8 # not a lot of choice
|
242
|
+
expected_rps << "0000"
|
243
|
+
expected_rss << "0001"
|
244
|
+
|
245
|
+
when 8..32 # RPS on cores 10-15 and 18-31, RSS tied to 0-7
|
246
|
+
case ix
|
247
|
+
when 0..7
|
248
|
+
expected_rps << ("00000000," * 3) + "fffefe00"
|
249
|
+
expected_rss << ("00000000," * 3) + sprintf("%08x", 1<<(ix+1))
|
250
|
+
else
|
251
|
+
cs.warn "#{netdev} IRQ strategy '#{entry.value}' can't handle IRQ#{ix}"
|
252
|
+
return
|
253
|
+
end
|
254
|
+
|
255
|
+
when 32..64 # Split the work across the two nodes
|
256
|
+
case ix
|
257
|
+
when 0..3 # alloc on node 0 (cpus 0-3)
|
258
|
+
expected_rps << ("00000000," * 2) + "0000ffff," + "0000ffe0"
|
259
|
+
expected_rss << ("00000000," * 3) + sprintf("%08x", 1<<(ix+1))
|
260
|
+
when 4..7 # alloc on node 1 (
|
261
|
+
expected_rps << ("00000000," * 2) + "ffff0000," + "ffe00000"
|
262
|
+
expected_rss << ("00000000," * 3) + sprintf("%08x", 1<<(ix + 9))
|
263
|
+
else
|
264
|
+
cs.warn "#{netdev} IRQ strategy '#{entry.value}' can't handle IRQ#{ix}"
|
265
|
+
return
|
266
|
+
end
|
267
|
+
|
268
|
+
else
|
269
|
+
cs.error "#{entry.lineno}: Can't handle #{ncores} cores in IRQ strategy '#{entry.value}'"
|
270
|
+
return
|
271
|
+
end
|
272
|
+
|
273
|
+
else
|
274
|
+
cs.error "#{entry.lineno}: Unrecognized #{netdev} IRQ strategy '#{entry.value}'"
|
275
|
+
return
|
276
|
+
end
|
277
|
+
end
|
278
|
+
irqs.each_with_index do |irq, ix|
|
279
|
+
actual_rss = Tweek.net_rss(irq)
|
280
|
+
mismatches += cs.assert_equal expected_rss[ix], actual_rss, "#{netdev}_irq_#{irq}_rss"
|
281
|
+
end
|
282
|
+
irqs.each_with_index do |irq, ix|
|
283
|
+
actual_rps = Tweek.net_rps(netdev, ix)
|
284
|
+
mismatches += cs.assert_equal expected_rps[ix], actual_rps, "#{netdev}_irq_#{irq}_rps"
|
285
|
+
end
|
286
|
+
entry.actual = 'null' if mismatches > 0
|
287
|
+
return
|
288
|
+
end
|
289
|
+
|
251
290
|
end
|
252
291
|
|
data/lib/tweek/version.rb
CHANGED
data/lib/tweek.rb
CHANGED
@@ -1,3 +1,64 @@
|
|
1
|
+
# Define data-collection methods so we can easily stub them for tests
|
2
|
+
#
|
1
3
|
module Tweek
|
2
|
-
|
4
|
+
|
5
|
+
def self.bootline
|
6
|
+
@bootline ||= ::File.open("/proc/cmdline", &:read).chomp
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.balance_pid
|
10
|
+
@balance_pid ||= `pgrep irqbalance`.chomp.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
# Determine the queue processing interrupts for the network device
|
14
|
+
# Empirically we observe that the convention for the name in /proc/interrupts varies
|
15
|
+
# so some hacking required...
|
16
|
+
def self.irqs netdev
|
17
|
+
@irqs = ::File.open("/proc/interrupts", &:readlines).grep(/\b#{netdev}\b/)
|
18
|
+
@irqs.reject! {|i| i !~ /\b#{netdev}-Tx-?Rx/} if @irqs.size > 1
|
19
|
+
@irqs.map{|m| m.partition(':')[0].strip}
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.ncores
|
23
|
+
`getconf _NPROCESSORS_ONLN`.chomp.to_i rescue 0
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.clocksource param
|
27
|
+
::File.open("/sys/devices/system/clocksource/#{param}/current_clocksource",&:read).chomp rescue $!.message
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.sysctl name
|
31
|
+
::File.open("/proc/sys/#{name}", &:read).chomp.gsub(/\s+/,' ') rescue $!.message
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.net_driver name
|
35
|
+
::File.basename(::File.readlink("/sys/class/net/#{name}/device/driver"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.blk_param blkdev, name
|
39
|
+
::File.open("/sys/block/#{blkdev}/queue/#{name}", &:read).chomp rescue $!.message
|
40
|
+
end
|
41
|
+
|
42
|
+
# Receive Side Scaling - hardware
|
43
|
+
def self.net_rss irq
|
44
|
+
::File.open("/proc/irq/#{irq}/smp_affinity",&:read).chomp rescue $!.message
|
45
|
+
end
|
46
|
+
|
47
|
+
# Receive Packet Steering - software
|
48
|
+
def self.net_rps netdev, ix
|
49
|
+
::File.open("/sys/class/net/#{netdev}/queues/rx-#{ix}/rps_cpus", &:read).chomp rescue $!.message
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.net_param netdev, name
|
53
|
+
::File.open("/sys/class/net/#{netdev}/#{name}", &:read).chomp.gsub(/\s+/,' ')
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.mounted
|
57
|
+
::File.open("/proc/mounts", &:readlines).map{|m| m.split(' ')}
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.xfsinfo mount
|
61
|
+
info = `xfs_info #{mount} 2>/dev/null`.chomp
|
62
|
+
return $?.exitstatus > 0 ? nil : info
|
63
|
+
end
|
3
64
|
end
|
data/settings/sample.set
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
-
# A documentation-rich sample for
|
1
|
+
# A documentation-rich sample file for Tweek
|
2
|
+
#
|
3
|
+
# This is NOT meant to be a recommended parameter set, it's purpose
|
4
|
+
# is to document the format with real examples and educate on the meaning and effect of
|
5
|
+
# various tuning parameters. Use with caution, YMMV!
|
2
6
|
#
|
3
7
|
# Comments begin with # and extend to the end of the line
|
4
|
-
|
8
|
+
=begin
|
9
|
+
Block comments are Ruby style =begin and =end
|
10
|
+
=end
|
5
11
|
# Conditionals use 'k' for kernel version, 'v' for distro version and 'd' for distro
|
6
12
|
# Version conditionals use the http://guides.rubygems.org/patterns/#semantic-versioning
|
7
13
|
# Distro conditionals follow Ruby syntax and you may use string or regex comparisons
|
@@ -25,12 +31,16 @@ maxcpus = 63 # Set the number of physical cores, eliminates the 'B' hyperthreads
|
|
25
31
|
# intel_idle.max_cstate=1
|
26
32
|
numa = off if k>3.9 # won't move memory around between NUMA zones, useful with large working set
|
27
33
|
|
34
|
+
|
35
|
+
# Recommended for heavy networking activity
|
36
|
+
#
|
28
37
|
SYSCTL
|
29
38
|
vm.min_free_kbytes = 838608
|
30
|
-
vm.
|
31
|
-
vm.zone_reclaim_mode = 1 if k~>3.13.0, k<4.9.0
|
39
|
+
vm.zone_reclaim_mode = 1
|
32
40
|
|
33
41
|
# These parameters taken from Brendan Gregg's Re:Invent talk 2014
|
42
|
+
#
|
43
|
+
SYSCTL
|
34
44
|
net.core.somaxconn = 1000
|
35
45
|
net.core.netdev_max_backlog = 5000
|
36
46
|
net.core.rmem_max = 16777216
|
@@ -47,27 +57,21 @@ net.ipv4.tcp_slow_start_after_idle = 0
|
|
47
57
|
net.ipv4.tcp_tw_reuse = 1
|
48
58
|
net.ipv4.ip_local_port_range = 1024 65535
|
49
59
|
net.ipv4.tcp_abort_on_overflow = 1 # allows a connection that is queued to be reset, not just dropped.
|
50
|
-
net.ipv4.tcp_fin_timeout = 50 if d=~/
|
60
|
+
net.ipv4.tcp_fin_timeout = 50 if d=~/AmazonAMI|RedHat/i
|
51
61
|
|
62
|
+
# Page cache flushing optimization (Brendan Gregg, Re:Invent 2014)
|
52
63
|
# Smoother page cache flushing: background flush earlier, aggressive later
|
53
|
-
# Brendan Gregg, Re:Invent 2014
|
54
64
|
#
|
55
65
|
vm.dirty_ratio = 80
|
56
66
|
vm.dirty_background_ratio = 5
|
57
67
|
vm.dirty_expire_centisecs = 12000
|
58
68
|
|
59
|
-
|
60
|
-
#
|
61
|
-
#
|
62
|
-
net.ipv4.tcp_syn_retries = 0
|
63
|
-
net.ipv4.tcp_synack_retries = 0
|
64
|
-
net.ipv4.tcp_timestamps = 0
|
65
|
-
=end
|
66
|
-
|
67
|
-
NET eth0 # Define one or more network devices
|
68
|
-
# Check the IRQ strategy:
|
69
|
+
NET eth0
|
70
|
+
# Check the IRQ strategy using the 'irqs' parameter:
|
71
|
+
#
|
69
72
|
# aws: Use first numa node, split RSS from RPS
|
70
73
|
# RSS allocated across 0-7 (node 0), RPS on first numa node
|
74
|
+
#
|
71
75
|
# pin: Differs depending on number of cores
|
72
76
|
# 32 Apportion across the single node as follows:
|
73
77
|
# RPS allocated across cores 10-15 and 18-31
|
@@ -75,10 +79,14 @@ NET eth0 # Define one or more network devices
|
|
75
79
|
# 64 Use both NUMA nodes, leave first core free on each node
|
76
80
|
# RPS allocated across remaining cores on each node
|
77
81
|
# RSS allocated across 1-4 (node 0) then 17-20 (node 1)
|
78
|
-
#
|
79
|
-
|
82
|
+
#
|
83
|
+
# balance: Use the irqbalance daemon
|
84
|
+
# null: Ignore this device
|
85
|
+
#
|
86
|
+
irqs = aws
|
87
|
+
# Use the 'driver' parameter for the driver name
|
80
88
|
driver = ena
|
81
|
-
#
|
89
|
+
# Other parameter names match values in /sys/class/net/<device>/ tree
|
82
90
|
mtu = 9001
|
83
91
|
device/driver/module/version = 1.1.3
|
84
92
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tweek
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Townsend
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,7 +65,7 @@ files:
|
|
65
65
|
- README.md
|
66
66
|
- bin/tweek
|
67
67
|
- lib/tweek.rb
|
68
|
-
- lib/tweek/
|
68
|
+
- lib/tweek/file.rb
|
69
69
|
- lib/tweek/section.rb
|
70
70
|
- lib/tweek/version.rb
|
71
71
|
- settings/sample.set
|