diff --git a/doc/source/test_plans/controlplane_density/configs/boot_attach_and_list_with_secgroups.json b/doc/source/test_plans/controlplane_density/configs/boot_attach_and_list_with_secgroups.json new file mode 100644 index 0000000..984b198 --- /dev/null +++ b/doc/source/test_plans/controlplane_density/configs/boot_attach_and_list_with_secgroups.json @@ -0,0 +1,62 @@ +{% set flavor_name = flavor_name or "m1.tiny" %} +{% set image_name = image_name or "^(cirros.*uec|TestVM)$" %} +{ + "NovaDensityPlugin.boot_attach_and_list_with_secgroups": [ + { + "args": { + "flavor": { + "name": "{{flavor_name}}" + }, + "image": { + "name": "{{image_name}}" + }, + "security_group_count": 10, + "rules_per_security_group": 10, + "boot_server_kwargs": { "auto_assign_nic" : true }, + "create_volume_kwargs": {}, + "volume_size": 1 + }, + "runner": { + "type": "constant", + "times": {{ 10 * compute }}, + "concurrency": {{concurrency}} + }, + "context": { + "users": { + "tenants": 10, + "users_per_tenant": 10 + }, + "quotas": { + "neutron": { + "network": -1, + "security_group": -1, + "security_group_rule": -1, + "port": -1, + "subnet": -1, + "router": -1 + }, + "nova": { + "instances": -1, + "cores": -1, + "ram": -1, + "floating_ips": -1, + "security_groups": -1, + "security_group_rules": -1 + }, + "cinder": { + "volumes": -1, + "gigabytes": -1, + "snapshots": -1 + } + }, + "network": { + "start_cidr": "{{ "100.1.0.0/25" if gre_enabled else "1.0.0.0/25" }}", + "networks_per_tenant": 10 + } + }, + "sla": { + "failure_rate": { "max": 0 } + } + } + ] +} diff --git a/doc/source/test_plans/controlplane_density/configs/nova_density.py b/doc/source/test_plans/controlplane_density/configs/nova_density.py new file mode 100644 index 0000000..03bd7b3 --- /dev/null +++ b/doc/source/test_plans/controlplane_density/configs/nova_density.py @@ -0,0 +1,173 @@ +# Copyright 2016: Mirantis 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. + +from rally import consts +from rally.plugins.openstack import scenario +from rally.plugins.openstack.scenarios.cinder import utils as cinder_utils +from rally.plugins.openstack.scenarios.nova import utils +from rally.task import types +from rally.task import validation + + +class NovaDensityPlugin(utils.NovaScenario, cinder_utils.CinderScenario): + """boot_attach_and_list_with_secgroups""" + @types.convert(image={"type": "glance_image"}, + flavor={"type": "nova_flavor"}) + @validation.image_valid_on_flavor("flavor", "image") + @validation.required_parameters("security_group_count", + "rules_per_security_group") + @validation.required_contexts("network") + @validation.required_services(consts.Service.NOVA) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["cinder", "nova"]}) + def boot_attach_and_list_with_secgroups( + self, image, flavor, + volume_size, + security_group_count, + rules_per_security_group, + do_delete=False, + detailed=True, + boot_server_kwargs=None, + create_volume_kwargs=None + ): + + if boot_server_kwargs is None: + boot_server_kwargs = {} + if create_volume_kwargs is None: + create_volume_kwargs = {} + + security_groups = self._create_security_groups( + security_group_count) + self._create_rules_for_security_group(security_groups, + rules_per_security_group) + + secgroups_names = [sg.name for sg in security_groups] + """boot server""" + server = self._boot_server(image, flavor, + security_groups=secgroups_names, + **boot_server_kwargs) + + volume = self._create_volume(volume_size, **create_volume_kwargs) + self._attach_volume(server, volume) + + self._list_security_groups() + self._list_servers(detailed) + + if do_delete: + self._detach_volume(server, volume) + self._delete_server(server) + self._delete_volume(volume) + self._delete_security_groups(security_groups) + + """boot_and_list_with_secgroups""" + @types.convert(image={"type": "glance_image"}, + flavor={"type": "nova_flavor"}) + @validation.image_valid_on_flavor("flavor", "image") + @validation.required_parameters("security_group_count", + "rules_per_security_group") + @validation.required_contexts("network") + @validation.required_services(consts.Service.NOVA) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["nova"]}) + def boot_and_list_with_secgroups( + self, image, flavor, + security_group_count, + rules_per_security_group, + do_delete=False, + detailed=True, + boot_server_kwargs=None + ): + + if boot_server_kwargs is None: + boot_server_kwargs = {} + + security_groups = self._create_security_groups( + security_group_count) + self._create_rules_for_security_group(security_groups, + rules_per_security_group) + + secgroups_names = [sg.name for sg in security_groups] + """boot server""" + server = self._boot_server(image, flavor, + security_groups=secgroups_names, + **boot_server_kwargs) + + self._list_security_groups() + self._list_servers(detailed) + + if do_delete: + self._delete_server(server) + self._delete_security_groups(security_groups) + + """boot_attach_and_list""" + @types.convert(image={"type": "glance_image"}, + flavor={"type": "nova_flavor"}) + @validation.image_valid_on_flavor("flavor", "image") + @validation.required_services(consts.Service.NOVA) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["cinder", "nova"]}) + def boot_attach_and_list( + self, image, flavor, + volume_size, + do_delete=False, + detailed=True, + boot_server_kwargs=None, + create_volume_kwargs=None + ): + + if boot_server_kwargs is None: + boot_server_kwargs = {} + if create_volume_kwargs is None: + create_volume_kwargs = {} + + """boot server""" + server = self._boot_server(image, flavor, + **boot_server_kwargs) + + volume = self._create_volume(volume_size, **create_volume_kwargs) + self._attach_volume(server, volume) + + self._list_servers(detailed) + + if do_delete: + self._detach_volume(server, volume) + self._delete_server(server) + self._delete_volume(volume) + + """boot_and_list""" + @types.convert(image={"type": "glance_image"}, + flavor={"type": "nova_flavor"}) + @validation.image_valid_on_flavor("flavor", "image") + @validation.required_services(consts.Service.NOVA) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["nova"]}) + def boot_and_list( + self, image, flavor, + do_delete=False, + detailed=True, + boot_server_kwargs=None + ): + + if boot_server_kwargs is None: + boot_server_kwargs = {} + + """boot server""" + server = self._boot_server(image, flavor, + **boot_server_kwargs) + + self._list_servers(detailed) + + if do_delete: + self._delete_server(server) diff --git a/doc/source/test_plans/controlplane_density/plan.rst b/doc/source/test_plans/controlplane_density/plan.rst new file mode 100644 index 0000000..e3fcadd --- /dev/null +++ b/doc/source/test_plans/controlplane_density/plan.rst @@ -0,0 +1,187 @@ +.. _controlplane_density: + +======================================= +OpenStack Control Plane Density testing +======================================= + +:status: **ready** +:version: 1 + +:Abstract: + + This document describes a test plan for measuring OpenStack control plane + performance under with large number of items in terms of ability to handle + specific amount of objects like VMs, networks, subnets etc. + + +Test Plan +========= + +Test Environment +---------------- + +This section describes the setup for OpenStack testing. +In these tests basic multi-node setup with OpenStack services comprises 6 +physical nodes: + * Three nodes for a compute node. This node simulates activity which is + typical for OpenStack compute components. + * Three nodes for a controller nodes. These node simulate activity which + is typical for OpenStack control plane services, including running three + MySQL instances managed by Galera cluster and memcached cluster for + Keystone caching. + +Preparation +^^^^^^^^^^^ + +**Single node installation** + +For single node installation the one can use DevStack_ tool that is targeted +at developers and CI systems to use upstream code. It makes many choices that +are not appropriate for production systems, but for the all-in-one purposes +this can fit ok. + + +**Multi node installation** + +Multi node environment installation depends much on the chosen set of OpenStack +deployment tools. + + +Environment description +^^^^^^^^^^^^^^^^^^^^^^^ + +The environment description includes hardware specification of servers, +network parameters, operation system and OpenStack deployment characteristics. + +.. table:: Amount of servers each role + + +------------+--------------+ + |Role |Servers count | + +============+==============+ + |rally |1 | + +------------+--------------+ + |controller |3 | + +------------+--------------+ + |compute |176 | + +------------+--------------+ + |compute-osd |20 | + +------------+--------------+ + |osd |0 | + +------------+--------------+ + +Hardware configuration of each server +------------------------------------- +All servers have same configuration describing in table below + +.. table:: Description of servers hardware + + +-------+----------------+-------------------------------+ + |server |vendor,model |HP,DL380 Gen9 | + +-------+----------------+-------------------------------+ + |CPU |vendor,model |Intel,E5-2680 v3 | + | +----------------+-------------------------------+ + | |processor_count |2 | + | +----------------+-------------------------------+ + | |core_count |12 | + | +----------------+-------------------------------+ + | |frequency_MHz |2500 | + +-------+----------------+-------------------------------+ + |RAM |vendor,model |HP,752369-081 | + | +----------------+-------------------------------+ + | |amount_MB |262144 | + +-------+----------------+-------------------------------+ + |NETWORK|interface_name |p1p1 | + | +----------------+-------------------------------+ + | |vendor,model |Intel,X710 Dual Port | + | +----------------+-------------------------------+ + | |bandwidth |10G | + +-------+----------------+-------------------------------+ + |STORAGE|dev_name |/dev/sda | + | +----------------+-------------------------------+ + | |vendor,model | | raid10 - HP P840 | + | | | | 12 disks EH0600JEDHE | + | +----------------+-------------------------------+ + | |SSD/HDD |HDD | + | +----------------+-------------------------------+ + | |size | 3,6TB | + +-------+----------------+-------------------------------+ + +Test Case 1: perform baseline Rally scenarios +--------------------------------------------- + +Description +^^^^^^^^^^^ + +1. Create work directory on server. In future we will call it as WORK_DIR +2. Create directory "plugins" in WORK_DIR and copy to the directory + :download:`nova_density.py ` plugin. +3. Create directory "scenarios" in WORK_DIR and copy to the directory + :download:`boot_attach_and_list_with_secgroups.json ` + scenario. +4. Create `deployment.json` file in WORK_DIR and fill it with OpenStack + environment info. Example of how it may look like is presented below: + + .. code:: json + + { + "admin": { + "password": "password", + "tenant_name": "tenant", + "username": "user" + }, + "auth_url": "http://1.2.3.4:5000/v2.0", + "region_name": "RegionOne", + "type": "ExistingCloud", + "endpoint_type": "internal", + "admin_port": 35357, + "https_insecure": true + } + +5. Create `job-params.yaml` file in WORK_DIR and fill it with scenarios info. + Example of how it may look like is presented below: + + .. code:: yaml + + --- + concurrency: 5 + compute: 196 + start_cidr: "1.0.0.0/16" + current_path: "/home/rally/rally-scenarios/heat/" + floating_ip_amount: 800 + floating_net: "admin_floating_net" + vlan_amount: 1025 + gre_enabled: false + http_server_with_glance_images: "1.2.3.4" + +6. Perform tests: + + .. code:: bash + + ${WORK_DIR:?} + DEPLOYMENT_NAME="$(uuidgen)" + DEPLOYMENT_CONFIG="${WORK_DIR}/deployment.json" + PLUGIN_PATH="${WORK_DIR}/plugins/nova_scale.py" + JOB_PARAMS_CONFIG="${WORK_DIR}/job-params.yaml" + rally deployment create --filename $(DEPLOYMENT_CONFIG) --name $(DEPLOYMENT_NAME) + SCENARIOS="boot_attach_and_list_with_secgroups.json" + for scenario in SCENARIOS; do + rally --plugin-paths ${PLUGINS_PATH} task start --tag ${scenario} --task-args-file ${JOB_PARAMS_CONFIG} ${WORK_DR}/scenarios/${scenario} + done + task_list="$(rally task list --uuids-only)" + rally task report --tasks ${task_list} --out=${WORK_DIR}/rally_report.html + +List of performance metrics +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Foe each component under test define atomic actions made in terms of this test +case. Define what time does it take to perform this specific action (minimum, +maximum, mean and percentiles across all attempts to perform this action). + +For example, in case of Cinder testing final measurement for volume creation +may look like: + ++---------------+----------------+--------------------+-------------------+-------------+-------------+ +| Operation | Mean | 90%ile | 50%ile | Max | Min | ++===============+================+====================+===================+=============+=============+ +| create_volume | | <90%ile_numbers> | <50%ile_numbers> | | | ++---------------+----------------+--------------------+-------------------+-------------+-------------+ diff --git a/doc/source/test_plans/index.rst b/doc/source/test_plans/index.rst index 64079f1..9f065b6 100644 --- a/doc/source/test_plans/index.rst +++ b/doc/source/test_plans/index.rst @@ -23,4 +23,4 @@ Test Plans 1000_nodes/plan reliability/plan control_plane/plan - + controlplane_density/plan