6 attr_reader :returncode, :stdout, :stderr
8 def initialize(vm, cmd, options = {})
9 @returncode, @stdout, @stderr = VMCommand.execute(vm, cmd, options)
12 def VMCommand.wait_until_remote_shell_is_up(vm, timeout = 30)
14 SystemTimer.timeout(timeout) do
15 VMCommand.execute(vm, "true", { :user => "root", :spawn => false })
18 raise "Remote shell seems to be down"
22 # The parameter `cmd` cannot contain newlines. Separate multiple
23 # commands using ";" instead.
24 # If `:spawn` is false the server will block until it has finished
25 # executing `cmd`. If it's true the server won't block, and the
26 # response will always be [0, "", ""] (only used as an
27 # ACK). execute() will always block until a response is received,
28 # though. Spawning is useful when starting processes in the
29 # background (or running scripts that does the same) like the
30 # vidalia-wrapper, or any application we want to interact with.
31 def VMCommand.execute(vm, cmd, options = {})
32 options[:user] ||= "root"
33 options[:spawn] ||= false
34 type = options[:spawn] ? "spawn" : "call"
35 socket = TCPSocket.new("127.0.0.1", vm.get_remote_shell_port)
36 STDERR.puts "#{type}ing as #{options[:user]}: #{cmd}" if $debug
38 socket.puts(JSON.dump([type, options[:user], cmd]))
39 s = socket.readline(sep = "\0").chomp("\0")
43 STDERR.puts "#{type} returned: #{s}" if $debug
46 rescue JSON::ParserError
47 # The server often returns something unparsable for the very
48 # first execute() command issued after a VM start/restore
49 # (generally from wait_until_remote_shell_is_up()) presumably
50 # because the TCP -> serial link isn't properly setup yet. All
51 # will be well after that initial hickup, so we just retry.
52 return VMCommand.execute(vm, cmd, options)
57 return @returncode == 0