(#19162) Execute shutdown command after puppet exits

Previously, there was a race condition between the time that puppet exited and
when the OS rebooted the system. This is because we were requesting a shutdown
(reboot) in `timeout` seconds, but puppet sends a report before exiting, and the report
is processed synchronously by the master. So it was possible for puppet to still be
running when the OS reboots the system.

This commit creates a Watcher class whose job is to wait for the puppet process
to complete, and then execute a command at the end.