title: How to connect to a xen console via Net::SSH (ruby)
body: <p>I'm trying to write some ruby code that could connect to a XenServer VMs console (via <code>/usr/lib/xen/bin/xenconsole</code>) by first SSHing into the Host server then accessing the VMs console from the command line.</p>
  
  <p>To do this I'm using the ruby library <code>Net::SSH</code>.  I'm doing ok logging into the Host server via SSH and running the commands to get the DOM id of the VM.  The problem comes when I'm running the xenconsole command.  You have to press "enter" after the command to get dumped into the console, then you have to press <code>CTRL + ]</code> to exit the VM's console and get back to the Host's command line.</p>
  
  <p>I'm using the code below, but it hangs at the "press enter" point and doesn't give any feedback from the SSH channel either as STDOUT or STDERR.  What can I do to get to the VM's console to execute commands on the VM?  Then how do I send the <code>CTRL + ]</code> characters?</p>
  
  <pre><code>def execute_remote_console(hostname, port, username, password, uuid)
  
  begin
  
  Net::SSH.start( hostname, username, :password =&gt; password, :port =&gt; port ) do |session|
  
    dom_list_line = session.exec! "list_domains | grep #{uuid}"
    if dom_list_line.match(/(\d+)/)
      dom_id = $1
      puts "found #{uuid} on DOM #{dom_id}"
    else
      raise "couldn't find DOM id"
    end
  
    console_command = "/usr/lib/xen/bin/xenconsole #{dom_id}"
    puts "connecting to console: #{console_command}"
  
    session.exec!( console_command ) do |ch,stream,data|
  
      puts "pressing (enter)"
      ch.send_data "\n"
  
      case stream
        when :stderr
          puts "E-&gt; #{data}"
          ch.exec "cat /etc/hostname" do |chan, success|
            raise "could not execute command" unless success
  
            # "on_data" is called when the process writes something to stdout
            chan.on_data do |c, data|
              $STDOUT.print data
            end
  
            # "on_extended_data" is called when the process writes something to stderr
            chan.on_extended_data do |c, type, data|
              $STDERR.print data
            end
  
            chan.on_close { puts "done!" }
          end
        when :stdout
          puts "O-&gt; #{data}"
        else
          puts" other: #{data}"
      end 
  
    end #end session.exec
  
  
  end #end SSH.start
  
  
    rescue
      puts "\t\t\tok (#{$!.message})" 
    end 
  
  end #end function
  </code></pre>