]> git.proxmox.com Git - mirror_novnc.git/blob - utils/nova-novncproxy
7e5afbd0c0e1711855cf44b01e79b36f9e360781
[mirror_novnc.git] / utils / nova-novncproxy
1 #!/usr/bin/env python
2 # vim: tabstop=4 shiftwidth=4 softtabstop=4
3
4 # Copyright (c) 2012 Openstack, LLC.
5 # All Rights Reserved.
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License"); you may
8 # not use this file except in compliance with the License. You may obtain
9 # a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 # License for the specific language governing permissions and limitations
17 # under the License.
18 #!/usr/bin/env python
19
20 '''
21 Websocket proxy that is compatible with Openstack Nova.
22 Leverages websockify by Joel Martin
23 '''
24
25 import Cookie
26 from oslo.config import cfg
27 import socket
28 import sys
29
30 import websockify
31
32 from nova import config
33 from nova import context
34 from nova import utils
35 from nova.openstack.common import rpc
36
37
38 opts = [
39 cfg.BoolOpt('record',
40 default=False,
41 help='Record sessions to FILE.[session_number]'),
42 cfg.BoolOpt('daemon',
43 default=False,
44 help='Become a daemon (background process)'),
45 cfg.BoolOpt('ssl_only',
46 default=False,
47 help='Disallow non-encrypted connections'),
48 cfg.BoolOpt('source_is_ipv6',
49 default=False,
50 help='Source is ipv6'),
51 cfg.StrOpt('cert',
52 default='self.pem',
53 help='SSL certificate file'),
54 cfg.StrOpt('key',
55 default=None,
56 help='SSL key file (if separate from cert)'),
57 cfg.StrOpt('web',
58 default='.',
59 help='Run webserver on same port. Serve files from DIR.'),
60 cfg.StrOpt('novncproxy_host',
61 default='0.0.0.0',
62 help='Host on which to listen for incoming requests'),
63 cfg.IntOpt('novncproxy_port',
64 default=6080,
65 help='Port on which to listen for incoming requests'),
66 ]
67 CONF = cfg.CONF
68 CONF.register_cli_opts(opts)
69
70 # As of nova commit 0b11668e64450039dc071a4a123abd02206f865f we must
71 # manually register the rpc library
72 if hasattr(rpc, 'register_opts'):
73 rpc.register_opts(CONF)
74
75
76 class NovaWebSocketProxy(websockify.WebSocketProxy):
77 def __init__(self, *args, **kwargs):
78 websockify.WebSocketProxy.__init__(self, *args, **kwargs)
79
80 def new_client(self):
81 """
82 Called after a new WebSocket connection has been established.
83 """
84 cookie = Cookie.SimpleCookie()
85 cookie.load(self.headers.getheader('cookie'))
86 token = cookie['token'].value
87 ctxt = context.get_admin_context()
88 connect_info = rpc.call(ctxt, 'consoleauth',
89 {'method': 'check_token',
90 'args': {'token': token}})
91
92 if not connect_info:
93 raise Exception("Invalid Token")
94
95 host = connect_info['host']
96 port = int(connect_info['port'])
97
98 # Connect to the target
99 self.msg("connecting to: %s:%s" % (
100 host, port))
101 tsock = self.socket(host, port,
102 connect=True)
103
104 # Handshake as necessary
105 if connect_info.get('internal_access_path'):
106 tsock.send("CONNECT %s HTTP/1.1\r\n\r\n" %
107 connect_info['internal_access_path'])
108 while True:
109 data = tsock.recv(4096, socket.MSG_PEEK)
110 if data.find("\r\n\r\n") != -1:
111 if not data.split("\r\n")[0].find("200"):
112 raise Exception("Invalid Connection Info")
113 tsock.recv(len(data))
114 break
115
116 if self.verbose and not self.daemon:
117 print(self.traffic_legend)
118
119 # Start proxying
120 try:
121 self.do_proxy(tsock)
122 except:
123 if tsock:
124 tsock.shutdown(socket.SHUT_RDWR)
125 tsock.close()
126 self.vmsg("%s:%s: Target closed" % (host, port))
127 raise
128
129
130 if __name__ == '__main__':
131 if CONF.ssl_only and not os.path.exists(CONF.cert):
132 parser.error("SSL only and %s not found" % CONF.cert)
133
134 # Setup flags
135 config.parse_args(sys.argv)
136
137 # Create and start the NovaWebSockets proxy
138 server = NovaWebSocketProxy(listen_host=CONF.novncproxy_host,
139 listen_port=CONF.novncproxy_port,
140 source_is_ipv6=CONF.source_is_ipv6,
141 verbose=CONF.verbose,
142 cert=CONF.cert,
143 key=CONF.key,
144 ssl_only=CONF.ssl_only,
145 daemon=CONF.daemon,
146 record=CONF.record,
147 web=CONF.web,
148 target_host='ignore',
149 target_port='ignore',
150 wrap_mode='exit',
151 wrap_cmd=None)
152 server.start_server()