Merge "Expose serial ports through a web interface"

This commit is contained in:
Jenkins 2014-07-07 19:34:25 +00:00 committed by Gerrit Code Review
commit 832cc45062
1 changed files with 258 additions and 0 deletions

258
specs/juno/serial-ports.rst Normal file
View File

@ -0,0 +1,258 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
======================================
Interactive web-based serial consoles
======================================
https://blueprints.launchpad.net/nova/+spec/serial-ports
This blueprint is about exposing interactive web-based serial consoles to
openstack VMs through a websocket proxy. It is mainly raised because of the
problems openstack is facing with the serial console logs that are hard to
maintain, grow indefinitely, etc. The point is not to eliminate the serial
console logs, but to give the users another option besides logging to a file
and to expose an interactive serial console.
Problem description
===================
Right now the serial console has unsolved issues with the logging that have
bounced from one release to another and no suitable solution was developed for
them. Most of the issues are nicely summed up in the serial console log
blueprint for juno https://review.openstack.org/#/c/80865/ however, this
proposal doesn't deal with exposing an interactive serial console to the end
user.
Proposed change
===============
This blueprint proposes the addition of a new service - serialproxy (a
websocket proxy) that would handle websocket connections to the serial
consoles. The websocket proxy can be deployed on a machine other from the
hypervisor, so unix domain sockets wouldn't do the trick. The best way to
expose them would be by opening a TCP socket for every serial console.
http://libvirt.org/formatdomain.html#elementsCharTCP
This service would act similarly to the novncproxy and scale in more or less
the same way.
One serial port can be accessed only by one user at a time, i.e. it can't
be muxed since none of the hypervisors have a 'clear this line' command
separate from the 'connect' command (or a flag to integrate that with the
original 'connect' call).
The proposed scenario for multiple users accessing the same serial port is the
following:
If a user is already connected, then reject the attempt of a second user to
access the console, but have an API to forceably disconnect an existing
session. This would be particularly important to cope with hung sessions where
the client network went away before the console was cleanly closed.
To allow multiple clients to connect to serial ports we'd need to create the
ports when the instance is booted, but we'd need to know the number of ports
that would need to be created in advance. That number can be passed through a
property in the image metadata, e.g. "serial_ports".
Since the serial ports are exposed through TCP sockets we would also need a
module that tests for free TCP ports and allocates them so that the libvirt
driver can use them when creating the serial ports. This should be persistent,
so that the ports that are already tested won't be tested again for a new
serial port.
Alternatives
------------
None
Data model impact
-----------------
None
REST API impact
---------------
The REST API would have one additional method to obtain the serial console URL
for the end user or for displaying in the dashboard.
V2 API specification:
POST: v2/{tenant_id}/servers/{server_id}/get-serial-console
V3 API specification:
POST: v3/servers/{server_id}/get-serial-console
Request parameters:
* tenant_id: The ID for the tenant or account in a multi-tenancy cloud.
* server_id: The UUID for the server to get the serial console for.
JSON response
::
{
"serial_console":
{
"url": "http://example.com:6083/serial.html?token=b40ac1c3-b640-4a6a-ae34-bf347ef089d6"
}
}
JSON schema definition
::
serial_console = {
'type': 'object',
'properties': {
'serial_console': {
'type': ['object', 'null'],
'properties': {},
'additionalProperties': False,
},
},
'additionalProperties': False,
}
HTTP response codes:
v2:
* Normal HTTP Response Code: 200 on success
v3:
* Normal HTTP Response Code: 202 on success
Security impact
---------------
The opening of TCP ports in the hypervisor node can enable anyone to gain
access to any of the serial consoles by scanning for open ports if the ports
specified in port_range config param are visible to the public.
Usually the hypervisor ports aren't externally exposed, so this wouldn't be any
better or worse than VNC.
The insecurity of VNC is being tackled by a blueprint that will add strong auth
to VNC on the internal network. That's not a reason to block this serial
console feature though. We can work with the QEMU community at a later date to
get SSL support for the character device sockets it exposes.
Notifications impact
--------------------
None
Other end user impact
---------------------
The python-novaclient will have to implement a new command.
Command:
get-serial-console <server> <console-type>
* param server: The name or Id of the server.
Performance Impact
------------------
Using the serial consoles instead of a graphical console would be more optimal
since it interacts with the instance through a text stream.
Other deployer impact
---------------------
Config options that are being added in the serial_console group:
[serial_console]
- enabled (type=BoolOpt, default=False)
- base_url (type=StrOpt, default='http://127.0.0.1:6083/serial.html')
- listen (type=StrOpt, default='0.0.0.0')
- proxyclient_address (type=StrOpt, default='127.0.0.1')
- port_range (type=StrOpt, default='10000:20000')
- record (type=BoolOpt, default=False)
- daemon (type=BoolOpt, default=False)
- ssl_only (type=BoolOpt, default=False)
- source_is_ipv6 (type=BoolOpt, default=False)
- cert (type=StrOpt, default='self.pem')
- key (type=StrOpt)
- web (type=StrOpt, default='/usr/share/serialproxy-static')
The default value of the "enabled" confing param is False so there's no need
to take something into account after this change gets merged.
A new service - serialproxy is introduced which will need to be deployed
separately in order for this feature to work with websockets.
The command line params would be no different from novnc's which would override
some of the config params specified in the config file).
Developer impact
----------------
None
Implementation
==============
Assignee(s)
-----------
Primary assignee:
Vladan Popovic
Other contributors:
Ian Wells
Sushma Korati
Work Items
----------
**Websocket proxy**
* Add a config param in nova that would enable the web-based serial console,
e.g. enabled=True|False where False would be the default.
* Configure libvirt to open TCP channels on the ports
http://libvirt.org/formatdomain.html#elementsCharTCP
* Add a port allocator module that would generate/test TCP ports and assign
them to the instance's libvirt config when it finds a free one.
This would require another config param in nova, e.g. port_range=10000:20000
* Implement the serial console config generation and retreival in the libvirt
driver.
* Add a method for obtaining the serial console in the compute manager.
* Add methods in the consoleauth that would authorize the tokens.
* Add API calls that would obtain the serial console URL with the generated
consoleauth token.
* Add a serialproxy service that will serve as a wesocket proxy for serial
consoles
* Add static files that will be serverd from the proxy, including a terminal
emulator, probably https://github.com/chjj/term.js/
Dependencies
============
May require packaging of the static files for the websocket proxy and the
terminal emulator.
Testing
=======
Unit tests should be sufficient to cover libvirt and the API part.
Documentation Impact
====================
Since tihs proposal introduces a new console and service the following things
should be documented at least:
* Deploying the serialproxy (with SSL/TLS support if possible)
* Changes in the image metadata (if that solution fits the needs for multiuser
serial consoles)
* Now to obtain a serial console URL from the API or from python-novaclient
* Examples of managing the ports specified in the port_range so that they are
only accessible from the node where the serialproxy is deployed and not from
the outside.
References
==========
None