tweek 0.9.9 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|