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

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. 

14 

15"""Serial consoles module.""" 

16 

17import socket 

18 

19from oslo_log import log as logging 

20 

21import nova.conf 

22from nova import exception 

23from nova import utils 

24 

25LOG = logging.getLogger(__name__) 

26 

27ALLOCATED_PORTS = set() # in-memory set of already allocated ports 

28SERIAL_LOCK = 'serial-lock' 

29 

30CONF = nova.conf.CONF 

31 

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). 

35 

36 

37@utils.synchronized(SERIAL_LOCK) 

38def acquire_port(host): 

39 """Returns a free TCP port on host. 

40 

41 Find and returns a free TCP port on 'host' in the range 

42 of 'CONF.serial_console.port_range'. 

43 """ 

44 

45 start, stop = _get_port_range() 

46 

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()) 

56 

57 raise exception.SocketPortRangeExhaustedException(host=host) 

58 

59 

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)) 

64 

65 

66def _get_port_range(): 

67 config_range = CONF.serial_console.port_range 

68 

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 

80 

81 

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()