Coverage for nova/console/serial.py: 96%
40 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
1# All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
15"""Serial consoles module."""
17import socket
19from oslo_log import log as logging
21import nova.conf
22from nova import exception
23from nova import utils
25LOG = logging.getLogger(__name__)
27ALLOCATED_PORTS = set() # in-memory set of already allocated ports
28SERIAL_LOCK = 'serial-lock'
30CONF = nova.conf.CONF
32# TODO(sahid): Add a method to initialize ALLOCATED_PORTS with the
33# already binded TPC port(s). (cf from danpb: list all running guests and
34# query the XML in libvirt driver to find out the TCP port(s) it uses).
37@utils.synchronized(SERIAL_LOCK)
38def acquire_port(host):
39 """Returns a free TCP port on host.
41 Find and returns a free TCP port on 'host' in the range
42 of 'CONF.serial_console.port_range'.
43 """
45 start, stop = _get_port_range()
47 for port in range(start, stop): 47 ↛ 57line 47 didn't jump to line 57 because the loop on line 47 didn't complete
48 if (host, port) in ALLOCATED_PORTS:
49 continue
50 try:
51 _verify_port(host, port)
52 ALLOCATED_PORTS.add((host, port))
53 return port
54 except exception.SocketPortInUseException as e:
55 LOG.warning(e.format_message())
57 raise exception.SocketPortRangeExhaustedException(host=host)
60@utils.synchronized(SERIAL_LOCK)
61def release_port(host, port):
62 """Release TCP port to be used next time."""
63 ALLOCATED_PORTS.discard((host, port))
66def _get_port_range():
67 config_range = CONF.serial_console.port_range
69 start, stop = map(int, config_range.split(':'))
70 if start >= stop:
71 default_port_range = nova.conf.serial_console.DEFAULT_PORT_RANGE
72 LOG.warning("serial_console.port_range should be in the "
73 "format <start>:<stop> and start < stop, "
74 "Given value %(port_range)s is invalid. "
75 "Taking the default port range %(default)s.",
76 {'port_range': config_range,
77 'default': default_port_range})
78 start, stop = map(int, default_port_range.split(':'))
79 return start, stop
82def _verify_port(host, port):
83 s = socket.socket()
84 try:
85 s.bind((host, port))
86 except socket.error as e:
87 raise exception.SocketPortInUseException(
88 host=host, port=port, error=e)
89 finally:
90 s.close()