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:
parent
27a4b6b6e3
commit
0cf9f6c2dc
|
@ -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 = {
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue