# Copyright 2016 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. from rally import exceptions from rally.task import types from rally.task import validation from rally_openstack.common import consts from rally_openstack.task import scenario from rally_openstack.task.scenarios.nova import utils """Scenarios for Nova aggregates.""" @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True) @scenario.configure(name="NovaAggregates.list_aggregates", platform="openstack") class ListAggregates(utils.NovaScenario): def run(self): """List all nova aggregates. Measure the "nova aggregate-list" command performance. """ self._list_aggregates() @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True) @scenario.configure(context={"admin_cleanup@openstack": ["nova"]}, name="NovaAggregates.create_and_list_aggregates", platform="openstack") class CreateAndListAggregates(utils.NovaScenario): """scenario for create and list aggregate.""" def run(self, availability_zone): """Create a aggregate and then list all aggregates. This scenario creates a aggregate and then lists all aggregates. :param availability_zone: The availability zone of the aggregate """ aggregate = self._create_aggregate(availability_zone) msg = "Aggregate isn't created" self.assertTrue(aggregate, err_msg=msg) all_aggregates = self._list_aggregates() msg = ("Created aggregate is not in the" " list of all available aggregates") self.assertIn(aggregate, all_aggregates, err_msg=msg) @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True) @scenario.configure(context={"admin_cleanup@openstack": ["nova"]}, name="NovaAggregates.create_and_delete_aggregate", platform="openstack") class CreateAndDeleteAggregate(utils.NovaScenario): """Scenario for create and delete aggregate.""" def run(self, availability_zone): """Create an aggregate and then delete it. This scenario first creates an aggregate and then delete it. :param availability_zone: The availability zone of the aggregate """ aggregate = self._create_aggregate(availability_zone) self._delete_aggregate(aggregate) @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True) @scenario.configure(context={"admin_cleanup@openstack": ["nova"]}, name="NovaAggregates.create_and_update_aggregate", platform="openstack") class CreateAndUpdateAggregate(utils.NovaScenario): """Scenario for create and update aggregate.""" def run(self, availability_zone): """Create an aggregate and then update its name and availability_zone This scenario first creates an aggregate and then update its name and availability_zone :param availability_zone: The availability zone of the aggregate """ aggregate = self._create_aggregate(availability_zone) self._update_aggregate(aggregate) @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True) @scenario.configure(context={"admin_cleanup@openstack": ["nova"]}, name="NovaAggregates.create_aggregate_add_and_remove_host", platform="openstack") class CreateAggregateAddAndRemoveHost(utils.NovaScenario): """Scenario for add a host to and remove the host from an aggregate.""" def run(self, availability_zone): """Create an aggregate, add a host to and remove the host from it Measure "nova aggregate-add-host" and "nova aggregate-remove-host" command performance. :param availability_zone: The availability zone of the aggregate """ aggregate = self._create_aggregate(availability_zone) hosts = self._list_hypervisors() host_name = hosts[0].service["host"] self._aggregate_add_host(aggregate, host_name) self._aggregate_remove_host(aggregate, host_name) @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True) @scenario.configure(context={"admin_cleanup@openstack": ["nova"]}, name="NovaAggregates.create_and_get_aggregate_details", platform="openstack") class CreateAndGetAggregateDetails(utils.NovaScenario): """Scenario for create and get aggregate details.""" def run(self, availability_zone): """Create an aggregate and then get its details. This scenario first creates an aggregate and then get details of it. :param availability_zone: The availability zone of the aggregate """ aggregate = self._create_aggregate(availability_zone) self._get_aggregate_details(aggregate) @types.convert(image={"type": "glance_image"}) @validation.add("required_services", services=[consts.Service.NOVA]) @validation.add("required_platform", platform="openstack", admin=True, users=True) @scenario.configure( context={"admin_cleanup@openstack": ["nova"], "cleanup@openstack": ["nova"]}, name="NovaAggregates.create_aggregate_add_host_and_boot_server", platform="openstack") class CreateAggregateAddHostAndBootServer(utils.NovaScenario): """Scenario to verify an aggregate.""" def run(self, image, metadata, availability_zone=None, ram=512, vcpus=1, disk=1, boot_server_kwargs=None): """Scenario to create and verify an aggregate This scenario creates an aggregate, adds a compute host and metadata to the aggregate, adds the same metadata to the flavor and creates an instance. Verifies that instance host is one of the hosts in the aggregate. :param image: The image ID to boot from :param metadata: The metadata to be set as flavor extra specs :param availability_zone: The availability zone of the aggregate :param ram: Memory in MB for the flavor :param vcpus: Number of VCPUs for the flavor :param disk: Size of local disk in GB :param boot_server_kwargs: Optional additional arguments to verify host aggregates :raises RallyException: if instance and aggregate hosts do not match """ boot_server_kwargs = boot_server_kwargs or {} aggregate = self._create_aggregate(availability_zone) hosts = self._list_hypervisors() host_name = None for i in range(len(hosts)): if hosts[i].state == "up" and hosts[i].status == "enabled": host_name = hosts[i].service["host"] break if not host_name: raise exceptions.RallyException("Could not find an available host") self._aggregate_set_metadata(aggregate, metadata) self._aggregate_add_host(aggregate, host_name) flavor = self._create_flavor(ram, vcpus, disk) flavor.set_keys(metadata) server = self._boot_server(image, flavor.id, **boot_server_kwargs) # NOTE: we need to get server object by admin user to obtain # "hypervisor_hostname" attribute server = self.admin_clients("nova").servers.get(server.id) instance_hostname = getattr(server, "OS-EXT-SRV-ATTR:hypervisor_hostname") if instance_hostname != host_name: raise exceptions.RallyException("Instance host and aggregate " "host are different")