4

I'm trying to automate disabling the Transparent Huge Pages (THP) Settings for MongoDB using a Chef Recipe.

The THP setting is explained here: MongoDocs THP Settings

I'm trying to follow the first option "In Boot-Time Configuration (Preferred)" by editing the grub configuration file at "/etc/grub.conf"

All I need to do is append "transparent_hugepage=never" to the end of the existing line that starts with "kernel "

I know I can replace a line with Chef::Util::FileEdit, using something like this:

ruby_block "replace_line" do
  block do
    file = Chef::Util::FileEdit.new("/etc/grub.conf")
    file.search_file_replace_line("/kernel/", "kernel <kernel path> <kernel options> transparent_hugepage=never")
    file.write_file
  end
end

but I need to keep the existing kernel path and kernel options.

I've tried playing around with Chef::Util::Editor, but haven't been successful initializing the constructor. Chef::Util::FileEdit is initialized with a file path (per above), but the ruby docs say that Chef::Util::Editor is initialized with "lines". I've tried

lines = Chef::Util::Editor.new(<lines>) 

where <lines> = file path, = Chef::Util::FileEdit.new(), and = 'test string', but nothing seems to work.

Does anyone have any experience with the Chef::Util::Editor? Or a better solution?

Thanks

Derek Soike
  • 11,238
  • 3
  • 79
  • 74
  • 1
    Is the file static, or are there other configurations that may be dynamic? If they file is static, then you can add the configuration file to the cookbook's files and then replace the previous config file using a cookbook_file directive. – Josh Edwards Apr 30 '15 at 15:55
  • Its been a while since this question was opened. Did you ever figure out a solution? – spuder Aug 14 '15 at 03:51
  • @spuder I never figured out how to modify a single line in a config file with chef. Wish I was a master chef, but pretty sure I'm still just working the dish pit. If you're trying to disable THP settings for MongoDB, I posted what I ended up doing as an answer. – Derek Soike Aug 15 '15 at 17:00

4 Answers4

0

I never figured out how to modify a single line in a config file using Chef, but here's the recipe I ended up using to disable THP settings for MongoDB.

Recipe: Install MongoDB

# Install MongoDB on Amazon Linux
# http://docs.mongodb.org/manual/tutorial/install-mongodb-on-amazon/

# 1: configure the package management system (yum)

# 2: install mongodb

# 3: configure mongodb settings

# 3.A: give mongod permission to files
# data & log directories (everything in /srv/mongodb)
# http://stackoverflow.com/questions/7948789/mongodb-mongod-complains-that-there-is-no-data-db-folder
execute "mongod_permission" do
    command "sudo chown -R mongod:mongod /srv/mongodb"
    #command "sudo chown mongod:mongod /var/run/mongodb/mongod.pid"
    #command "sudo chown -R $USER /srv/mongodb"
end

# 3.B: edit Transparent Huge Pages (THP) Settings
# get rid of mongod startup warning
# http://docs.mongodb.org/manual/reference/transparent-huge-pages/#transparent-huge-pages-thp-settings

# 3.B.1: disable
execute "disable_thp_khugepaged_defrag" do
    command "echo 0 | sudo tee /sys/kernel/mm/transparent_hugepage/khugepaged/defrag" # different b/c file doesn't have options list
end
execute "disable_thp_hugepage_defrag" do
    command "echo 'never > /sys/kernel/mm/transparent_hugepage/defrag' | sudo tee --append /sys/kernel/mm/transparent_hugepage/defrag"
end
execute "disable_thp_hugepage_enables" do
    command "echo 'never > /sys/kernel/mm/transparent_hugepage/enabled' | sudo tee --append /sys/kernel/mm/transparent_hugepage/enabled"
end

# 3.B.2: verify disabled on reboot
template "/etc/rc.local" do
    source "init-rc.local.erb"
    owner 'root'
    group 'root'
    mode '0775'
end

# 4: use upstart & monit to keep mongod alive

Template: init-rc.local.erb

touch /var/lock/subsys/local

if test -f /sys/kernel/mm/transparent_hugepage/khugepaged/defrag; then
  echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
  echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
  echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
Derek Soike
  • 11,238
  • 3
  • 79
  • 74
0

The problem with your own solution is the template can be overwritten by another recipe with it's own rc.local template.

To change that, I add the lines to the existing rc.local

execute "disable_thp_hugepage_defrag" do
    command "sudo sed -i -e '$i \\echo never > /sys/kernel/mm/transparent_hugepage/defrag\\n' /etc/rc.local"
    not_if 'grep -c "transparent_hugepage/defrag" /etc/rc.local'
end
execute "disable_thp_hugepage_enables" do
    command "sudo sed -i -e '$i \\echo never > /sys/kernel/mm/transparent_hugepage/enabled\\n' /etc/rc.local"
    not_if 'grep -c "transparent_hugepage/enabled" /etc/rc.local'
end

The grep makes sure that the line is not already in it.

Maybe chef has something better to manage that?

Constantin Guay
  • 1,604
  • 2
  • 15
  • 26
0

We can efficietly replace contents of file by grouping the elements

e.g. appending "transparent_hugepage=never" to the end of the existing line that starts with "kernel "

ruby_block "replace_line" do
  block do
    file = Chef::Util::FileEdit.new("/etc/grub.conf")
    file.search_file_replace_line(/kernel.*/, '\0 tansparent_hugepage=never')
    file.write_file
  end
end

\0 adds whole mached string

note: ' '(single quote)

zero323
  • 322,348
  • 103
  • 959
  • 935
devzone
  • 49
  • 1
  • 7
0

I disabled hugepages by replicating the following in chef (looks the same as above but with the addition of a not_if statement):

echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

E.G

execute "disable_hugepage_defrag" do
  not_if "grep -F '[never]' /sys/kernel/mm/transparent_hugepage/defrag"
  command "echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag"
end

I have also had success inserting lines with file.insert_line_if_no_match the ruby line replace feature will probably work for you.

search_file_replace_line(regex, newline) ⇒ Object

ruby_block 'replace_line' do
  block do
    file = Chef::Util::FileEdit.new('/path/to/file')
    file.search_file_replace_line('/Line to find/', 'Line to replace with')
    file.write_file
  end
end
jorfus
  • 2,804
  • 27
  • 23