2013-07-28 05:17:05 +00:00
|
|
|
module Vagrant
|
|
|
|
module LXC
|
|
|
|
class SudoWrapper
|
|
|
|
# Include this so we can use `Subprocess` more easily.
|
|
|
|
include Vagrant::Util::Retryable
|
|
|
|
|
2014-07-25 00:45:04 +00:00
|
|
|
attr_reader :wrapper_path
|
|
|
|
|
2017-12-13 21:35:16 +00:00
|
|
|
def self.dest_path
|
|
|
|
"/usr/local/bin/vagrant-lxc-wrapper"
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize()
|
|
|
|
@wrapper_path = Pathname.new(SudoWrapper.dest_path).exist? && SudoWrapper.dest_path || nil
|
2013-11-06 03:10:40 +00:00
|
|
|
@logger = Log4r::Logger.new("vagrant::lxc::sudo_wrapper")
|
2013-07-28 05:17:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def run(*command)
|
2014-04-08 17:58:07 +00:00
|
|
|
options = command.last.is_a?(Hash) ? command.last : {}
|
2017-01-29 18:53:09 +00:00
|
|
|
|
|
|
|
# Avoid running LXC commands with a restrictive umask.
|
|
|
|
# Otherwise disasters occur, like the container root directory
|
|
|
|
# having permissions `rwxr-x---` which prevents the `vagrant`
|
|
|
|
# user from accessing its own home directory; among other
|
|
|
|
# problems, SSH cannot then read `authorized_keys`!
|
|
|
|
old_mask = File.umask
|
|
|
|
File.umask(old_mask & 022) # allow all `r` and `x` bits
|
|
|
|
|
|
|
|
begin
|
|
|
|
if @wrapper_path && !options[:no_wrapper]
|
|
|
|
command.unshift @wrapper_path
|
|
|
|
execute *(['sudo'] + command)
|
|
|
|
else
|
|
|
|
execute *(['sudo', '/usr/bin/env'] + command)
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
File.umask(old_mask)
|
2015-09-23 18:15:28 +00:00
|
|
|
end
|
2013-07-28 05:17:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# TODO: Review code below this line, it was pretty much a copy and
|
|
|
|
# paste from VirtualBox base driver and has no tests
|
|
|
|
def execute(*command, &block)
|
|
|
|
# Get the options hash if it exists
|
|
|
|
opts = {}
|
|
|
|
opts = command.pop if command.last.is_a?(Hash)
|
|
|
|
|
|
|
|
tries = 0
|
|
|
|
tries = 3 if opts[:retryable]
|
|
|
|
|
|
|
|
sleep = opts.fetch(:sleep, 1)
|
|
|
|
|
|
|
|
# Variable to store our execution result
|
|
|
|
r = nil
|
|
|
|
|
|
|
|
retryable(:on => LXC::Errors::ExecuteError, :tries => tries, :sleep => sleep) do
|
|
|
|
# Execute the command
|
|
|
|
r = raw(*command, &block)
|
|
|
|
|
|
|
|
# If the command was a failure, then raise an exception that is
|
|
|
|
# nicely handled by Vagrant.
|
|
|
|
if r.exit_code != 0
|
|
|
|
if @interrupted
|
2017-08-09 10:31:15 +00:00
|
|
|
raise LXC::Errors::SubprocessInterruptError, command.inspect
|
2013-07-28 05:17:05 +00:00
|
|
|
else
|
2014-02-02 21:27:08 +00:00
|
|
|
raise LXC::Errors::ExecuteError,
|
2016-02-16 11:13:53 +00:00
|
|
|
command: command.inspect, stderr: r.stderr, stdout: r.stdout, exitcode: r.exit_code
|
2013-07-28 05:17:05 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return the output, making sure to replace any Windows-style
|
|
|
|
# newlines with Unix-style.
|
2013-10-11 22:15:12 +00:00
|
|
|
stdout = r.stdout.gsub("\r\n", "\n")
|
2013-10-11 21:16:09 +00:00
|
|
|
if opts[:show_stderr]
|
2013-10-11 22:15:12 +00:00
|
|
|
{ :stdout => stdout, :stderr => r.stderr.gsub("\r\n", "\n") }
|
2013-10-11 21:16:09 +00:00
|
|
|
else
|
2013-10-11 22:15:12 +00:00
|
|
|
stdout
|
2013-10-11 21:16:09 +00:00
|
|
|
end
|
2013-07-28 05:17:05 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def raw(*command, &block)
|
|
|
|
int_callback = lambda do
|
|
|
|
@interrupted = true
|
|
|
|
@logger.info("Interrupted.")
|
|
|
|
end
|
|
|
|
|
|
|
|
# Append in the options for subprocess
|
|
|
|
command << { :notify => [:stdout, :stderr] }
|
|
|
|
|
|
|
|
Vagrant::Util::Busy.busy(int_callback) do
|
|
|
|
Vagrant::Util::Subprocess.execute(*command, &block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|