diff --git a/plugins/guests/linux/cap/reboot.rb b/plugins/guests/linux/cap/reboot.rb new file mode 100644 index 000000000..30c9c984f --- /dev/null +++ b/plugins/guests/linux/cap/reboot.rb @@ -0,0 +1,42 @@ +require "log4r" + +module VagrantPlugins + module GuestLinux + module Cap + class Reboot + MAX_REBOOT_RETRY_DURATION = 120 + + def self.reboot(machine) + @logger = Log4r::Logger.new("vagrant::linux::reboot") + reboot_script = "reboot" + + comm = machine.communicate + + @logger.debug("Issuing reboot command for guest") + comm.sudo(reboot_script) + + machine.ui.info(I18n.t("vagrant.guests.capabilities.rebooting")) + + @logger.debug("Waiting for machine to finish rebooting") + + wait_remaining = MAX_REBOOT_RETRY_DURATION + begin + wait_for_reboot(machine) + rescue Vagrant::Errors::MachineGuestNotReady => e + raise if wait_remaining < 0 + @logger.warn("Machine not ready, cannot start reboot yet. Trying again") + sleep(5) + wait_remaining -= 5 + retry + end + end + + def self.wait_for_reboot(machine) + while !machine.guest.ready? + sleep 10 + end + end + end + end + end +end diff --git a/plugins/guests/linux/plugin.rb b/plugins/guests/linux/plugin.rb index e4752571e..777d5cbec 100644 --- a/plugins/guests/linux/plugin.rb +++ b/plugins/guests/linux/plugin.rb @@ -82,6 +82,16 @@ module VagrantPlugins Cap::ReadIPAddress end + guest_capability(:linux, :wait_for_reboot) do + require_relative "cap/reboot" + Cap::Reboot + end + + guest_capability(:linux, :reboot) do + require_relative "cap/reboot" + Cap::Reboot + end + guest_capability(:linux, :remove_public_key) do require_relative "cap/public_key" Cap::PublicKey diff --git a/test/unit/plugins/guests/linux/cap/reboot_test.rb b/test/unit/plugins/guests/linux/cap/reboot_test.rb new file mode 100644 index 000000000..4c9f8f751 --- /dev/null +++ b/test/unit/plugins/guests/linux/cap/reboot_test.rb @@ -0,0 +1,50 @@ +require_relative "../../../../base" + +require Vagrant.source_root.join("plugins/guests/linux/cap/reboot") + +describe "VagrantPlugins::GuestLinux::Cap::Reboot" do + let(:described_class) do + VagrantPlugins::GuestLinux::Plugin.components.guest_capabilities[:linux].get(:wait_for_reboot) + end + + let(:machine) { double("machine") } + let(:guest) { double("guest") } + let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + let(:ui) { double("ui") } + + before do + allow(machine).to receive(:communicate).and_return(communicator) + allow(machine).to receive(:guest).and_return(guest) + allow(machine.guest).to receive(:ready?).and_return(true) + allow(machine).to receive(:ui).and_return(ui) + allow(ui).to receive(:info) + end + + after do + communicator.verify_expectations! + end + + describe ".reboot" do + it "reboots the vm" do + allow(communicator).to receive(:execute) + + expect(communicator).to receive(:execute).with(/reboot/, nil).and_return(0) + expect(described_class).to receive(:wait_for_reboot) + + described_class.reboot(machine) + end + + context "user output" do + before do + allow(communicator).to receive(:execute) + allow(described_class).to receive(:wait_for_reboot) + end + + after { described_class.reboot(machine) } + + it "sends message to user that guest is rebooting" do + expect(ui).to receive(:info) + end + end + end +end