Console proxy (fix vatesfr/xo#14).

This commit is contained in:
Julien Fontanet
2015-02-03 17:39:12 +01:00
parent 39fd092055
commit b73de087d2
4 changed files with 91 additions and 10 deletions

View File

@@ -21,6 +21,7 @@ $serveStatic = require 'serve-static'
$API = require './api'
$Connection = require './connection'
$WebServer = require 'http-server-plus'
$wsProxy = require './ws-proxy'
$XO = require './xo'
{$coroutine, $fiberize, $waitEvent, $wait} = require './fibers-utils'
{$fileExists, $wrap} = require './utils'
@@ -45,6 +46,42 @@ $httpListenFailure = (error) ->
#=====================================================================
getVmConsoleUrl = (xo, id) ->
vm = xo.getObject(id, 'VM')
return unless vm?.power_state is 'Running'
{sessionId} = xo.getXAPI(vm)
for console in vm.consoles
if console.protocol is 'rfb'
return "#{console.location}&session_id=#{sessionId}"
return
CONSOLE_PROXY_PATH_RE = /^\/consoles\/(.*)$/
setUpConsoleProxy = (webServer, xo) ->
webSocketServer = new $WSServer({
noServer: true,
})
webServer.on('upgrade', (req, res, head) ->
matches = CONSOLE_PROXY_PATH_RE.exec(req.url)
return unless matches
url = getVmConsoleUrl(xo, matches[1])
return unless url
webSocketServer.handleUpgrade(req, res, head, (connection) ->
$wsProxy(connection, url)
return
)
return
)
return
#=====================================================================
# Main.
exports = module.exports = $coroutine (args) ->
return exports.help() unless (
@@ -128,6 +165,9 @@ exports = module.exports = $coroutine (args) ->
connect.use $bind xo.handleProxyRequest, xo
# WebSocket server for consoles.
setUpConsoleProxy(webServer, xo)
# Create the WebSocket server.
wsServer = new $WSServer {
server: webServer

View File

@@ -328,9 +328,6 @@ module.exports = ->
rule: 'VM'
bind: -> @genval.$poolRef
}
# FIXME: Should be remove ASAP!
$sessionId : -> @genval.$sessionId ? @val.$sessionId
}
#-------------------------------------------------------------------

51
src/ws-proxy.js Normal file
View File

@@ -0,0 +1,51 @@
import assign from 'lodash.assign';
import debug from 'debug';
import WebSocket from 'ws';
debug = debug('xo:wsProxy');
let defaults = {
// Automatically close the client connection when the remote close.
autoClose: true,
// Reject secure connections to unauthorized remotes (bad CA).
rejectUnauthorized: false,
};
// Proxy a WebSocket `client` to a remote server which has `url` as
// address.
export default function wsProxy(client, url, opts) {
opts = assign({}, defaults, opts);
let remote = new WebSocket(url, {
protocol: opts.protocol || client.protocol,
rejectUnauthorized: opts.rejectUnauthorized,
}).once('open', function () {
debug('connected to', url);
}).once('close', function () {
debug('remote closed');
if (opts.autoClose) {
client.close();
}
}).once('error', function (error) {
debug('remote error', error);
}).on('message', function (message) {
client.send(message, function (error) {
if (error) {
debug('client send error', error);
}
});
});
client.once('close', function () {
debug('client closed');
remote.close();
}).on('message', function (message) {
remote.send(message, function (error) {
if (error) {
debug('remote send error', error);
}
});
});
}

View File

@@ -285,9 +285,6 @@ class $XO extends $EventEmitter
# Normalizes the records.
normalizeObject pool, ref, 'pool'
# FIXME: Remove this security flaw (currently necessary for consoles).
pool.$sessionId = xapi.sessionId
objects[ref] = pool
# Then retrieve all other objects.
@@ -335,10 +332,6 @@ class $XO extends $EventEmitter
# Normalizes the object.
normalizeObject object, ref, type
# FIXME: Remove this security flaw (currently necessary
# for consoles).
object.$sessionId = xapi.sessionId if type is 'pool'
# Adds the object to the corresponding list (and ensures
# it is not in the other).
if operation is 'del'