From d9c03b1ecbc79021cbd597e45a29b84587db0a67 Mon Sep 17 00:00:00 2001 From: Radoslav Gerganov Date: Tue, 28 Mar 2017 11:26:10 +0300 Subject: [PATCH] VMware: serial console log (completed) Commit ace11d3 adds a serial port device to instances, so the serial console output can be sent to a virtual serial port concentrator (VSPC). This patch finishes the implementation by returning the output saved by VSPC to the end user. The config option 'serial_log_dir' should have the same value as in the VSPC configuration (i.e. it must point to the same directory). The VSPC implementation is available at https://github.com/openstack/vmware-vspc blueprint vmware-console-log-complete Change-Id: I7e40dc41b0354d414bc8eae331f8257959e1d123 --- doc/source/user/support-matrix.ini | 2 +- nova/conf/vmware.py | 7 ++++++ .../unit/virt/vmwareapi/test_driver_api.py | 22 +++++++++++++++---- nova/virt/vmwareapi/driver.py | 19 ++++++++++++++++ .../vmware-console-log-384fbb9a6aa095ad.yaml | 8 +++++++ 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/vmware-console-log-384fbb9a6aa095ad.yaml diff --git a/doc/source/user/support-matrix.ini b/doc/source/user/support-matrix.ini index 531d1feac9fa..5b917ac86f52 100644 --- a/doc/source/user/support-matrix.ini +++ b/doc/source/user/support-matrix.ini @@ -955,7 +955,7 @@ driver-impl-libvirt-kvm-s390x=complete driver-impl-libvirt-qemu-x86=complete driver-impl-libvirt-lxc=missing driver-impl-libvirt-xen=complete -driver-impl-vmware=missing +driver-impl-vmware=complete driver-impl-hyperv=complete driver-impl-ironic=missing driver-impl-libvirt-vz-vm=missing diff --git a/nova/conf/vmware.py b/nova/conf/vmware.py index 0cf34e6f267b..d0f1bba09930 100644 --- a/nova/conf/vmware.py +++ b/nova/conf/vmware.py @@ -91,6 +91,13 @@ Possible values: Related options: This option is ignored if serial_port_service_uri is not specified. * serial_port_service_uri +"""), + cfg.StrOpt('serial_log_dir', + default='/opt/vmware/vspc', + help=""" +Specifies the directory where the Virtual Serial Port Concentrator is +storing console log files. It should match the 'serial_log_dir' config +value of VSPC. """), ] diff --git a/nova/tests/unit/virt/vmwareapi/test_driver_api.py b/nova/tests/unit/virt/vmwareapi/test_driver_api.py index 272fe3b40dd5..379e73aeeda2 100644 --- a/nova/tests/unit/virt/vmwareapi/test_driver_api.py +++ b/nova/tests/unit/virt/vmwareapi/test_driver_api.py @@ -1671,10 +1671,6 @@ class VMwareAPIVMTestCase(test.NoDBTestCase, actual = self.conn.get_instance_diagnostics(instance) self.assertDiagnosticsEqual(expected, actual) - def test_get_console_output(self): - self.assertRaises(NotImplementedError, self.conn.get_console_output, - None, None) - def test_get_vnc_console_non_existent(self): self._create_instance() self.assertRaises(exception.InstanceNotFound, @@ -1702,6 +1698,24 @@ class VMwareAPIVMTestCase(test.NoDBTestCase, self.context, self.instance) + def test_get_console_output(self): + self.flags(serial_log_dir='/opt/vspc', group='vmware') + self._create_instance() + with test.nested( + mock.patch('os.path.exists', return_value=True), + mock.patch('{}.open'.format(driver.__name__), create=True), + mock.patch('nova.privsep.path.last_bytes') + ) as (fake_exists, fake_open, fake_last_bytes): + fake_open.return_value = mock.MagicMock() + fake_fd = fake_open.return_value.__enter__.return_value + fake_last_bytes.return_value = b'fira', 0 + output = self.conn.get_console_output(self.context, self.instance) + fname = self.instance.uuid.replace('-', '') + fake_exists.assert_called_once_with('/opt/vspc/{}'.format(fname)) + fake_last_bytes.assert_called_once_with(fake_fd, + driver.MAX_CONSOLE_BYTES) + self.assertEqual(b'fira', output) + def test_get_volume_connector(self): self._create_vm() connector_dict = self.conn.get_volume_connector(self.instance) diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index c39b2cc9521e..bf587bf25034 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -19,10 +19,12 @@ A connection to the VMware vCenter platform. """ +import os import re from oslo_log import log as logging from oslo_utils import excutils +from oslo_utils import units from oslo_utils import versionutils as v_utils from oslo_vmware import api from oslo_vmware import exceptions as vexc @@ -35,6 +37,7 @@ from nova.compute import task_states import nova.conf from nova import exception from nova.i18n import _ +import nova.privsep.path from nova.virt import driver from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import error_util @@ -49,6 +52,7 @@ LOG = logging.getLogger(__name__) CONF = nova.conf.CONF TIME_BETWEEN_API_CALL_RETRIES = 1.0 +MAX_CONSOLE_BYTES = 100 * units.Ki class VMwareVCDriver(driver.ComputeDriver): @@ -259,6 +263,21 @@ class VMwareVCDriver(driver.ComputeDriver): def get_mks_console(self, context, instance): return self._vmops.get_mks_console(instance) + def get_console_output(self, context, instance): + if not CONF.vmware.serial_log_dir: + LOG.error("The 'serial_log_dir' config option is not set!") + return + fname = instance.uuid.replace('-', '') + path = os.path.join(CONF.vmware.serial_log_dir, fname) + if not os.path.exists(path): + LOG.warning('The console log is missing. Check your VSPC ' + 'configuration', instance=instance) + return b"" + with open(path, 'rb') as fp: + read_log_data, remaining = nova.privsep.path.last_bytes( + fp, MAX_CONSOLE_BYTES) + return read_log_data + def _get_vcenter_uuid(self): """Retrieves the vCenter UUID.""" diff --git a/releasenotes/notes/vmware-console-log-384fbb9a6aa095ad.yaml b/releasenotes/notes/vmware-console-log-384fbb9a6aa095ad.yaml new file mode 100644 index 000000000000..ff312aa4b9b5 --- /dev/null +++ b/releasenotes/notes/vmware-console-log-384fbb9a6aa095ad.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + VMware serial console log is completed. `VSPC`_ must be deployed along + with nova-compute and configured properly. The ``[vmware]/serial_log_dir`` + config option must have the same value in both nova.conf and vspc.conf. + + .. _VSPC: https://github.com/openstack/vmware-vspc