
Validate all data feeded into bareon by jsonschema, not only data related to disk partitioning. It allows ironic-driver to make early data validation (https://review.openstack.org/410841). Change-Id: Ic1acf6b162ada83950ad4a890d32ca2a80152302
447 lines
14 KiB
Python
447 lines
14 KiB
Python
#
|
|
# Copyright 2016 Cray Inc. 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
|
|
import unittest2
|
|
|
|
from bareon.drivers.data import ironic
|
|
|
|
PROVISION_SAMPLE_DATA_SWIFT = {
|
|
"partitions": [
|
|
{
|
|
"id": {
|
|
"type": "name",
|
|
"value": "sda"
|
|
},
|
|
"volumes": [
|
|
{
|
|
"mount": "/boot",
|
|
"size": "200",
|
|
"type": "raid",
|
|
"file_system": "ext2",
|
|
"name": "Boot"
|
|
},
|
|
{
|
|
"mount": "/tmp",
|
|
"size": "200",
|
|
"type": "partition",
|
|
"file_system": "ext2",
|
|
"partition_guid": "fake_guid",
|
|
"name": "TMP"
|
|
},
|
|
{
|
|
"size": "19438",
|
|
"type": "pv",
|
|
"lvm_meta_size": "64",
|
|
"vg": "os"
|
|
},
|
|
{
|
|
"size": "45597",
|
|
"type": "pv",
|
|
"lvm_meta_size": "64",
|
|
"vg": "image"
|
|
}
|
|
],
|
|
"type": "disk",
|
|
"size": "65587"
|
|
},
|
|
{
|
|
"id": {
|
|
"type": "scsi",
|
|
"value": "1:0:0:0"
|
|
},
|
|
"volumes": [
|
|
{
|
|
"mount": "/boot",
|
|
"size": "200",
|
|
"type": "raid",
|
|
"file_system": "ext2",
|
|
"name": "Boot"
|
|
},
|
|
{
|
|
"size": "0",
|
|
"type": "pv",
|
|
"lvm_meta_size": "10",
|
|
"vg": "os"
|
|
},
|
|
{
|
|
"size": "64971",
|
|
"type": "pv",
|
|
"lvm_meta_size": "64",
|
|
"vg": "image"
|
|
}
|
|
],
|
|
"type": "disk",
|
|
"size": "65587"
|
|
},
|
|
{
|
|
'id': {
|
|
'type': 'path',
|
|
'value': 'disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0'
|
|
},
|
|
"volumes": [
|
|
{
|
|
"mount": "/boot",
|
|
"size": "200",
|
|
"type": "raid",
|
|
"file_system": "ext2",
|
|
"name": "Boot"
|
|
},
|
|
{
|
|
"size": "19374",
|
|
"type": "pv",
|
|
"lvm_meta_size": "10",
|
|
"vg": "os"
|
|
},
|
|
{
|
|
"size": "175347",
|
|
"type": "pv",
|
|
"lvm_meta_size": "64",
|
|
"vg": "image"
|
|
}
|
|
],
|
|
"type": "disk",
|
|
"size": "195019"
|
|
},
|
|
{
|
|
"_allocate_size": "min",
|
|
"label": "Base System",
|
|
"min_size": 19374,
|
|
"volumes": [
|
|
{
|
|
"mount": "/",
|
|
"size": "15360",
|
|
"type": "lv",
|
|
"name": "root",
|
|
"file_system": "ext4"
|
|
},
|
|
{
|
|
"mount": "swap",
|
|
"size": "4014",
|
|
"type": "lv",
|
|
"name": "swap",
|
|
"file_system": "swap"
|
|
}
|
|
],
|
|
"type": "vg",
|
|
"id": "os"
|
|
},
|
|
{
|
|
"_allocate_size": "all",
|
|
"label": "Image Storage",
|
|
"min_size": 5120,
|
|
"volumes": [
|
|
{
|
|
"mount": "/var/lib/glance",
|
|
"size": "175347",
|
|
"type": "lv",
|
|
"name": "glance",
|
|
"file_system": "xfs"
|
|
}
|
|
],
|
|
"type": "vg",
|
|
"id": "image"
|
|
},
|
|
{
|
|
"id": {
|
|
"type": "name",
|
|
"value": "sdd"
|
|
},
|
|
"volumes": [
|
|
{
|
|
"mount": "/var",
|
|
"size": "0",
|
|
"type": "raid",
|
|
"file_system": "ext2",
|
|
"name": "Boot"
|
|
},
|
|
{
|
|
"mount": "/tmp",
|
|
"size": "0",
|
|
"type": "partition",
|
|
"file_system": "ext2",
|
|
"partition_guid": "fake_guid",
|
|
"name": "TMP"
|
|
}
|
|
],
|
|
"type": "disk",
|
|
"size": "65587"
|
|
}
|
|
]
|
|
}
|
|
|
|
PROVISION_SAMPLE_DATA_RSYNC = {
|
|
'ks_meta': {
|
|
'rsync_root_path': "10.10.10.1::testroot/path",
|
|
"pm_data": {
|
|
"kernel_params": "console=ttyS0,9600 console=tty0 rootdelay=90 "
|
|
"nomodeset", },
|
|
'profile': ''
|
|
}
|
|
}
|
|
|
|
LIST_BLOCK_DEVICES_SAMPLE = [
|
|
{'scsi': '0:0:0:0',
|
|
'name': 'sda',
|
|
'device': '/dev/sda',
|
|
'path': [
|
|
'/dev/disk/by-id/ata-VBOX_HARDDISK',
|
|
'/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK',
|
|
'/dev/disk/by-id/wwn-fake_wwn_1']},
|
|
{'scsi': '1:0:0:0',
|
|
'name': 'sdb',
|
|
'device': '/dev/sdb',
|
|
'path': [
|
|
'/dev/disk/by-id/ata-VBOX_HARDDISK_VBf2923215-708af674',
|
|
'/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBf2923215-708af674',
|
|
'/dev/disk/by-id/wwn-fake_wwn_2']},
|
|
{'scsi': '2:0:0:0',
|
|
'name': 'sdc',
|
|
'device': '/dev/sdc',
|
|
'path': [
|
|
'/dev/disk/by-id/ata-VBOX_HARDDISK_VB50ee61eb-84e74fdf',
|
|
'/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB50ee61eb-84e74fdf',
|
|
'/dev/disk/by-id/wwn-fake_wwn_3',
|
|
'/dev/disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0']},
|
|
{'scsi': '3:0:0:0',
|
|
'name': 'sdd',
|
|
'device': '/dev/sdd',
|
|
'path': [
|
|
'/dev/disk/by-id/ata-VBOX_HARDDISK_VB50ee61eb-84fdf',
|
|
'/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB50e74fdf',
|
|
'/dev/disk/by-id/wwn-fake_wwn_3',
|
|
'/dev/disk/by-path/pci-0000:00:0d.0-scsi3:0:0:0']},
|
|
]
|
|
|
|
|
|
class _IronicTest(unittest2.TestCase):
|
|
def setUp(self):
|
|
super(_IronicTest, self).setUp()
|
|
with mock.patch.object(ironic.Ironic, 'validate_data'):
|
|
self.data_driver = ironic.Ironic({'partitions': []})
|
|
|
|
|
|
class TestIronicMatch(_IronicTest):
|
|
def test_match_device_by_scsi_matches(self):
|
|
# matches by scsi address
|
|
fake_ks_disk = {
|
|
'id': {
|
|
'type': 'scsi',
|
|
'value': '0:0:0:1'
|
|
}
|
|
}
|
|
fake_hu_disk = {
|
|
'scsi': '0:0:0:1'
|
|
}
|
|
self.assertTrue(
|
|
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
|
|
|
def test_match_device_by_scsi_not_matches(self):
|
|
# matches by scsi address
|
|
fake_ks_disk = {
|
|
'id': {
|
|
'type': 'scsi',
|
|
'value': '0:0:0:1'
|
|
}
|
|
}
|
|
fake_hu_disk = {
|
|
'scsi': '5:0:0:1'
|
|
}
|
|
self.assertFalse(
|
|
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
|
|
|
def test_match_device_by_path_matches(self):
|
|
fake_ks_disk = {
|
|
'id': {
|
|
'type': 'path',
|
|
'value': 'disk/by-path/pci-0000:00:07.0-virtio-pci-virtio3'
|
|
}
|
|
}
|
|
fake_hu_disk = {
|
|
'path': [
|
|
"/dev/disk/by-path/pci-0000:00:07.0-virtio-pci-virtio3",
|
|
"/dev/disk/by-path/fake_path",
|
|
"/dev/sdd"
|
|
]
|
|
}
|
|
self.assertTrue(
|
|
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
|
|
|
def test_match_device_by_path_not_matches(self):
|
|
fake_ks_disk = {
|
|
'id': {
|
|
'type': 'path',
|
|
'value': 'disk/by-path/pci-0000:00:07.0-virtio-pci-virtio3'
|
|
}
|
|
}
|
|
fake_hu_disk = {
|
|
'path': [
|
|
"/dev/disk/by-path/fake_path",
|
|
"/dev/sdd"
|
|
]
|
|
}
|
|
self.assertFalse(
|
|
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
|
|
|
def test_match_device_by_name_matches(self):
|
|
fake_ks_disk = {
|
|
'id': {
|
|
'type': 'name',
|
|
'value': 'sda'
|
|
}
|
|
}
|
|
fake_hu_disk = {
|
|
'name': '/dev/sda'
|
|
}
|
|
self.assertTrue(
|
|
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
|
|
|
def test_match_device_by_name_not_matches(self):
|
|
fake_ks_disk = {
|
|
'id': {
|
|
'type': 'name',
|
|
'value': 'sda'
|
|
}
|
|
}
|
|
fake_hu_disk = {
|
|
'name': '/dev/sdd'
|
|
}
|
|
self.assertFalse(
|
|
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
|
|
|
|
|
@mock.patch('bareon.utils.hardware.scsi_address', mock.Mock())
|
|
class TestNailgunMockedMeta(_IronicTest):
|
|
def test_partition_scheme(self):
|
|
with mock.patch.object(ironic.Ironic, 'validate_data'):
|
|
data_driver = ironic.Ironic(PROVISION_SAMPLE_DATA_SWIFT)
|
|
|
|
data_driver.get_image_ids = mock.MagicMock
|
|
mock_devices = data_driver._get_block_devices = mock.MagicMock()
|
|
mock_devices.return_value = LIST_BLOCK_DEVICES_SAMPLE
|
|
|
|
p_scheme = data_driver.partition_scheme
|
|
self.assertEqual(5, len(p_scheme.fss))
|
|
self.assertEqual(5, len(p_scheme.pvs))
|
|
self.assertEqual(3, len(p_scheme.lvs))
|
|
self.assertEqual(2, len(p_scheme.vgs))
|
|
self.assertEqual(3, len(p_scheme.parteds))
|
|
|
|
|
|
@mock.patch('bareon.utils.hardware.get_block_devices_from_udev_db')
|
|
class TestGetBlockDevices(_IronicTest):
|
|
def setUp(self):
|
|
super(TestGetBlockDevices, self).setUp()
|
|
self.mock_devices = mock.Mock()
|
|
self.data_driver._get_block_device_info = self.mock_devices
|
|
|
|
def test_no_devices(self, mock_get_block_devices_from_udev_db):
|
|
mock_get_block_devices_from_udev_db.return_value = []
|
|
|
|
result = self.data_driver._get_block_devices()
|
|
self.assertEqual(result, [])
|
|
mock_get_block_devices_from_udev_db.assert_called_once_with()
|
|
self.assertEqual(self.mock_devices.call_count, 0)
|
|
|
|
def test_device_info(self, mock_get_block_devices_from_udev_db):
|
|
data = {'test': 'fake'}
|
|
|
|
mock_get_block_devices_from_udev_db.return_value = [data]
|
|
self.mock_devices.return_value = block_device = 'test_value'
|
|
result = self.data_driver._get_block_devices()
|
|
self.assertEqual(result, [block_device])
|
|
mock_get_block_devices_from_udev_db.assert_called_once_with()
|
|
self.mock_devices.assert_called_once_with(data)
|
|
|
|
|
|
@mock.patch('bareon.utils.hardware.get_device_ids')
|
|
@mock.patch('bareon.utils.hardware.get_device_info')
|
|
@mock.patch('bareon.utils.hardware.scsi_address')
|
|
class TestGetBlockDevice(_IronicTest):
|
|
def test_no_device_info(self, mock_scsi_address, mock_get_device_info,
|
|
mock_get_device_ids):
|
|
device = 'fake_device'
|
|
|
|
mock_scsi_address.return_value = None
|
|
mock_get_device_info.return_value = {}
|
|
mock_get_device_ids.return_value = []
|
|
|
|
result = self.data_driver._get_block_device_info(device)
|
|
|
|
self.assertEqual(result, {'name': 'fake_device'})
|
|
|
|
def test_device_info(self, mock_scsi_address, mock_get_device_info,
|
|
mock_get_device_ids):
|
|
device = 'fake_device'
|
|
devpath = ['test/devpath']
|
|
uspec = {'DEVPATH': devpath}
|
|
|
|
mock_get_device_info.return_value = {
|
|
'uspec': uspec
|
|
}
|
|
mock_scsi_address.return_value = scsi_address = '1:0:0:0'
|
|
mock_get_device_ids.return_value = devpath
|
|
|
|
desired = {'path': devpath, 'name': device, 'scsi': scsi_address,
|
|
'uspec': uspec}
|
|
|
|
result = self.data_driver._get_block_device_info(device)
|
|
self.assertEqual(result, desired)
|
|
mock_get_device_info.assert_called_once_with(device)
|
|
mock_scsi_address.assert_called_once_with(device)
|
|
|
|
|
|
@mock.patch('bareon.drivers.data.ironic.Ironic.validate_data', mock.Mock())
|
|
class TestGetGrub(unittest2.TestCase):
|
|
@mock.patch('bareon.utils.utils.parse_kernel_cmdline')
|
|
def test_kernel_params(self, cmdline_mock):
|
|
data = {'deploy_data': {'kernel_params': "test_param=test_val",
|
|
'other_data': 'test'},
|
|
'partitions': {}}
|
|
cmdline_mock.return_value = {
|
|
"BOOTIF": "01-52-54-00-a5-55-58",
|
|
"extrastuff": "test123"
|
|
}
|
|
|
|
data_driver = ironic.Ironic(data)
|
|
|
|
self.assertEqual('test_param=test_val BOOTIF=01-52-54-00-a5-55-58',
|
|
data_driver.grub.kernel_params)
|
|
|
|
def test_no_kernel_params(self):
|
|
data = {'deploy_data': {'other_data': "test"},
|
|
'partitions': {}}
|
|
data_driver = ironic.Ironic(data)
|
|
|
|
self.assertEqual('', data_driver.grub.kernel_params)
|
|
|
|
|
|
@mock.patch('bareon.drivers.data.ironic.Ironic.validate_data', mock.Mock())
|
|
class TestPartitionsPolicy(unittest2.TestCase):
|
|
def test_partitions_policy(self):
|
|
data = {'partitions_policy': "test_value",
|
|
'partitions': {}}
|
|
|
|
data_driver = ironic.Ironic(data)
|
|
|
|
self.assertEqual('test_value', data_driver.partitions_policy)
|
|
|
|
def test_partitions_policy_default(self):
|
|
data = {'partitions': {}}
|
|
|
|
data_driver = ironic.Ironic(data)
|
|
|
|
self.assertEqual('verify', data_driver.partitions_policy)
|