diff --git a/nova/tests/functional/test_scheduler.py b/nova/tests/functional/test_scheduler.py index 77cf5f9c2955..6c9d66d99a32 100644 --- a/nova/tests/functional/test_scheduler.py +++ b/nova/tests/functional/test_scheduler.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime + from nova.compute import instance_actions from nova import test from nova.tests import fixtures as nova_fixtures @@ -21,6 +23,115 @@ CELL1_NAME = 'cell1' CELL2_NAME = 'cell2' +class AggregateImagePropertiesIsolationTestCase( + integrated_helpers._IntegratedTestBase, +): + """Test the AggregateImagePropertiesIsolation filter.""" + + def setUp(self): + self.flags( + enabled_filters=['AggregateImagePropertiesIsolation'], + group='filter_scheduler') + + super().setUp() + + def _create_aggregate(self, metadata): + aggregate = self.admin_api.post_aggregate( + {'aggregate': {'name': 'my-aggregate'}}) + aggregate = self.admin_api.post_aggregate_action( + aggregate['id'], + {'set_metadata': {'metadata': metadata}}) + self.admin_api.add_host_to_aggregate( + aggregate['id'], self.compute.host) + return aggregate + + def _create_image(self, metadata): + image = { + 'id': 'c456eb30-91d7-4f43-8f46-2efd9eccd744', + 'name': 'fake-image-custom-property', + 'created_at': datetime.datetime(2011, 1, 1, 1, 2, 3), + 'updated_at': datetime.datetime(2011, 1, 1, 1, 2, 3), + 'deleted_at': None, + 'deleted': False, + 'status': 'active', + 'is_public': False, + 'container_format': 'raw', + 'disk_format': 'raw', + 'size': '25165824', + 'min_ram': 0, + 'min_disk': 0, + 'protected': False, + 'visibility': 'public', + 'tags': ['tag1', 'tag2'], + 'properties': { + 'kernel_id': 'nokernel', + 'ramdisk_id': 'nokernel', + }, + } + image['properties'].update(metadata) + return self.glance.create(None, image) + + def test_filter_passes(self): + """Ensure the filter allows hosts in aggregates with matching metadata. + """ + self._create_aggregate(metadata={'os_type': 'windows'}) + image = self._create_image(metadata={'os_type': 'windows'}) + self._create_server(image_uuid=image['id']) + + def test_filter_rejects(self): + """Ensure the filter rejects hosts in aggregates with mismatched + metadata. + """ + self._create_aggregate(metadata={'os_type': 'windows'}) + image = self._create_image(metadata={'os_type': 'linux'}) + self._create_server(image_uuid=image['id'], expected_state='ERROR') + + def test_filter_passes_with_prefix(self): + """Ensure the filter allows hosts in aggregates with matching metadata + when a namespace is configured. + """ + self.flags( + aggregate_image_properties_isolation_namespace='os', + aggregate_image_properties_isolation_separator='_', + group='filter_scheduler', + ) + self._create_aggregate(metadata={'os_type': 'windows'}) + image = self._create_image(metadata={'os_type': 'windows'}) + self._create_server(image_uuid=image['id']) + + def test_filter_rejects_with_prefix(self): + """Ensure the filter rejects hosts in aggregates with matching metadata + when a namespace is configured. + """ + self.flags( + aggregate_image_properties_isolation_namespace='os', + aggregate_image_properties_isolation_separator='_', + group='filter_scheduler', + ) + self._create_aggregate(metadata={'os_type': 'windows'}) + image = self._create_image(metadata={'os_type': 'linux'}) + self._create_server(image_uuid=image['id'], expected_state='ERROR') + + def test_filter_passes_with_invalid_key(self): + """Ensure invalid keys are ignored by the filter.""" + self._create_aggregate(metadata={'type': 'windows'}) + image = self._create_image(metadata={'type': 'linux'}) + self._create_server(image_uuid=image['id']) + + def test_filter_passes_with_irrelevant_key(self): + """Ensure valid keys that are no in the namespace are ignored by the + filter. + """ + self.flags( + aggregate_image_properties_isolation_namespace='os', + aggregate_image_properties_isolation_separator='_', + group='filter_scheduler', + ) + self._create_aggregate(metadata={'os_type': 'windows'}) + image = self._create_image(metadata={'hw_firmware_type': 'uefi'}) + self._create_server(image_uuid=image['id']) + + class MultiCellSchedulerTestCase(test.TestCase, integrated_helpers.InstanceHelperMixin):