Kyle L. Henderson 26f158ac90 Move PowerVM driver options into a group
Following the compute driver standards, the driver options should
be placed in their own configuration group.  This change set
introduces the 'powervm' group.

Also, removed the reference to configuration credentials in the
README.rst file.

Change-Id: I8e28f118d4c6f9fe4922e6fd5ba095c5f9e62b4a
2015-06-30 08:15:50 -05:00

722 lines
30 KiB
Python

# Copyright 2014, 2015 IBM Corp.
#
# 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 oslo_config import cfg
import logging
from nova import exception as exc
from nova import objects
from nova import test
from nova.tests.unit import fake_instance
from nova.virt import fake
import pypowervm.adapter as pvm_adp
import pypowervm.exceptions as pvm_exc
from pypowervm.tests.wrappers.util import pvmhttp
import pypowervm.wrappers.logical_partition as pvm_lpar
import pypowervm.wrappers.managed_system as pvm_ms
from nova_powervm.tests.virt import powervm
from nova_powervm.tests.virt.powervm import fixtures as fx
from nova_powervm.virt.powervm import driver
MS_HTTPRESP_FILE = "managedsystem.txt"
MS_NAME = 'HV4'
LOG = logging.getLogger(__name__)
logging.basicConfig()
CONF = cfg.CONF
CONF.import_opt('my_ip', 'nova.netconf')
class FakeClass(object):
"""Used for the test_inst_dict."""
pass
class TestPowerVMDriver(test.TestCase):
def setUp(self):
super(TestPowerVMDriver, self).setUp()
ms_http = pvmhttp.load_pvm_resp(MS_HTTPRESP_FILE)
self.assertIsNotNone(ms_http, "Could not load %s " % MS_HTTPRESP_FILE)
entries = ms_http.response.feed.findentries(pvm_ms._SYSTEM_NAME,
MS_NAME)
self.assertNotEqual(entries, None,
"Could not find %s in %s" %
(MS_NAME, MS_HTTPRESP_FILE))
self.wrapper = pvm_ms.System.wrap(entries[0])
self.flags(disk_driver='localdisk', group='powervm')
self.drv_fix = self.useFixture(fx.PowerVMComputeDriver())
self.drv = self.drv_fix.drv
self.apt = self.drv_fix.pypvm.apt
self.fc_vol_drv = self.drv.vol_drvs['fibre_channel']
self.disk_dvr = self.drv.disk_dvr
self.crt_lpar_p = mock.patch('nova_powervm.virt.powervm.vm.crt_lpar')
self.crt_lpar = self.crt_lpar_p.start()
self.addCleanup(self.crt_lpar_p.stop)
resp = pvm_adp.Response('method', 'path', 'status', 'reason', {})
resp.entry = pvm_lpar.LPAR._bld(None).entry
self.crt_lpar.return_value = pvm_lpar.LPAR.wrap(resp)
def test_driver_create(self):
"""Validates that a driver of the PowerVM type can just be
initialized.
"""
test_drv = driver.PowerVMDriver(fake.FakeVirtAPI())
self.assertIsNotNone(test_drv)
def test_get_volume_connector(self):
vol_connector = self.drv.get_volume_connector(None)
self.assertIsNotNone(vol_connector['wwpns'])
self.assertIsNotNone(vol_connector['host'])
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
@mock.patch('nova.context.get_admin_context')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
def test_driver_ops(self, mock_get_flv, mock_get_ctx, mock_getuuid):
"""Validates the PowerVM driver operations."""
# get_info()
inst = fake_instance.fake_instance_obj(mock.sentinel.ctx)
mock_getuuid.return_value = '1234'
info = self.drv.get_info(inst)
self.assertEqual(info.id, '1234')
# list_instances()
tgt_mock = 'nova_powervm.virt.powervm.vm.get_lpar_names'
with mock.patch(tgt_mock) as mock_get_list:
fake_lpar_list = ['1', '2']
mock_get_list.return_value = fake_lpar_list
inst_list = self.drv.list_instances()
self.assertEqual(fake_lpar_list, inst_list)
# instance_exists()
tgt_mock = 'nova_powervm.virt.powervm.vm.instance_exists'
with mock.patch(tgt_mock) as mock_inst_exists:
mock_inst_exists.side_effect = [True, False]
self.assertTrue(self.drv.instance_exists(mock.Mock()))
self.assertFalse(self.drv.instance_exists(mock.Mock()))
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugMgmtVif.execute')
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugVifs.execute')
@mock.patch('nova.virt.configdrive.required_by')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
@mock.patch('pypowervm.tasks.power.power_on')
def test_spawn_ops(self, mock_pwron, mock_get_flv, mock_cfg_drv,
mock_plug_vifs, mock_plug_mgmt_vif):
"""Validates the PowerVM driver operations."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
my_flavor = inst.get_flavor()
mock_get_flv.return_value = my_flavor
mock_cfg_drv.return_value = False
# Invoke the method.
self.drv.spawn('context', inst, mock.Mock(),
'injected_files', 'admin_password')
# Create LPAR was called
self.crt_lpar.assert_called_with(
self.apt, self.drv.host_wrapper, inst, my_flavor)
# Power on was called
self.assertTrue(mock_pwron.called)
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugMgmtVif.execute')
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugVifs.execute')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'create_cfg_drv_vopt')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'_validate_vopt_vg')
@mock.patch('nova.virt.configdrive.required_by')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
@mock.patch('pypowervm.tasks.power.power_on')
def test_spawn_with_cfg(self, mock_pwron, mock_get_flv, mock_cfg_drv,
mock_val_vopt, mock_cfg_vopt, mock_plug_vifs,
mock_plug_mgmt_vif):
"""Validates the PowerVM spawn w/ config drive operations."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
my_flavor = inst.get_flavor()
mock_get_flv.return_value = my_flavor
mock_cfg_drv.return_value = True
# Invoke the method.
self.drv.spawn('context', inst, mock.Mock(),
'injected_files', 'admin_password')
# Create LPAR was called
self.crt_lpar.assert_called_with(self.apt, self.drv.host_wrapper,
inst, my_flavor)
# Power on was called
self.assertTrue(mock_pwron.called)
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugMgmtVif.execute')
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugVifs.execute')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'create_cfg_drv_vopt')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'_validate_vopt_vg')
@mock.patch('nova.virt.configdrive.required_by')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
@mock.patch('pypowervm.tasks.power.power_on')
def test_spawn_with_bdms(self, mock_pwron, mock_get_flv, mock_cfg_drv,
mock_val_vopt, mock_cfg_vopt, mock_plug_vifs,
mock_plug_mgmt_vif):
"""Validates the PowerVM spawn w/ config drive operations."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
my_flavor = inst.get_flavor()
mock_get_flv.return_value = my_flavor
mock_cfg_drv.return_value = True
# Create some fake BDMs
block_device_info = self._fake_bdms()
# Invoke the method.
self.drv.spawn('context', inst, mock.Mock(),
'injected_files', 'admin_password',
block_device_info=block_device_info)
# Create LPAR was called
self.crt_lpar.assert_called_with(self.apt, self.drv.host_wrapper,
inst, my_flavor)
# Power on was called
self.assertTrue(mock_pwron.called)
# Check that the connect volume was called
self.assertEqual(2, self.fc_vol_drv.connect_volume.call_count)
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugMgmtVif.execute')
@mock.patch('nova_powervm.virt.powervm.tasks.network.PlugVifs.execute')
@mock.patch('nova_powervm.virt.powervm.vm.dlt_lpar')
@mock.patch('nova.virt.configdrive.required_by')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
@mock.patch('pypowervm.tasks.power.power_on')
@mock.patch('pypowervm.tasks.power.power_off')
def test_spawn_ops_rollback(self, mock_pwroff, mock_pwron, mock_get_flv,
mock_cfg_drv, mock_dlt, mock_plug_vifs,
mock_plug_mgmt_vifs):
"""Validates the PowerVM driver operations. Will do a rollback."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
my_flavor = inst.get_flavor()
mock_get_flv.return_value = my_flavor
mock_cfg_drv.return_value = False
block_device_info = self._fake_bdms()
# Make sure power on fails.
mock_pwron.side_effect = exc.Forbidden()
# Invoke the method.
self.assertRaises(exc.Forbidden, self.drv.spawn, 'context', inst,
mock.Mock(), 'injected_files', 'admin_password',
block_device_info=block_device_info)
# Create LPAR was called
self.crt_lpar.assert_called_with(self.apt, self.drv.host_wrapper,
inst, my_flavor)
self.assertEqual(2, self.fc_vol_drv.connect_volume.call_count)
# Power on was called
self.assertTrue(mock_pwron.called)
# Validate the rollbacks were called
self.assertEqual(2, self.fc_vol_drv.disconnect_volume.call_count)
@mock.patch('nova_powervm.virt.powervm.vm.dlt_lpar')
@mock.patch('nova_powervm.virt.powervm.vm.power_off')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'dlt_vopt')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'_validate_vopt_vg')
@mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper')
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
@mock.patch('nova_powervm.virt.powervm.vm.UUIDCache')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
def test_destroy(
self, mock_get_flv, mock_cache, mock_pvmuuid, mock_inst_wrap,
mock_val_vopt, mock_dlt_vopt, mock_pwroff, mock_dlt):
"""Validates the basic PowerVM destroy."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
inst.task_state = None
mock_get_flv.return_value = inst.get_flavor()
singleton = mock.Mock()
mock_cache.get_cache.return_value = singleton
# BDMs
mock_bdms = self._fake_bdms()
# Invoke the method.
self.drv.destroy('context', inst, mock.Mock(),
block_device_info=mock_bdms)
# Power off was called
self.assertTrue(mock_pwroff.called)
# Validate that the vopt delete was called
self.assertTrue(mock_dlt_vopt.called)
# Validate that the volume detach was called
self.assertEqual(2, self.fc_vol_drv.disconnect_volume.call_count)
# Delete LPAR was called, and removed from the cache
mock_dlt.assert_called_with(self.apt, mock.ANY)
singleton.remove.assert_called_with(inst.name)
# Start negative tests
def reset_mocks():
# Reset the mocks for a bad case test
for mk in [mock_pwroff, mock_dlt, mock_dlt_vopt,
self.fc_vol_drv.disconnect_volume, mock_dlt, singleton]:
mk.reset_mock()
def assert_not_called():
# Power off was not called
self.assertFalse(mock_pwroff.called)
# Validate that the vopt delete was not called
self.assertFalse(mock_dlt_vopt.called)
# Validate that the volume detach was not called
self.assertFalse(self.fc_vol_drv.disconnect_volume.called)
# Delete LPAR was not called, but it was removed from the cache
self.assertFalse(mock_dlt.called)
singleton.remove.assert_called_with(inst.name)
reset_mocks()
# Pretend we didn't find the VM on the system
mock_pvmuuid.side_effect = exc.InstanceNotFound(instance_id=inst.name)
# Invoke the method.
self.drv.destroy('context', inst, mock.Mock(),
block_device_info=mock_bdms)
assert_not_called()
mock_resp = mock.Mock()
mock_resp.status = 404
mock_resp.reqpath = (
'/rest/api/uom/ManagedSystem/c5d782c7-44e4-3086-ad15-'
'b16fb039d63b/LogicalPartition/1B5FB633-16D1-4E10-A14'
'5-E6FB905161A3?group=None')
mock_pvmuuid.side_effect = pvm_exc.HttpError('error msg',
response=mock_resp)
# Invoke the method.
self.drv.destroy('context', inst, mock.Mock(),
block_device_info=mock_bdms)
assert_not_called()
# Ensure the exception is raised with non-matching path
reset_mocks()
mock_resp.reqpath = (
'/rest/api/uom/ManagedSystem/c5d782c7-44e4-3086-ad15-'
'b16fb039d63b/SomeResource/1B5FB633-16D1-4E10-A14'
'5-E6FB905161A3?group=None')
# Invoke the method.
self.assertRaises(pvm_exc.HttpError, self.drv.destroy, 'context', inst,
mock.Mock(), block_device_info=mock_bdms)
assert_not_called()
@mock.patch('nova_powervm.virt.powervm.volume.vscsi.VscsiVolumeAdapter.'
'connect_volume')
@mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper')
def test_attach_volume(self, mock_inst_wrap, mock_conn_volume):
"""Validates the basic PowerVM destroy."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
inst.task_state = None
# BDMs
mock_bdm = self._fake_bdms()['block_device_mapping'][0]
# Invoke the method.
self.drv.attach_volume('context', mock_bdm['connection_info'],
inst, mock.Mock())
# Verify the connect volume was invoked
self.assertEqual(1, mock_conn_volume.call_count)
@mock.patch('nova_powervm.virt.powervm.volume.vscsi.VscsiVolumeAdapter.'
'disconnect_volume')
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
def test_detach_volume(self, mock_pvmuuid, mock_disconn_volume):
"""Validates the basic PowerVM destroy."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
inst.task_state = None
# BDMs
mock_bdm = self._fake_bdms()['block_device_mapping'][0]
# Invoke the method.
self.drv.detach_volume(mock_bdm['connection_info'], inst, mock.Mock())
# Verify the connect volume was invoked
self.assertEqual(1, mock_disconn_volume.call_count)
@mock.patch('nova_powervm.virt.powervm.vm.dlt_lpar')
@mock.patch('nova_powervm.virt.powervm.vm.power_off')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'dlt_vopt')
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
'_validate_vopt_vg')
@mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper')
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
def test_destroy_rollback(self, mock_get_flv, mock_pvmuuid, mock_inst_wrap,
mock_val_vopt, mock_dlt_vopt, mock_pwroff,
mock_dlt):
"""Validates the basic PowerVM destroy rollback mechanism works."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
inst.task_state = None
mock_get_flv.return_value = inst.get_flavor()
# BDMs
mock_bdms = self._fake_bdms()
# Fire a failure in the power off.
mock_dlt.side_effect = exc.Forbidden()
# Invoke the method.
self.assertRaises(exc.Forbidden, self.drv.destroy, 'context', inst,
mock.Mock(), block_device_info=mock_bdms)
# Validate that the vopt delete was called
self.assertTrue(mock_dlt_vopt.called)
# Validate that the volume detach was called
self.assertEqual(2, self.fc_vol_drv.disconnect_volume.call_count)
# Delete LPAR was called
mock_dlt.assert_called_with(self.apt, mock.ANY)
# Validate the rollbacks were called.
self.assertEqual(2, self.fc_vol_drv.connect_volume.call_count)
@mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
@mock.patch('nova_powervm.virt.powervm.vm.power_off')
@mock.patch('nova_powervm.virt.powervm.vm.update')
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
def test_resize(self, mock_get_flv, mock_update, mock_pwr_off,
mock_get_uuid):
"""Validates the PowerVM driver resize operation."""
# Set up the mocks to the resize operation.
inst = objects.Instance(**powervm.TEST_INSTANCE)
host = self.drv.get_host_ip_addr()
resp = pvm_adp.Response('method', 'path', 'status', 'reason', {})
resp.entry = pvm_lpar.LPAR._bld(None).entry
self.apt.read.return_value = resp
# Catch root disk resize smaller.
small_root = objects.Flavor(vcpus=1, memory_mb=2048, root_gb=9)
self.assertRaises(
exc.InstanceFaultRollback, self.drv.migrate_disk_and_power_off,
'context', inst, 'dest', small_root, 'network_info')
new_flav = objects.Flavor(vcpus=1, memory_mb=2048, root_gb=10)
# We don't support resize to different host.
self.assertRaises(
NotImplementedError, self.drv.migrate_disk_and_power_off,
'context', inst, 'bogus host', new_flav, 'network_info')
self.drv.migrate_disk_and_power_off(
'context', inst, host, new_flav, 'network_info')
mock_pwr_off.assert_called_with(
self.drv.adapter, inst, self.drv.host_uuid, entry=mock.ANY)
mock_update.assert_called_with(
self.drv.adapter, self.drv.host_wrapper, inst, new_flav,
entry=mock.ANY)
# Boot disk resize
boot_flav = objects.Flavor(vcpus=1, memory_mb=2048, root_gb=12)
self.drv.migrate_disk_and_power_off(
'context', inst, host, boot_flav, 'network_info')
self.drv.disk_dvr.extend_disk.assert_called_with(
'context', inst, dict(type='boot'), 12)
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
@mock.patch('nova_powervm.virt.powervm.driver.vm')
@mock.patch('nova_powervm.virt.powervm.tasks.vm.vm')
@mock.patch('nova_powervm.virt.powervm.tasks.vm.power')
def test_rescue(self, mock_task_pwr, mock_task_vm,
mock_dvr_vm, mock_get_flv):
"""Validates the PowerVM driver rescue operation."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
self.drv.disk_dvr = mock.Mock()
# Invoke the method.
self.drv.rescue('context', inst, mock.MagicMock(),
mock.MagicMock(), 'rescue_psswd')
self.assertTrue(mock_task_vm.power_off.called)
self.assertTrue(self.drv.disk_dvr.create_disk_from_image.called)
self.assertTrue(self.drv.disk_dvr.connect_disk.called)
# TODO(IBM): Power on not called until bootmode=sms is supported
# self.assertTrue(mock_task_pwr.power_on.called)
@mock.patch('nova.objects.flavor.Flavor.get_by_id')
@mock.patch('nova_powervm.virt.powervm.driver.vm')
@mock.patch('nova_powervm.virt.powervm.tasks.vm.vm')
@mock.patch('nova_powervm.virt.powervm.tasks.vm.power')
def test_unrescue(self, mock_task_pwr, mock_task_vm,
mock_dvr_vm, mock_get_flv):
"""Validates the PowerVM driver rescue operation."""
# Set up the mocks to the tasks.
inst = objects.Instance(**powervm.TEST_INSTANCE)
self.drv.disk_dvr = mock.Mock()
# Invoke the method.
self.drv.unrescue(inst, 'network_info')
self.assertTrue(mock_task_vm.power_off.called)
self.assertTrue(self.drv.disk_dvr.disconnect_image_disk.called)
self.assertTrue(self.drv.disk_dvr.delete_disks.called)
self.assertTrue(mock_task_pwr.power_on.called)
@mock.patch('nova_powervm.virt.powervm.driver.LOG')
def test_log_op(self, mock_log):
"""Validates the log_operations."""
drv = driver.PowerVMDriver(fake.FakeVirtAPI())
inst = objects.Instance(**powervm.TEST_INSTANCE)
drv._log_operation('fake_op', inst)
entry = (r'Operation: %(op)s. Virtual machine display '
'name: %(display_name)s, name: %(name)s, '
'UUID: %(uuid)s')
msg_dict = {'uuid': '49629a5c-f4c4-4721-9511-9725786ff2e5',
'display_name': u'Fake Instance',
'name': 'instance-00000001',
'op': 'fake_op'}
mock_log.info.assert_called_with(entry, msg_dict)
def test_host_resources(self):
# Set the return value of None so we use the cached value in the drv
self.apt.read.return_value = None
self.drv.host_wrapper = self.wrapper
stats = self.drv.get_available_resource('nodename')
self.assertIsNotNone(stats)
# Check for the presence of fields added to host stats
fields = ('local_gb', 'local_gb_used')
for fld in fields:
value = stats.get(fld, None)
self.assertIsNotNone(value)
@mock.patch('nova_powervm.virt.powervm.tasks.network.state_ok_for_plug')
@mock.patch('nova_powervm.virt.powervm.vm.crt_secure_rmc_vif')
@mock.patch('nova_powervm.virt.powervm.vm.get_secure_rmc_vswitch')
@mock.patch('nova_powervm.virt.powervm.vm.crt_vif')
@mock.patch('nova_powervm.virt.powervm.vm.get_cnas')
def test_plug_vifs(self, mock_vm_get, mock_vm_crt, mock_get_rmc_vswitch,
mock_crt_rmc_vif, mock_vm_state):
inst = objects.Instance(**powervm.TEST_INSTANCE)
# Mock up the CNA response
cnas = [mock.MagicMock(), mock.MagicMock()]
cnas[0].mac = 'AABBCCDDEEFF'
cnas[0].vswitch_uri = 'fake_uri'
cnas[1].mac = 'AABBCCDDEE11'
cnas[1].vswitch_uri = 'fake_mgmt_uri'
mock_vm_get.return_value = cnas
mock_vm_state.return_value = True
# Mock up the network info. They get sanitized to upper case.
net_info = [
{'address': 'aa:bb:cc:dd:ee:ff'},
{'address': 'aa:bb:cc:dd:ee:22'}
]
# Mock up the rmc vswitch
vswitch_w = mock.MagicMock()
vswitch_w.href = 'fake_mgmt_uri'
mock_get_rmc_vswitch.return_value = vswitch_w
# Run method
self.drv.plug_vifs(inst, net_info)
# The create should have only been called once. The other was already
# existing.
self.assertEqual(1, mock_vm_crt.call_count)
self.assertEqual(0, mock_crt_rmc_vif.call_count)
def test_extract_bdm(self):
"""Tests the _extract_bdm method."""
self.assertEqual([], self.drv._extract_bdm(None))
self.assertEqual([], self.drv._extract_bdm({'fake': 'val'}))
fake_bdi = {'block_device_mapping': ['content']}
self.assertListEqual(['content'], self.drv._extract_bdm(fake_bdi))
def test_inst_dict(self):
"""Tests the _inst_dict method."""
class_name = 'nova_powervm.tests.virt.powervm.test_driver.FakeClass'
inst_dict = driver._inst_dict({'test': class_name})
self.assertEqual(1, len(inst_dict.keys()))
self.assertIsInstance(inst_dict['test'], FakeClass)
def test_get_host_ip_addr(self):
self.assertEqual(self.drv.get_host_ip_addr(), CONF.my_ip)
@mock.patch('nova_powervm.virt.powervm.driver.LOG.warn')
@mock.patch('nova.compute.utils.get_machine_ips')
def test_get_host_ip_addr_failure(self, mock_ips, mock_log):
mock_ips.return_value = ['1.1.1.1']
self.drv.get_host_ip_addr()
mock_log.assert_called_once_with(u'my_ip address (%(my_ip)s) was '
u'not found on any of the '
u'interfaces: %(ifaces)s',
{'ifaces': '1.1.1.1',
'my_ip': mock.ANY})
def test_shared_stg_calls(self):
data = self.drv.check_instance_shared_storage_local('context', 'inst')
self.assertTrue(
self.drv.disk_dvr.check_instance_shared_storage_local.called)
self.drv.check_instance_shared_storage_remote('context', data)
self.assertTrue(
self.drv.disk_dvr.check_instance_shared_storage_remote.called)
self.drv.check_instance_shared_storage_cleanup('context', data)
self.assertTrue(
self.drv.disk_dvr.check_instance_shared_storage_cleanup.called)
@mock.patch('nova_powervm.virt.powervm.vm.get_instance_wrapper')
@mock.patch('pypowervm.tasks.power.power_on')
@mock.patch('pypowervm.tasks.power.power_off')
def test_reboot(self, mock_pwroff, mock_pwron, mock_instw):
entry = mock.Mock()
# State doesn't matter
entry.state = "whatever"
mock_instw.return_value = entry
inst = objects.Instance(**powervm.TEST_INSTANCE)
# Validate SOFT vs HARD and power_on called with each.
self.assertTrue(self.drv.reboot('context', inst, None, 'SOFT'))
mock_pwroff.assert_called_with(entry, self.drv.host_uuid,
force_immediate=False)
mock_pwron.assert_called_with(entry, self.drv.host_uuid)
self.assertTrue(self.drv.reboot('context', inst, None, 'HARD'))
mock_pwroff.assert_called_with(entry, self.drv.host_uuid,
force_immediate=True)
self.assertEqual(2, mock_pwron.call_count)
mock_pwron.assert_called_with(entry, self.drv.host_uuid)
# If power_on raises an exception, it percolates up.
mock_pwron.side_effect = pvm_exc.VMPowerOnFailure(lpar_nm='lpar',
reason='reason')
self.assertRaises(pvm_exc.VMPowerOnFailure, self.drv.reboot, 'context',
inst, None, 'SOFT')
# But power_off was called first.
mock_pwroff.assert_called_with(entry, self.drv.host_uuid,
force_immediate=False)
# If power_off raises an exception, power_on is not called, and the
# exception percolates up.
pwron_count = mock_pwron.call_count
mock_pwroff.side_effect = pvm_exc.VMPowerOffFailure(lpar_nm='lpar',
reason='reason')
self.assertRaises(pvm_exc.VMPowerOffFailure, self.drv.reboot,
'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 = {
'block_device_mapping': [
{
'connection_info': {
'driver_volume_type': 'fibre_channel',
'data': {
'volume_id': 'fake_vol_uuid',
'target_lun': 0
}
},
'mount_device': '/dev/vda'
},
{
'connection_info': {
'driver_volume_type': 'fibre_channel',
'data': {
'volume_id': 'fake_vol_uuid2',
'target_lun': 1
}
},
'mount_device': '/dev/vdb'
}
]
}
return block_device_info
@mock.patch('nova_powervm.virt.powervm.tasks.image.UpdateTaskState.'
'execute')
@mock.patch('nova_powervm.virt.powervm.tasks.storage.InstanceDiskToMgmt.'
'execute')
@mock.patch('nova_powervm.virt.powervm.tasks.image.StreamToGlance.execute')
@mock.patch('nova_powervm.virt.powervm.tasks.storage.'
'RemoveInstanceDiskFromMgmt.execute')
def test_snapshot(self, mock_rm, mock_stream, mock_conn, mock_update):
inst = mock.Mock()
inst.display_name = 'inst'
mock_conn.return_value = 'stg_elem', 'vios_wrap', 'disk_path'
self.drv.snapshot('context', inst, 'image_id', 'update_task_state')
self.assertEqual(2, mock_update.call_count)
self.assertEqual(1, mock_conn.call_count)
mock_stream.assert_called_with(disk_path='disk_path')
mock_rm.assert_called_with(stg_elem='stg_elem', vios_wrap='vios_wrap',
disk_path='disk_path')