Search code examples
mongodbcentoschef-infrachef-recipecookbook

chef won't start my init.d service


I'm creating a service via this mongo doc.

I have this in my recipe to install the service via a template:

service 'disable-transparent-hugepages' do
  supports :restart => true, :start => true, :stop => true, :reload => true
  action :nothing
end

template 'disable-transparent-hugepages' do
  path '/etc/init.d/disable-transparent-hugepages'
  source 'disable-transparent-hugepages.erb'
  owner 'root'
  group 'root'
  mode '0755'
  notifies :enable, 'service[disable-transparent-hugepages]'
  notifies :start, 'service[disable-transparent-hugepages]'
end

When I run the recipe multiple times it pulls the init.d script to the right location, but if I check the status of it I see this: enter image description here

After I confirmed its installed I added a line in the recipe to just start the service like normal:

service 'disable-transparent-hugepages' do
  action :start
end

But still it isn't started.

If I manually start it I can see it working: enter image description here

Why isn't chef starting the service?

Edit: Ok so I found this SO question that says my problem might be that I need the init.d script (found in the link to the mongo doc) needs to exit with a non 0 return code. I am unsure though how to have the script return a non zero code when checking the status.


Solution

  • This has to do with the assumption on what the script support as command.

    Quoting chef doc about service resource about the supports property (emphasis on last line is mine):

    supports Ruby Type: Hash

    A list of properties that controls how the chef-client is to attempt to manage a service: :restart, :reload, :status. For :restart, the init script or other service provider can use a restart command; if :restart is not specified, the chef-client attempts to stop and then start a service. For :reload, the init script or other service provider can use a reload command. For :status, the init script or other service provider can use a status command to determine if the service is running; if :status is not specified, the chef-client attempts to match the service_name against the process table as a regular expression, unless a pattern is specified as a parameter property. Default value: { :restart => false, :reload => false, :status => false } for all platforms (except for the Red Hat platform family, which defaults to { :restart => false, :reload => false, :status => true }.)

    when status is true, the provider try to call it, if it returns 0 the service is supposed to be running.

    According to the link you gave, the script only support start and hence return 0 when called with parameter status.

    One way to fix this is using a more precise definition of the service like this:

    service 'disable-transparent-hugepages' do
      supports :restart => false, :start => true, :stop => false, :reload => false, :status => false
      action :start
    end
    

    Another way would be to fix the init script to implement the status command, returning 0 if the file have the proper content and 1 if not.

    Something along this line as status case would do I think (untested):

    status)
    if [ -d /sys/kernel/mm/transparent_hugepage ]; then
      thp_path=/sys/kernel/mm/transparent_hugepage
    elif [ -d /sys/kernel/mm/redhat_transparent_hugepage ]; then
      thp_path=/sys/kernel/mm/redhat_transparent_hugepage
    else
      return 0
    fi
    
    re='^(0|no)$'
    return [[ $(cat ${thp_path}/khugepaged/defrag) =~ $re ]]
    ;;
    

    My opinion:

    As it is not exactly a real service, I would go to manage those files directly instead of using a pseudo service for this.