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

250 lines
10 KiB
Python

# Copyright 2016 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 compute_hyperv.nova import constants
from compute_hyperv.nova import pathutils
from compute_hyperv.nova import serialconsolehandler
from compute_hyperv.nova import serialproxy
from compute_hyperv.tests.unit import test_base
class SerialConsoleHandlerTestCase(test_base.HyperVBaseTestCase):
@mock.patch.object(pathutils.PathUtils, 'get_vm_console_log_paths')
def setUp(self, mock_get_log_paths):
super(SerialConsoleHandlerTestCase, self).setUp()
mock_get_log_paths.return_value = [mock.sentinel.log_path]
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(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(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(serialconsolehandler.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='127.0.0.3',
group='serial_console')
self._consolehandler._setup_serial_proxy_handler()
mock_serial_proxy_class.assert_called_once_with(
mock.sentinel.instance_name,
'127.0.0.3', 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(serialconsolehandler.utilsfactory,
'get_named_pipe_handler')
def _test_get_named_pipe_handler(self, mock_get_pipe_handler,
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_get_pipe_handler.return_value, ret_val)
mock_get_pipe_handler.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(exception.NovaException,
self._consolehandler._get_vm_serial_port_mapping)
@mock.patch('nova.console.type.ConsoleSerial')
def test_get_serial_console(self, mock_serial_console):
self.flags(enabled=True, group='serial_console')
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)
def test_get_serial_console_disabled(self):
self.flags(enabled=False, group='serial_console')
self.assertRaises(exception.ConsoleTypeUnavailable,
self._consolehandler.get_serial_console)