02dbf675a6
In order to support the management VIF for RMC connections, the link local address needs to be defined on the management VIF. For legacy versions of cloud-init as well as broad distribution support, this change set switches to a 'static' definition of the link local address. This applies to a broader set of cloud init revisions. Change-Id: I2f072b697b858cb0ee5bc7189c5f593f77fede89
198 lines
8.2 KiB
Python
198 lines
8.2 KiB
Python
# Copyright 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 nova import test
|
|
import os
|
|
from pypowervm.tests.wrappers.util import pvmhttp
|
|
from pypowervm.wrappers import storage as pvm_stor
|
|
|
|
from nova_powervm.tests.virt.powervm import fixtures as fx
|
|
from nova_powervm.virt.powervm import exception as npvmex
|
|
from nova_powervm.virt.powervm import media as m
|
|
|
|
VOL_GRP_DATA = 'fake_volume_group.txt'
|
|
VOL_GRP_NOVG_DATA = 'fake_volume_group_no_vg.txt'
|
|
|
|
VOL_GRP_WITH_VIOS = 'fake_volume_group_with_vio_data.txt'
|
|
VIOS_WITH_VOL_GRP = 'fake_vios_with_volume_group_data.txt'
|
|
|
|
VIOS_NO_VG = 'fake_vios_feed_no_vg.txt'
|
|
VIOS_FEED = 'fake_vios_feed.txt'
|
|
|
|
|
|
class TestConfigDrivePowerVM(test.TestCase):
|
|
"""Unit Tests for the ConfigDrivePowerVM class."""
|
|
|
|
def setUp(self):
|
|
super(TestConfigDrivePowerVM, self).setUp()
|
|
|
|
# Find directory for response file(s)
|
|
data_dir = os.path.dirname(os.path.abspath(__file__))
|
|
data_dir = os.path.join(data_dir, 'data')
|
|
|
|
self.pypvm = self.useFixture(fx.PyPowerVM())
|
|
self.apt = self.pypvm.apt
|
|
|
|
def resp(file_name):
|
|
file_path = os.path.join(data_dir, file_name)
|
|
return pvmhttp.load_pvm_resp(
|
|
file_path, adapter=self.apt).get_response()
|
|
|
|
self.vol_grp_resp = resp(VOL_GRP_DATA)
|
|
self.vol_grp_novg_resp = resp(VOL_GRP_NOVG_DATA)
|
|
|
|
self.vg_to_vio = resp(VOL_GRP_WITH_VIOS)
|
|
self.vio_to_vg = resp(VIOS_WITH_VOL_GRP)
|
|
|
|
self.vio_feed_no_vg = resp(VIOS_NO_VG)
|
|
self.vio_feed = resp(VIOS_FEED)
|
|
|
|
# Wipe out the static variables, so that the revalidate is called
|
|
m.ConfigDrivePowerVM._cur_vios_uuid = None
|
|
m.ConfigDrivePowerVM._cur_vios_name = None
|
|
m.ConfigDrivePowerVM._cur_vg_uuid = None
|
|
|
|
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
|
|
'_validate_vopt_vg')
|
|
@mock.patch('nova.api.metadata.base.InstanceMetadata')
|
|
@mock.patch('nova.virt.configdrive.ConfigDriveBuilder.make_drive')
|
|
def test_crt_cfg_dr_iso(self, mock_mkdrv, mock_meta, mock_vopt_valid):
|
|
"""Validates that the image creation method works."""
|
|
cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'host_uuid')
|
|
mock_instance = mock.MagicMock()
|
|
mock_instance.name = 'fake-instance'
|
|
mock_instance.uuid = '1e46bbfd-73b6-3c2a-aeab-a1d3f065e92f'
|
|
mock_files = mock.MagicMock()
|
|
mock_net = mock.MagicMock()
|
|
iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso(mock_instance,
|
|
mock_files,
|
|
mock_net)
|
|
self.assertEqual('cfg_fake_instance.iso', file_name)
|
|
self.assertEqual('/tmp/cfgdrv/cfg_fake_instance.iso', iso_path)
|
|
# Make sure the length is limited properly
|
|
mock_instance.name = 'fake-instance-with-name-that-is-too-long'
|
|
iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso(mock_instance,
|
|
mock_files,
|
|
mock_net)
|
|
self.assertEqual('cfg_fake_instance_with_name_that_.iso', file_name)
|
|
self.assertEqual('/tmp/cfgdrv/cfg_fake_instance_with_name_that_.iso',
|
|
iso_path)
|
|
|
|
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
|
|
'_create_cfg_dr_iso')
|
|
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
|
|
'_validate_vopt_vg')
|
|
@mock.patch('os.path.getsize')
|
|
@mock.patch('os.remove')
|
|
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
|
|
'_upload_vopt')
|
|
@mock.patch('pypowervm.tasks.scsi_mapper.add_vscsi_mapping')
|
|
def test_crt_cfg_drv_vopt(self, mock_add_map, mock_upld,
|
|
mock_rm, mock_size, mock_validate, mock_cfg_iso):
|
|
# Mock Returns
|
|
mock_cfg_iso.return_value = '/tmp/cfgdrv/fake.iso', 'fake.iso'
|
|
mock_size.return_value = 10000
|
|
mock_upld.return_value = (mock.Mock(), None)
|
|
|
|
# Run
|
|
cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host')
|
|
cfg_dr_builder.create_cfg_drv_vopt(mock.MagicMock(), mock.MagicMock(),
|
|
mock.MagicMock(), 'fake_lpar')
|
|
self.assertTrue(mock_upld.called)
|
|
self.assertTrue(mock_add_map.called)
|
|
|
|
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
|
|
'_validate_vopt_vg')
|
|
def test_mgmt_cna_to_vif(self, mock_validate):
|
|
mock_cna = mock.MagicMock()
|
|
mock_cna.mac = "FAD4433ED120"
|
|
|
|
# Run
|
|
cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host')
|
|
vif = cfg_dr_builder._mgmt_cna_to_vif(mock_cna)
|
|
|
|
# Validate
|
|
self.assertEqual(vif.get('address'), "fa:d4:43:3e:d1:20")
|
|
self.assertEqual(vif.get('id'), 'mgmt_vif')
|
|
self.assertIsNotNone(vif.get('network'))
|
|
self.assertEqual(1, len(vif.get('network').get('subnets')))
|
|
subnet = vif.get('network').get('subnets')[0]
|
|
self.assertEqual(6, subnet.get('version'))
|
|
self.assertEqual('fe80::/64', subnet.get('cidr'))
|
|
ip = subnet.get('ips')[0]
|
|
self.assertEqual('fe80::f8d4:43ff:fe3e:d120', ip.get('address'))
|
|
|
|
def test_mac_to_link_local(self):
|
|
mac = 'fa:d4:43:3e:d1:20'
|
|
self.assertEqual('fe80::f8d4:43ff:fe3e:d120',
|
|
m.ConfigDrivePowerVM._mac_to_link_local(mac))
|
|
|
|
mac = '00:00:00:00:00:00'
|
|
self.assertEqual('fe80::0200:00ff:fe00:0000',
|
|
m.ConfigDrivePowerVM._mac_to_link_local(mac))
|
|
|
|
mac = 'ff:ff:ff:ff:ff:ff'
|
|
self.assertEqual('fe80::fdff:ffff:feff:ffff',
|
|
m.ConfigDrivePowerVM._mac_to_link_local(mac))
|
|
|
|
def test_validate_opt_vg(self):
|
|
self.apt.read.side_effect = [self.vio_feed, self.vol_grp_resp]
|
|
vg_update = self.vol_grp_resp.feed.entries[0]
|
|
self.apt.update_by_path.return_value = vg_update
|
|
cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host')
|
|
self.assertEqual('1e46bbfd-73b6-3c2a-aeab-a1d3f065e92f',
|
|
cfg_dr_builder.vg_uuid)
|
|
|
|
def test_validate_opt_vg_fail(self):
|
|
self.apt.read.side_effect = [self.vio_feed_no_vg,
|
|
self.vol_grp_novg_resp]
|
|
self.assertRaises(npvmex.NoMediaRepoVolumeGroupFound,
|
|
m.ConfigDrivePowerVM, self.apt, 'fake_host')
|
|
|
|
@mock.patch('pypowervm.tasks.scsi_mapper.remove_vopt_mapping')
|
|
@mock.patch('nova_powervm.virt.powervm.media.ConfigDrivePowerVM.'
|
|
'_validate_vopt_vg')
|
|
def test_dlt_vopt(self, mock_vop_valid, mock_remove_map):
|
|
|
|
# Set up the mock data.
|
|
resp = mock.MagicMock(name='resp')
|
|
type(resp).body = mock.PropertyMock(return_value='2')
|
|
self.apt.read.side_effect = [resp, self.vg_to_vio]
|
|
|
|
# We tell it to remove all the optical medias.
|
|
vg = pvm_stor.VG.wrap(self.vg_to_vio)
|
|
mock_remove_map.return_value = ('fake_vios',
|
|
vg.vmedia_repos[0].optical_media)
|
|
|
|
# Make sure that the first update is a VIO and doesn't have the vopt
|
|
# mapping
|
|
def validate_update(*kargs, **kwargs):
|
|
vol_grp = kargs[0]
|
|
# This is the VG update. Make sure there are no optical medias
|
|
# anymore.
|
|
self.assertEqual(0, len(vol_grp.vmedia_repos[0].optical_media))
|
|
return vol_grp.entry
|
|
|
|
self.apt.update_by_path.side_effect = validate_update
|
|
|
|
# Invoke the operation
|
|
cfg_dr = m.ConfigDrivePowerVM(self.apt, 'fake_host')
|
|
cfg_dr.dlt_vopt('fake_lpar_uuid')
|
|
|
|
self.assertEqual(1, self.apt.update_by_path.call_count)
|