diff --git a/browbeat-config.yaml b/browbeat-config.yaml index a8d8260cd..6c1ae09ba 100644 --- a/browbeat-config.yaml +++ b/browbeat-config.yaml @@ -46,6 +46,7 @@ rally: - nova: rally/rally-plugins/nova - browbeat: rally/rally-plugins/browbeat - workloads: rally/rally-plugins/workloads + - dynamic-workloads: rally/rally-plugins/dynamic-workloads shaker: server: 1.1.1.1 port: 5555 @@ -525,3 +526,20 @@ workloads: concurrency_level: 10 send_results: true file: rally/rally-plugins/workloads/abench.yml + + - name: dynamic-workloads + enabled: false + type: rally + rally_deployment: overcloud + concurrency: + - 1 + times: 1 + scenarios: + - name: dynamic-workload-1 + enabled: true + enable_dhcp: true + image_name: cirros + flavor_name: m1.small + num_vms: 10 + file: rally/rally-plugins/dynamic-workloads/dynamic_workload.yml + diff --git a/rally/rally-plugins/dynamic-workloads/README.rst b/rally/rally-plugins/dynamic-workloads/README.rst new file mode 100644 index 000000000..e175d0db2 --- /dev/null +++ b/rally/rally-plugins/dynamic-workloads/README.rst @@ -0,0 +1,6 @@ +Browbeat Rally Plugin: dynamic-workloads +====================================== + +Functions: +---------- +- create_delete_servers: Create 'N' VMs and delete 'N/2' VMs during test. diff --git a/rally/rally-plugins/dynamic-workloads/base.py b/rally/rally-plugins/dynamic-workloads/base.py new file mode 100644 index 000000000..97959c428 --- /dev/null +++ b/rally/rally-plugins/dynamic-workloads/base.py @@ -0,0 +1,49 @@ +# 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 logging +from rally_openstack.scenarios.neutron import utils as neutron_utils +from rally_openstack.scenarios.vm import utils as vm_utils + +LOG = logging.getLogger(__name__) + + +class DynamicBase(vm_utils.VMScenario, neutron_utils.NeutronScenario): + def create_delete_servers(self, image, flavor, num_vms=1, min_sleep=0, max_sleep=10, + network_create_args=None, subnet_create_args=None): + """Creates servers and deletes servers. + + :param image: image ID or instance for server creation + :param flavor: int, flavor ID or instance for server creation + :param num_vms: int, number of servers to create + :param min_sleep: int, minimum duration to sleep before deleting a server + :param max_sleep: int, maximum duration to sleep before deleting a server + :param network_create_args: dict, arguments for network creation + :param subnet_create_args: dict, arguments for subnet creation + """ + network = self._create_network(network_create_args or {}) + self._create_subnet(network, subnet_create_args or {}) + kwargs = {} + kwargs["nics"] = [{"net-id": network["network"]["id"]}] + servers = [] + + for i in range(num_vms): + server = self._boot_server(image, flavor, **kwargs) + LOG.info("Created server {} when i = {}".format(server,i)) + servers.append(server) + # Delete least recently created server from list when i=1,3,5,7..... + if i % 2 == 1: + self.sleep_between(min_sleep, max_sleep) + server_to_delete = servers[0] + self._delete_server(server_to_delete, force=True) + LOG.info("Deleted server {} when i = {}".format(server_to_delete,i)) + servers.pop(0) diff --git a/rally/rally-plugins/dynamic-workloads/dynamic_workload.py b/rally/rally-plugins/dynamic-workloads/dynamic_workload.py new file mode 100644 index 000000000..c0441b40f --- /dev/null +++ b/rally/rally-plugins/dynamic-workloads/dynamic_workload.py @@ -0,0 +1,33 @@ +# 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_openstack import consts +from rally.task import scenario +from rally.task import types +from rally.task import validation +import base + + +@types.convert(image={"type": "glance_image"}, flavor={"type": "nova_flavor"}) +@validation.add("image_valid_on_flavor", flavor_param="flavor", image_param="image") +@validation.add( + "required_services", services=[consts.Service.NEUTRON, consts.Service.NOVA] +) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure( + context={"cleanup@openstack": ["neutron", "nova"]}, + name="BrowbeatPlugin.dynamic_workload", + platform="openstack", +) +class DynamicWorkload(base.DynamicBase): + def run(self, image, flavor, num_vms, subnet_create_args, **kwargs): + self.create_delete_servers(image, flavor, num_vms, subnet_create_args=subnet_create_args) diff --git a/rally/rally-plugins/dynamic-workloads/dynamic_workload.yml b/rally/rally-plugins/dynamic-workloads/dynamic_workload.yml new file mode 100644 index 000000000..b46524875 --- /dev/null +++ b/rally/rally-plugins/dynamic-workloads/dynamic_workload.yml @@ -0,0 +1,41 @@ +{% set image_name = image_name or 'cirros' %} +{% set flavor_name = flavor_name or 'm1.xtiny' %} +{% set enable_dhcp = enable_dhcp or true %} +{% set num_vms = num_vms or 1 %} +{% set sla_max_avg_duration = sla_max_avg_duration or 60 %} +{% set sla_max_failure = sla_max_failure or 0 %} +{% set sla_max_seconds = sla_max_seconds or 60 %} +--- +BrowbeatPlugin.dynamic_workload: + - + args: + flavor: + name: '{{flavor_name}}' + image: + name: '{{image_name}}' + network_create_args: {} + subnet_create_args: {'enable_dhcp': '{{enable_dhcp}}'} + num_vms: {{num_vms}} + runner: + concurrency: {{concurrency}} + times: {{times}} + type: 'constant' + context: + users: + tenants: 1 + users_per_tenant: 1 + quotas: + neutron: + network: -1 + port: -1 + router: -1 + subnet: -1 + nova: + instances: -1 + cores: -1 + ram: -1 + sla: + max_avg_duration: {{sla_max_avg_duration}} + max_seconds_per_iteration: {{sla_max_seconds}} + failure_rate: + max: {{sla_max_failure}}