diff --git a/browbeat-config.yaml b/browbeat-config.yaml index 81eec34b2..d3330a63e 100644 --- a/browbeat-config.yaml +++ b/browbeat-config.yaml @@ -58,6 +58,7 @@ rally: - workloads: rally/rally-plugins/workloads - dynamic-workloads: rally/rally-plugins/dynamic-workloads - reports: rally/rally-plugins/reports + - manila: rally/rally-plugins/manila shaker: server: 1.1.1.1 port: 5555 @@ -698,3 +699,12 @@ workloads: access: "127.0.0.1" access_type: "ip" file: rally/manila/create-share-allow-and-deny-access.yml + - name: create-share-boot-vm-mount-share-write-delete-vm-share + enabled: true + flavor_name: m1.small + image_name: centos7 + user: centos + share_type: default + provider_net_id: + ext_net_id: + file: rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.yml diff --git a/rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.py b/rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.py new file mode 100644 index 000000000..b375f5dc9 --- /dev/null +++ b/rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.py @@ -0,0 +1,159 @@ +# 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.common import logging +from rally import exceptions +from rally.task import types +from rally.task import utils as rally_utils +from rally.task import validation +from rally.task import scenario + +from rally_openstack.common import consts +from rally_openstack.task.scenarios.manila import utils +from rally_openstack.task.scenarios.vm import utils as vm_utils +from rally_openstack.task.scenarios.neutron import utils as neutron_utils + +"""Scenarios for Manila shares.""" + +LOG = logging.getLogger(__name__) + +@types.convert(image={"type": "glance_image"}, + flavor={"type": "nova_flavor"}) +@validation.add("image_valid_on_flavor", flavor_param="flavor", + image_param="image", fail_on_404_image=False) +@validation.add("number", param_name="port", minval=1, maxval=65535, + nullable=True, integer_only=True) +@validation.add("external_network_exists", param_name="floating_network") +@validation.add("required_services", services=[consts.Service.MANILA, + consts.Service.NEUTRON, + consts.Service.NOVA]) +@validation.add("required_platform", platform="openstack", users=True) +@scenario.configure(context={"cleanup@openstack": ["manila", "nova", "neutron"], + "keypair@openstack": {}, + "allow_ssh@openstack": None}, + name="BrowbeatPlugin.create_share_boot_vm_access_share", + platform="openstack") +class CreateNFSShareBootVMAndAccessShare(utils.ManilaScenario, vm_utils.VMScenario, + neutron_utils.NeutronScenario): + def run(self, image, flavor, username, provider_net_id, ext_net_id, size=1, password=None, + router_create_args=None, network_create_args=None, subnet_create_args=None, + port=22, use_floating_ip=True, force_delete=False, max_log_length=None, + **kwargs): + """Create a share and access it from VM. + + - create NFS share + - launch VM + - Attach provider network (StorageNFS) to VM + - authorize VM's ip (StorageNFS) to access the share + - mount share inside the VM + - write to share + - delete VM + - delete share + + :param size: share size in GB, should be greater than 0 + :param image: glance image name to use for the vm + :param flavor: VM flavor name + :param username: ssh username on server + :param provider_net_id: ID of the StorageNFS provider network + :param ext_net_id: ID of external network + :param password: Password on SSH authentication + :param floating_network: external network name, for floating ip + :param port: ssh port for SSH connection + :param use_floating_ip: bool, floating or fixed IP for SSH connection + :param force_delete: whether to use force_delete for servers + :param max_log_length: The number of tail nova console-log lines user + would like to retrieve + :param kwargs: optional args to create a share or a VM + """ + share_proto = "nfs" + share = self._create_share( + share_proto=share_proto, + size=size, + **kwargs) + location = self._export_location(share) + + ext_net_name = self.clients("neutron").show_network( + ext_net_id)["network"]["name"] + router_create_args["tenant_id"] = self.context["tenant"]["id"] + router_create_args.setdefault("external_gateway_info", + {"network_id": ext_net_id, "enable_snat": True}) + router = self.admin_clients("neutron").create_router({"router": router_create_args}) + + network = self._create_network(network_create_args or {}) + subnet = self._create_subnet(network, subnet_create_args or {}) + self._add_interface_router(subnet['subnet'], router['router']) + kwargs["nics"] = [{"net-id": network['network']['id']}] + + server, fip = self._boot_server_with_fip( + image, flavor, use_floating_ip=use_floating_ip, + floating_network=ext_net_name, + key_name=self.context["user"]["keypair"]["name"], + **kwargs) + self._attach_interface(server, net_id=provider_net_id) + server = self._show_server(server) + + for net in server.addresses: + if str(net) == self.clients("neutron").show_network(provider_net_id)["network"]["name"]: + ip = str(server.addresses[net][0]["addr"]) + self._allow_access_share(share, "ip", ip, "rw") + + mount_opt = "-t nfs -o nfsvers=4.1,proto=tcp" + test_data = "Test Data" + script = f"sudo cloud-init status -w;" \ + f"sudo ip add add {ip}/24 dev eth1;" \ + f"sudo ip link set eth1 up;" \ + f"sudo mount {mount_opt} {location[0]} /mnt || exit 1;" \ + f"df -h;" \ + f"sudo echo {test_data} | sudo tee /mnt/testfile || exit 2" + + command = { + "script_inline": script, + "interpreter": "/bin/bash" + } + try: + rally_utils.wait_for_status( + server, + ready_statuses=["ACTIVE"], + update_resource=rally_utils.get_from_manager(), + ) + + code, out, err = self._run_command( + fip["ip"], port, username, password, command=command) + if code: + raise exceptions.ScriptError( + "Error running command %(command)s. " + "Error %(code)s: %(error)s" % { + "command": command, "code": code, "error": err}) + except (exceptions.TimeoutException, + exceptions.SSHTimeout): + console_logs = self._get_server_console_output(server, + max_log_length) + LOG.debug("VM console logs:\n%s" % console_logs) + raise + + finally: + self._delete_server_with_fip(server, fip, + force_delete=force_delete) + self._delete_share(share) + self._remove_interface_router(subnet['subnet'], router['router']) + + self.add_output(complete={ + "title": "Script StdOut", + "chart_plugin": "TextArea", + "data": str(out).split("\n") + }) + if err: + self.add_output(complete={ + "title": "Script StdErr", + "chart_plugin": "TextArea", + "data": err.split("\n") + }) diff --git a/rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.yml b/rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.yml new file mode 100644 index 000000000..e579cddb2 --- /dev/null +++ b/rally/rally-plugins/manila/create-share-boot-vm-mount-share-write-delete-vm-share.yml @@ -0,0 +1,48 @@ +{% set image_name = image_name or "centos7" %} +{% set flavor_name = flavor_name or "m1.small" %} +{% 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.create_share_boot_vm_access_share: + - + args: + size: 1 + share_type: {{share_type}} + flavor: + name: {{flavor_name}} + image: + name: {{image_name}} + username: {{user}} + provider_net_id: "{{ provider_net_id }}" + ext_net_id: "{{ ext_net_id }}" + router_create_args: {} + network_create_args: {} + subnet_create_args: {} + runner: + type: "constant" + times: {{times}} + concurrency: {{concurrency}} + context: + quotas: + manila: + shares: -1 + gigabytes: -1 + nova: + instances: -1 + cores: -1 + ram: -1 + neutron: + network: -1 + port: -1 + router: -1 + subnet: -1 + floatingip: -1 + users: + tenants: 1 + users_per_tenant: 1 + sla: + max_avg_duration: {{ sla_max_avg_duration }} + max_seconds_per_iteration: {{ sla_max_seconds }} + failure_rate: + max: {{ sla_max_failure }}