compute-hyperv/hyperv/tests/unit/test_serialconsolehandler.py

257 lines
10 KiB
Python

# Copyright 2015 Cloudbase Solutions Srl
# 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.
import mock
from nova import exception
from hyperv.nova import constants
from hyperv.nova import ioutils
from hyperv.nova import namedpipe
from hyperv.nova import serialconsolehandler
from hyperv.nova import serialproxy
from hyperv.nova import utilsfactory
from hyperv.nova import vmutils
from hyperv.tests.unit import test_base
class SerialConsoleHandlerTestCase(test_base.HyperVBaseTestCase):
@mock.patch.object(utilsfactory, 'get_pathutils')
def setUp(self, mock_get_pathutils):
super(SerialConsoleHandlerTestCase, self).setUp()
self._consolehandler = serialconsolehandler.SerialConsoleHandler(
mock.sentinel.instance_name)
self._consolehandler._log_path = mock.sentinel.log_path
self._consolehandler._pathutils = mock.Mock()
self._consolehandler._vmutils = mock.Mock()
@mock.patch.object(serialconsolehandler.SerialConsoleHandler,
'_setup_handlers')
def test_start_handler(self, mock_setup_handlers):
mock_workers = [mock.Mock(), mock.Mock()]
self._consolehandler._workers = mock_workers
self._consolehandler.start()
mock_setup_handlers.assert_called_once_with()
for worker in mock_workers:
worker.start.assert_called_once_with()
@mock.patch('nova.console.serial.release_port')
def test_stop_handler(self, mock_release_port):
mock_serial_proxy = mock.Mock()
mock_workers = [mock_serial_proxy, mock.Mock()]
self._consolehandler._serial_proxy = mock_serial_proxy
self._consolehandler._listen_host = mock.sentinel.host
self._consolehandler._listen_port = mock.sentinel.port
self._consolehandler._workers = mock_workers
self._consolehandler.stop()
mock_release_port.assert_called_once_with(mock.sentinel.host,
mock.sentinel.port)
for worker in mock_workers:
worker.stop.assert_called_once_with()
@mock.patch.object(serialconsolehandler.SerialConsoleHandler,
'_setup_named_pipe_handlers')
@mock.patch.object(serialconsolehandler.SerialConsoleHandler,
'_setup_serial_proxy_handler')
def _test_setup_handlers(self, mock_setup_proxy, mock_setup_pipe_handlers,
serial_console_enabled=True):
self.flags(enabled=serial_console_enabled, group='serial_console')
self._consolehandler._setup_handlers()
self.assertEqual(serial_console_enabled, mock_setup_proxy.called)
mock_setup_pipe_handlers.assert_called_once_with()
def test_setup_handlers(self):
self._test_setup_handlers()
def test_setup_handlers_console_disabled(self):
self._test_setup_handlers(serial_console_enabled=False)
@mock.patch.object(serialproxy, 'SerialProxy')
@mock.patch('nova.console.serial.acquire_port')
@mock.patch.object(serialconsolehandler.threading, 'Event')
@mock.patch.object(ioutils, 'IOQueue')
def test_setup_serial_proxy_handler(self, mock_io_queue, mock_event,
mock_acquire_port,
mock_serial_proxy_class):
mock_input_queue = mock.sentinel.input_queue
mock_output_queue = mock.sentinel.output_queue
mock_client_connected = mock_event.return_value
mock_io_queue.side_effect = [mock_input_queue, mock_output_queue]
mock_serial_proxy = mock_serial_proxy_class.return_value
mock_acquire_port.return_value = mock.sentinel.port
self.flags(proxyclient_address=mock.sentinel.host,
group='serial_console')
self._consolehandler._setup_serial_proxy_handler()
mock_serial_proxy_class.assert_called_once_with(
mock.sentinel.instance_name,
mock.sentinel.host, mock.sentinel.port,
mock_input_queue,
mock_output_queue,
mock_client_connected)
self.assertIn(mock_serial_proxy, self._consolehandler._workers)
@mock.patch.object(serialconsolehandler.SerialConsoleHandler,
'_get_named_pipe_handler')
@mock.patch.object(serialconsolehandler.SerialConsoleHandler,
'_get_vm_serial_port_mapping')
def _mock_setup_named_pipe_handlers(self, mock_get_port_mapping,
mock_get_pipe_handler,
serial_port_mapping=None):
mock_get_port_mapping.return_value = serial_port_mapping
self._consolehandler._setup_named_pipe_handlers()
expected_workers = [mock_get_pipe_handler.return_value
for port in serial_port_mapping]
self.assertEqual(expected_workers, self._consolehandler._workers)
return mock_get_pipe_handler
def test_setup_ro_pipe_handler(self):
serial_port_mapping = {
constants.SERIAL_PORT_TYPE_RW: mock.sentinel.pipe_path
}
mock_get_handler = self._mock_setup_named_pipe_handlers(
serial_port_mapping=serial_port_mapping)
mock_get_handler.assert_called_once_with(
mock.sentinel.pipe_path,
pipe_type=constants.SERIAL_PORT_TYPE_RW,
enable_logging=True)
def test_setup_pipe_handlers(self):
serial_port_mapping = {
constants.SERIAL_PORT_TYPE_RO: mock.sentinel.ro_pipe_path,
constants.SERIAL_PORT_TYPE_RW: mock.sentinel.rw_pipe_path
}
mock_get_handler = self._mock_setup_named_pipe_handlers(
serial_port_mapping=serial_port_mapping)
expected_calls = [mock.call(mock.sentinel.ro_pipe_path,
pipe_type=constants.SERIAL_PORT_TYPE_RO,
enable_logging=True),
mock.call(mock.sentinel.rw_pipe_path,
pipe_type=constants.SERIAL_PORT_TYPE_RW,
enable_logging=False)]
mock_get_handler.assert_has_calls(expected_calls, any_order=True)
@mock.patch.object(namedpipe, 'NamedPipeHandler')
def _test_get_named_pipe_handler(self, mock_pipe_handler_class,
pipe_type=None, enable_logging=False):
expected_args = {}
if pipe_type == constants.SERIAL_PORT_TYPE_RW:
self._consolehandler._input_queue = mock.sentinel.input_queue
self._consolehandler._output_queue = mock.sentinel.output_queue
self._consolehandler._client_connected = (
mock.sentinel.connect_event)
expected_args.update({
'input_queue': mock.sentinel.input_queue,
'output_queue': mock.sentinel.output_queue,
'connect_event': mock.sentinel.connect_event})
if enable_logging:
expected_args['log_file'] = mock.sentinel.log_path
ret_val = self._consolehandler._get_named_pipe_handler(
mock.sentinel.pipe_path, pipe_type, enable_logging)
self.assertEqual(mock_pipe_handler_class.return_value, ret_val)
mock_pipe_handler_class.assert_called_once_with(
mock.sentinel.pipe_path,
**expected_args)
def test_get_ro_named_pipe_handler(self):
self._test_get_named_pipe_handler(
pipe_type=constants.SERIAL_PORT_TYPE_RO,
enable_logging=True)
def test_get_rw_named_pipe_handler(self):
self._test_get_named_pipe_handler(
pipe_type=constants.SERIAL_PORT_TYPE_RW,
enable_logging=False)
def _mock_get_port_connections(self, port_connections):
get_port_connections = (
self._consolehandler._vmutils.get_vm_serial_port_connections)
get_port_connections.return_value = port_connections
def test_get_vm_serial_port_mapping_having_tagged_pipes(self):
ro_pipe_path = 'fake_pipe_ro'
rw_pipe_path = 'fake_pipe_rw'
self._mock_get_port_connections([ro_pipe_path, rw_pipe_path])
ret_val = self._consolehandler._get_vm_serial_port_mapping()
expected_mapping = {
constants.SERIAL_PORT_TYPE_RO: ro_pipe_path,
constants.SERIAL_PORT_TYPE_RW: rw_pipe_path
}
self.assertEqual(expected_mapping, ret_val)
def test_get_vm_serial_port_mapping_untagged_pipe(self):
pipe_path = 'fake_pipe_path'
self._mock_get_port_connections([pipe_path])
ret_val = self._consolehandler._get_vm_serial_port_mapping()
expected_mapping = {constants.SERIAL_PORT_TYPE_RW: pipe_path}
self.assertEqual(expected_mapping, ret_val)
def test_get_vm_serial_port_mapping_exception(self):
self._mock_get_port_connections([])
self.assertRaises(vmutils.HyperVException,
self._consolehandler._get_vm_serial_port_mapping)
@mock.patch('nova.console.type.ConsoleSerial')
def _test_get_serial_console(self, mock_serial_console,
console_enabled=True):
self.flags(enabled=console_enabled, group='serial_console')
if console_enabled:
self._consolehandler._listen_host = mock.sentinel.host
self._consolehandler._listen_port = mock.sentinel.port
ret_val = self._consolehandler.get_serial_console()
self.assertEqual(mock_serial_console.return_value, ret_val)
mock_serial_console.assert_called_once_with(
host=mock.sentinel.host,
port=mock.sentinel.port)
else:
self.assertRaises(exception.ConsoleTypeUnavailable,
self._consolehandler.get_serial_console)
def test_get_serial_console(self):
self._test_get_serial_console()
def test_get_serial_console_disabled(self):
self._test_get_serial_console(console_enabled=False)