Add support for PowerVM Console

This change set adds support for the PowerVM VNC console.

Changes the remove vterm to always be invoked.  This shouldn't have a
performance impact if the console is not running.  Ensures proper clean
up on the system running the PowerVM API.

Change-Id: Ia6a5dd445410fcd5351c3528003a83ba659805bb
This commit is contained in:
Drew Thorstensen 2015-05-06 15:20:54 -05:00
parent 27a4b6b6e3
commit 0cf9f6c2dc
5 changed files with 51 additions and 26 deletions

View File

@ -693,6 +693,20 @@ class TestPowerVMDriver(test.TestCase):
'context', inst, None, 'HARD')
self.assertEqual(pwron_count, mock_pwron.call_count)
@mock.patch('pypowervm.tasks.vterm.open_vnc_vterm')
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
def test_get_vnc_console(self, mock_uuid, mock_vterm):
# Mock response
mock_vterm.return_value = '10'
# Invoke
inst = objects.Instance(**powervm.TEST_INSTANCE)
resp = self.drv.get_vnc_console(mock.ANY, inst)
# Validate
self.assertEqual('127.0.0.1', resp.host)
self.assertEqual('10', resp.port)
@staticmethod
def _fake_bdms():
block_device_info = {

View File

@ -160,19 +160,23 @@ class TestVM(test.TestCase):
"""Performs a delete LPAR test."""
vm.dlt_lpar(self.apt, '12345')
self.assertEqual(1, self.apt.delete.call_count)
self.assertEqual(1, mock_vterm.call_count)
# test failure due to open vterm
resp = mock.Mock()
# Test Failure Path
# build a mock response body with the expected HSCL msg
resp = mock.Mock()
resp.body = 'error msg: HSCL151B more text'
self.apt.delete.side_effect = pvm_exc.Error(
'Mock Error Message', response=resp)
# If failed due to vterm test close_vterm and delete are called
# Reset counters
self.apt.reset_mock()
mock_vterm.reset_mock()
self.assertRaises(pvm_exc.Error,
vm.dlt_lpar, self.apt, '12345')
self.assertEqual(1, mock_vterm.call_count)
self.assertEqual(2, self.apt.delete.call_count)
self.assertEqual(1, self.apt.delete.call_count)
def test_build_attr(self):
"""Perform tests against _build_attrs."""

View File

@ -63,6 +63,8 @@ CONF.register_opts(pvm_opts)
# Options imported from other regions
CONF.import_opt('host', 'nova.netconf')
CONF.import_opt('my_ip', 'nova.netconf')
CONF.import_opt('vncserver_proxyclient_address', 'nova.vnc')
CONF.import_opt('vncserver_listen', 'nova.vnc')
# NPIV Options will go in separate section. Only applicable if the

View File

@ -16,6 +16,7 @@
from nova.compute import task_states
from nova.compute import utils as compute_utils
from nova.console import type as console_type
from nova import context as ctx
from nova import exception
from nova import image
@ -38,6 +39,7 @@ from pypowervm import adapter as pvm_apt
from pypowervm import exceptions as pvm_exc
from pypowervm.helpers import log_helper as log_hlp
from pypowervm.tasks import power as pvm_pwr
from pypowervm.tasks import vterm as pvm_vterm
from pypowervm import util as pvm_util
from pypowervm.utils import retry as pvm_retry
from pypowervm.wrappers import managed_system as pvm_ms
@ -925,6 +927,21 @@ class PowerVMDriver(driver.ComputeDriver):
return []
return block_device_info.get('block_device_mapping', [])
def get_vnc_console(self, context, instance):
"""Get connection info for a vnc console.
:param context: security context
:param instance: nova.objects.instance.Instance
:returns an instance of console.type.ConsoleVNC
"""
self._log_operation('get_vnc_console', instance)
lpar_uuid = vm.get_pvm_uuid(instance)
port = pvm_vterm.open_vnc_vterm(self.adapter, lpar_uuid,
bind_ip=CONF.vncserver_listen)
host = CONF.vncserver_proxyclient_address
return console_type.ConsoleVNC(host=host, port=port)
def _inst_dict(input_dict):
"""Builds a dictionary with instances as values based on the input classes.

View File

@ -390,31 +390,19 @@ def dlt_lpar(adapter, lpar_uuid):
# Attempt to delete the VM. If delete fails because of vterm
# we will close the vterm and try the delete again
try:
LOG.info(_LI('Deleting virtual machine. LPARID: %s') % lpar_uuid)
LOG.info(_LI('Deleting virtual machine. LPARID: %s'), lpar_uuid)
# Ensure any vterms are closed. Will no-op otherwise.
vterm.close_vterm(adapter, lpar_uuid)
# Run the LPAR delete
resp = adapter.delete(pvm_lpar.LPAR.schema_type, root_id=lpar_uuid)
LOG.info(_LI('Virtual machine delete status: %s') % resp.status)
LOG.info(_LI('Virtual machine delete status: %d'), resp.status)
return resp
except pvm_exc.Error as e:
resp = e.response
if (resp.body and
any(code in str(resp.body) for code in ['HSCL151B'])):
# If this is a vterm error attempt to close vterm
try:
LOG.info(_LI('Closing virtual terminal'))
vterm.close_vterm(adapter, lpar_uuid)
# Try to delete the vm again
resp = adapter.delete(pvm_lpar.LPAR.schema_type,
root_id=lpar_uuid)
LOG.info(_LI('Virtual machine delete status: %s')
% resp.status)
return resp
except pvm_exc.Error as e:
# Fall through and raise exception
pass
except pvm_exc.Error:
# Attempting to close vterm did not help so raise exception
LOG.error(_LE('Virtual machine delete failed: LPARID=%s')
% lpar_uuid)
raise e
LOG.error(_LE('Virtual machine delete failed: LPARID=%s'),
lpar_uuid)
raise
def power_on(adapter, instance, host_uuid, entry=None):