Is there a way for a Chef recipe to continue after a reboot (Windows)?

6.8k Views Asked by At

I am trying to use Chef to automate installation/deployment of an older version of a Windows product (Sharepoint 2007, specifically), and I almost have it working, but, at one point during the installation, the installer encounters an "application compatibility" problem and pops up a window that asks whether to continue or not. If I click to continue, the installation continues to the end, and it works properly.

I found a way to avoid the popup, by adding an "Appcompat" key in the windows registry, but if I use regedit to add the key during the Chef run, I have to get Chef to reboot the machine and then to continue with the rest of the installation afterwards.

I've tried a recipe with something like:

reboot 'Restart Computer' do
  action :nothing
end


powershell_script "install-Sharepoint2007-PREREQUISITES" do
code <<-EOH

regedit /s .\appcompat.reg

EOH

notifies :reboot_now, 'reboot[Restart Computer]', :immediately

end


powershell_script "install-Sharepoint2007" do
code <<-EOH

... the rest of the installation....

EOH

notifies :reboot_now, 'reboot[Restart Computer]', :immediately

end

but the processing basically stops, after the reboot after setting the registry key.

So I was wondering: Is there a way to do this with Chef?

Thanks, Jim

EDIT:

I find it hard to use just the comments because of lack of formatting so I'm adding information on what I have tried thus far here.

Basically, the only way I can get the chef-client to run in a scheduled task so far is to do a "ONCE" scheduled task, setting the time for the task to run (so far, I'm manually setting the time in my schtasks command, just to test).

When I do that, and set the "/RU" to SYSTEM, I can see the "chef-client -o" start to run and it actually seems to complete, but I see errors in the Sharepoint installer logs, and in particular, it appears that some of the steps in the psconfig (the Sharepoint command line configuration tool) are failing.

I think/guess that the reason for those failures is that the schtasks is running the "chef-client -o" as the wrong Windows user.

The thing is, if I run the "chef-client -o" on the 2nd part cookbook "manually", i.e., if I log into the Windows machine and type:

chef-client -o install-SHAREPOINT-PART2

Then, Sharepoint gets installed and configured correctly.

So, the thing I'm stuck on now is when I do that same "chef-client -o" command via schtasks, what should I use as the "/RU" and "/RP" for the schtasks command?

Thanks, Jim

EDIT 2: Sorry, I forgot to include the schtasks line in the first cookbook/recipe, which sets up the task for the second cookbook/recipe chef run:

schtasks /create /tn Task_Name /tr "chef-client -o install-SHAREPOINT2007FULL-PART2" /sc once /RU "SYSTEM" /SD 06/27/2015 /ST 12:30

EDIT 3: The original reason that I was looking into this (having Chef work "through" a reboot) was that as part of installing Sharepoint, I had to set a Windows registry key, and I thought that I had to reboot to make that registry change effective for the rest of the install process.

However, I did some testing yesterday, and it appears that is not the case. I can make the registry change, then do the rest of the installation, without having to reboot in between.

So, bottom line is that I didn't need to process after the reboot after all.

But anyway, hopefully some of the info here may help someone later. The main thing I found was was I couldn't get it to work using ONSTART with the /Z /V1... I had to use the ONCE and would have had to have code in my Chef recipe to figure out the date and time to fire the ONCE tasks.

4

There are 4 best solutions below

6
On

All in all I would say not as-is.

You have to tweak things to work there by doing a two pass run.

Your first pass will add the registry information, plan a chef-run in a few minutes (targetting after the reboot) if chef is not installed as a service, and reboot.

The second pass should go over the registry part and do the rest of the installation.

According to your code and assuming Chef is installed as an autostarting service on the node you could add just a guard to your powershell resource like this:

powershell_script "install-Sharepoint2007-PREREQUISITES" do
  code <<-EOH
    regedit /s .\appcompat.reg
  EOH
  notifies :reboot_now, 'reboot[Restart Computer]', :immediately
  not_if registry_data_exists?(
              KEY_PATH,
              { :name => "NAME", :type => TYPE, :data => VALUE },
              ARCHITECTURE
         )
end

Doc on the guards here and on the registry recipe helpers here

0
On

You can have chef run a scheduled task on start up to run chef.

windows_task 'Chef client' do
  user 'SYSTEM'
  command 'chef-client -L C:\chef\chef-client.log'
  run_level :highest
  frequency :onstart
  frequency_modifier 30
  action :create
end

Then when the node reboots, chef will run again.

Consider the following recipe that joins a windows computer to a domain, reboots, runs chef (as a scheduled task), then deletes the scheduled task.

https://github.com/NetDocuments/ad-join-cookbook/blob/master/resources/domain_join.rb

Update There is a RFC proposal to change the exit codes of chef to allow for intellegently handling reboots.

CHEF RFC #62

0
On

Use rakefile to trigger the converge. You should also give some sleep time after windows reboot and re-converge again: Here's and example.

sh 'bundle exec kitchen converge'
      sleep 120
      sh 'bundle exec kitchen verify'
0
On

I have done it using FLAG file method, example given below. Example of domain join-

---------------------------Script Start------------------------

    powershell_script 'Domain_Join' do
    guard_interpreter :powershell_script
    code -domainJoin
    $currentTime = Get-Date
    $currentTimeString = $currentTime.ToString()

  $systemDomain = (Get-WmiObject Win32_ComputerSystem).Domain
  If (($systemDomain) -eq 'domainName')
  { 
    Try {
  write-host "$env:computerName is DOMAIN MEMBER"
  Remove-Item C:\\DomainJoinFlag.txt -ErrorAction Stop
  Unregister-ScheduledTask -TaskName "Chef client schedule_DJ" -Confirm:$false
  } # end of Try
          Catch [System.Management.Automation.ItemNotFoundException]
            { write-host "Server is already domain member, Or Exception raised due to either missing FLAG file or Server startup schedule task configuration." 
              eventcreate /t INFORMATION /ID 0909 /L APPLICATION /SO "ChefClient_$env:computerName" /D "Server is already domain member, Or Exception raised due to either missing FLAG file or Server startup schedule task configuration. Refer to the CHEF reciepie for DomainJoin or check Administrative credentials for creting schedule task"}
            }
    else { write-host "$env:computerName is NOT domain member, joining the server to the domain. Server will be rebooting in a while..."
            eventcreate /t INFORMATION /ID 0909 /L APPLICATION /SO "ChefClient_$env:computerName" /D "Joining the server : $env:ComputerName to the domain ININLAB.COM (Server Time): $currentTimeString"
            New-Item C:\\DomainJoinFlag.txt -type file -force
            write-host "$env:computerName DOMAIN JOIN INITIATED for the server"
            $cred = New-Object System.Management.Automation.PsCredential("domain\\domain_user", (ConvertTo-SecureString "Password" -AsPlainText -Force))
            Add-Computer -DomainName "domainName" -Credential $cred -OUPath "OU=HyperV,OU=Infrastructure,OU=Servers,DC=domain,DC=name"
            shutdown -r -t 120
            } #end_of_else
            domainJoin
  notifies :run, 'windows_task[Chef client schedule_DJ]', :immediately
end

windows_task 'Chef client schedule_DJ' do
  user 'SYSTEM'
  command 'chef-client -L C:\chef\chef-client_after_reboot_domainJoin.log'
  run_level :highest
  frequency :onstart
  frequency_modifier 30
  action :create
  only_if { ::File.exist?('C:\\DomainJoinFlag.txt') }
end

---------------------------Script Ends------------------------