| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- #!/usr/bin/env python
- # vim: tabstop=4 shiftwidth=4 softtabstop=4
- # Copyright (c) 2012 Openstack, LLC.
- # All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License"); you may
- # not use this file except in compliance with the License. You may obtain
- # a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- # License for the specific language governing permissions and limitations
- # under the License.
- #!/usr/bin/env python
- '''
- Websocket proxy that is compatible with Openstack Nova.
- Leverages websockify by Joel Martin
- '''
- import Cookie
- from oslo.config import cfg
- import socket
- import sys
- import websockify
- from nova import config
- from nova import context
- from nova import utils
- from nova.openstack.common import rpc
- opts = [
- cfg.BoolOpt('record',
- default=False,
- help='Record sessions to FILE.[session_number]'),
- cfg.BoolOpt('daemon',
- default=False,
- help='Become a daemon (background process)'),
- cfg.BoolOpt('ssl_only',
- default=False,
- help='Disallow non-encrypted connections'),
- cfg.BoolOpt('source_is_ipv6',
- default=False,
- help='Source is ipv6'),
- cfg.StrOpt('cert',
- default='self.pem',
- help='SSL certificate file'),
- cfg.StrOpt('key',
- default=None,
- help='SSL key file (if separate from cert)'),
- cfg.StrOpt('web',
- default='.',
- help='Run webserver on same port. Serve files from DIR.'),
- cfg.StrOpt('novncproxy_host',
- default='0.0.0.0',
- help='Host on which to listen for incoming requests'),
- cfg.IntOpt('novncproxy_port',
- default=6080,
- help='Port on which to listen for incoming requests'),
- ]
- CONF = cfg.CONF
- CONF.register_cli_opts(opts)
- # As of nova commit 0b11668e64450039dc071a4a123abd02206f865f we must
- # manually register the rpc library
- if hasattr(rpc, 'register_opts'):
- rpc.register_opts(CONF)
- class NovaWebSocketProxy(websockify.WebSocketProxy):
- def __init__(self, *args, **kwargs):
- websockify.WebSocketProxy.__init__(self, *args, **kwargs)
- def new_client(self):
- """
- Called after a new WebSocket connection has been established.
- """
- cookie = Cookie.SimpleCookie()
- cookie.load(self.headers.getheader('cookie'))
- token = cookie['token'].value
- ctxt = context.get_admin_context()
- connect_info = rpc.call(ctxt, 'consoleauth',
- {'method': 'check_token',
- 'args': {'token': token}})
- if not connect_info:
- raise Exception("Invalid Token")
- host = connect_info['host']
- port = int(connect_info['port'])
- # Connect to the target
- self.msg("connecting to: %s:%s" % (
- host, port))
- tsock = self.socket(host, port,
- connect=True)
- # Handshake as necessary
- if connect_info.get('internal_access_path'):
- tsock.send("CONNECT %s HTTP/1.1\r\n\r\n" %
- connect_info['internal_access_path'])
- while True:
- data = tsock.recv(4096, socket.MSG_PEEK)
- if data.find("\r\n\r\n") != -1:
- if not data.split("\r\n")[0].find("200"):
- raise Exception("Invalid Connection Info")
- tsock.recv(len(data))
- break
- if self.verbose and not self.daemon:
- print(self.traffic_legend)
- # Start proxying
- try:
- self.do_proxy(tsock)
- except:
- if tsock:
- tsock.shutdown(socket.SHUT_RDWR)
- tsock.close()
- self.vmsg("%s:%s: Target closed" % (host, port))
- raise
- if __name__ == '__main__':
- if CONF.ssl_only and not os.path.exists(CONF.cert):
- parser.error("SSL only and %s not found" % CONF.cert)
- # Setup flags
- config.parse_args(sys.argv)
- # Create and start the NovaWebSockets proxy
- server = NovaWebSocketProxy(listen_host=CONF.novncproxy_host,
- listen_port=CONF.novncproxy_port,
- source_is_ipv6=CONF.source_is_ipv6,
- verbose=CONF.verbose,
- cert=CONF.cert,
- key=CONF.key,
- ssl_only=CONF.ssl_only,
- daemon=CONF.daemon,
- record=CONF.record,
- web=CONF.web,
- target_host='ignore',
- target_port='ignore',
- wrap_mode='exit',
- wrap_cmd=None)
- server.start_server()
|