Crucible network workload

Added a new workload in browbeat, where in it uses Crucible to run
benchmarks. This workload uses Crucible remote endpoint against
Openstack VMs.

Change-Id: If374ed803fe57f04acaa4c64ae037516eb6f4fa9
This commit is contained in:
rajeshP524 2024-01-04 11:30:24 +05:30
parent 0024927764
commit 1e85bfc730
9 changed files with 749 additions and 0 deletions

View File

@ -909,3 +909,33 @@ workloads:
sample: 1
ansible_forks: 5
file: rally/rally-plugins/pbench-fio/pbench-fio.yml
- name: Network
enabled: false
type: rally
rally_deployment: overcloud
concurrency:
- 1
times: 1
scenarios:
- name: crucible-uperf
enabled: true
image_name: rhel9
flavor_name: m1.small
num_provider_networks: 10
cidr_prefix: "192.18"
provider_phys_net: "datacentre"
server_client_pairs_per_network: 5
# do not append '/' at the end for dir_path
crucible_repo_dir_path: /home/stack/crucible_repos
# crucible controller info
hostname_or_ip:
user: root
password:
ext_iface: eno4
# crucible run params
client_userenv: "stream8"
tags: "browbeat:browbeat"
profile_path: "mv_params.json"
num_samples: 3
file: rally/rally-plugins/workloads/crucible-uperf.yml

View File

@ -0,0 +1,240 @@
# 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.common import consts
from rally_openstack.task.scenarios.nova import utils as nova_utils
from rally_openstack.task.scenarios.neutron import utils as neutron_utils
from rally.task import scenario
from rally.task import types
from rally.task import validation
from rally.common import logging
import concurrent.futures
import threading
import os
from jinja2 import Environment
from jinja2 import FileSystemLoader
import paramiko
import time
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")
@validation.add("required_services", services=[consts.Service.NEUTRON, consts.Service.NOVA])
@validation.add("required_platform", platform="openstack", users=True)
@validation.add("required_contexts", contexts=("crucible_provider_networks"))
@scenario.configure(context={"cleanup@openstack": ["neutron", "nova"],"keypair@openstack": {}},
name="BrowbeatPlugin.crucible_uperf",
platform="openstack")
class CrucibleUperf(nova_utils.NovaScenario, neutron_utils.NeutronScenario):
def __init__(self, *args, **kwargs):
super(CrucibleUperf, self).__init__(*args, **kwargs)
# Create a lock for the dictionary
self.dictionary_lock = threading.Lock()
self.server_client_info_dict = {}
def deploy_vms_per_network(self, image, flavor, provider_network,
server_client_pairs_per_network):
try:
kwargs = {}
kwargs["nics"] = [{"net-id": provider_network["id"]}]
kwargs["key_name"] = self.context["user"]["keypair"]["name"]
for i in range(server_client_pairs_per_network):
server = self._boot_server(image, flavor, **kwargs)
client = self._boot_server(image, flavor, **kwargs)
# Update server and client names
server_name = provider_network["name"] + '_server_' + str(i + 1)
client_name = provider_network["name"] + '_client_' + str(i + 1)
# Acquire lock before updating the dictionary
with self.dictionary_lock:
self.server_client_info_dict[server_name] = (
list(server.addresses.values())[0][0]['addr'])
self.server_client_info_dict[client_name] = (
list(client.addresses.values())[0][0]['addr'])
except Exception as e:
print(f"Error in deploy_vms_per_network: {e}")
def generate_entry_strings(self, N, perN):
inventory_str = "[instances]\n"
name_ip_mappings_str = ""
endpoint_str = ""
for i in range(1, N + 1):
for j in range(1, perN + 1):
server_name = f"provider_{i}_server_{j}"
client_name = f"provider_{i}_client_{j}"
inventory_str += (
f"{self.server_client_info_dict[server_name]} "
f"ansible_user=cloud-user ansible_private_key_file=/root/browbeat_pkey\n"
)
inventory_str += (
f"{self.server_client_info_dict[client_name]} "
f"ansible_user=cloud-user ansible_private_key_file=/root/browbeat_pkey\n"
)
name_ip_mappings_str += \
f"{server_name}=\"{self.server_client_info_dict[server_name]}\"\n"
name_ip_mappings_str += \
f"{client_name}=\"{self.server_client_info_dict[client_name]}\"\n"
index = (i - 1) * perN + j
endpoint_str += (
f" --endpoint remotehost,user:root,host:${client_name},"
f"client:{index}-{index},userenv:${{client_userenv}} \\\n"
)
endpoint_str += (
f" --endpoint remotehost,user:root,host:${server_name},"
f"server:{index}-{index},userenv:${{client_userenv}} \\\n"
)
endpoint_str = endpoint_str.rstrip('\n').rstrip('\\')
return inventory_str, name_ip_mappings_str, endpoint_str
def render_template(self, env, template, client_userenv, tags, profile, num_samples,
name_ip_mappings_str, endpoint_str, output_file_path):
rendered_template = template.render(
client_userenv=client_userenv,
tags=tags,
profile=profile,
num_samples=num_samples,
name_ip_mappings_str=name_ip_mappings_str,
endpoint_str=endpoint_str
)
with open(output_file_path, 'w') as file:
file.write(rendered_template)
def run_bootstrap(self, host, username, password):
try:
with paramiko.SSHClient() as ssh:
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password)
# set permissions on pkey before ansible uses that file
ssh.exec_command("/usr/bin/chmod 0600 /root/browbeat_pkey")
cmd = "/usr/bin/ansible-playbook -i browbeat_ansible_inventory.ini -f 16 " \
"-vvv /root/browbeat_bootstrap.yaml &> /root/browbeat_bootstrap.log"
_, stdout, stderr = ssh.exec_command(cmd)
# Check the exit status of the command
if stdout.channel.recv_exit_status() == 0:
LOG.info(f"Bootstrap playbook on {host} executed successfully.")
return True
else:
raise Exception(
f"Ansible execution failed on {host}. Error: {stderr.read().decode()}"
)
except Exception as e:
raise Exception(f"Error in run_bootstrap: {e}")
def run_crucible_uperf(self, host, username, password):
try:
with paramiko.SSHClient() as ssh:
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password)
ssh.exec_command("/usr/bin/chmod 777 /root/browbeat_uperf_script.sh")
cmd = "/root/browbeat_uperf_script.sh &> /root/browbeat_uperf_script.log"
_, stdout, stderr = ssh.exec_command(cmd)
# Check the exit status of the command
if stdout.channel.recv_exit_status() == 0:
LOG.info(f"Crucible uperf script on {host} executed successfully.")
return True
else:
raise Exception(
f"Crucible uperf execution failed on {host}."
f" Error: {stderr.read().decode()}"
)
except Exception as e:
raise Exception(f"Error in run_crucible_uperf: {e}")
def copy_crucible_results(self, hostname_or_ip, user, password, crucible_result_dir):
cmd = (
f"sshpass -p '{password}' scp -r {user}@{hostname_or_ip}:/var/lib/crucible/run/latest/"
f" {crucible_result_dir}/"
)
os.system(cmd)
def run(self, image, flavor, server_client_pairs_per_network, hostname_or_ip, user, password,
num_provider_networks, client_userenv, tags, profile, num_samples,
crucible_repo_dir_path, **kwargs):
provider_networks = self.context["provider_networks"]
with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
network_futures = [
executor.submit(
self.deploy_vms_per_network, image, flavor, provider_network,
server_client_pairs_per_network
)
for provider_network in provider_networks
]
concurrent.futures.wait(network_futures)
for instance_name, ip_address in self.server_client_info_dict.items():
print(f"{instance_name}: {ip_address}")
pkey = self.context["user"]["keypair"]["private"]
with open("./rally/rally-plugins/workloads/crucible/browbeat_pkey", 'w') as file:
file.write(pkey)
# prepare ansible inventory and uperf script entry strings
inventory_str, name_ip_mappings_str, endpoint_str = \
self.generate_entry_strings(num_provider_networks, server_client_pairs_per_network)
with open(
"./rally/rally-plugins/workloads/crucible/browbeat_ansible_inventory.ini", 'w'
) as file:
file.write(inventory_str)
# prepare the script
env = Environment(loader=FileSystemLoader(os.getcwd()))
template_path = './rally/rally-plugins/workloads/crucible/templates/uperf_script.sh.j2'
template = env.get_template(template_path)
self.output_file_path = './rally/rally-plugins/workloads/crucible/browbeat_uperf_script.sh'
self.render_template(env, template, client_userenv, tags, profile, num_samples,
name_ip_mappings_str, endpoint_str, self.output_file_path)
# copy over scp
scp_commands = [
f"sshpass -p '{password}' scp ./rally/rally-plugins/workloads/crucible/browbeat* "
f"{user}@{hostname_or_ip}:/root/",
f"sshpass -p '{password}' scp ./rally/rally-plugins/workloads/crucible/mv_params.json "
f"{user}@{hostname_or_ip}:/root/",
f"sshpass -p '{password}' scp ./rally/rally-plugins/workloads/crucible/ansible/"
f"browbeat* {user}@{hostname_or_ip}:/root/"
]
# Execute scp commands
for scp_command in scp_commands:
os.system(scp_command)
# copy repos to crucible controller over ssh
repo_names = os.listdir(crucible_repo_dir_path)
for repo_name in repo_names:
repo = crucible_repo_dir_path + "/" + repo_name
scp_command = (
f"sshpass -p '{password}' scp {repo} {user}@{hostname_or_ip}:/root/"
)
os.system(scp_command)
time.sleep(60)
self.run_bootstrap(hostname_or_ip, user, password)
self.run_crucible_uperf(hostname_or_ip, user, password)
# copy results
with open('../rally_result_dir_path') as f:
rally_result_dir_path = f.readline()
crucible_result_dir = rally_result_dir_path + "/crucible/results"
os.makedirs(crucible_result_dir)
self.copy_crucible_results(hostname_or_ip, user, password, crucible_result_dir)

View File

@ -0,0 +1,59 @@
{% 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 %}
{% set nova_api_version = nova_api_version or 2.74 %}
---
BrowbeatPlugin.crucible_uperf:
-
args:
flavor:
name: '{{ flavor_name }}'
image:
name: '{{ image_name }}'
num_provider_networks: {{ num_provider_networks }}
server_client_pairs_per_network: {{ server_client_pairs_per_network }}
hostname_or_ip: "{{ hostname_or_ip }}"
user: "{{ user }}"
password: "{{ password }}"
ext_iface: "{{ ext_iface }}"
client_userenv: "{{ client_userenv }}"
tags: "{{ tags }}"
profile: "{{ profile_path }}"
num_samples: {{ num_samples }}
crucible_repo_dir_path: "{{ crucible_repo_dir_path }}"
metadata:
test_metadata: "true"
runner:
concurrency: {{ concurrency }}
times: {{ times }}
type: 'constant'
context:
users:
tenants: 1
users_per_tenant: 8
api_versions:
nova:
version: {{ nova_api_version }}
quotas:
neutron:
network: -1
port: -1
router: -1
subnet: -1
nova:
instances: -1
cores: -1
ram: -1
crucible_provider_networks:
hostname_or_ip: "{{ hostname_or_ip }}"
user: "{{ user }}"
password: "{{ password }}"
ext_iface: "{{ ext_iface }}"
num_provider_networks: {{ num_provider_networks }}
cidr_prefix: "{{ cidr_prefix }}"
provider_phys_net: "{{ provider_phys_net }}"
sla:
max_avg_duration: {{sla_max_avg_duration}}
max_seconds_per_iteration: {{sla_max_seconds}}
failure_rate:
max: {{sla_max_failure}}

View File

@ -0,0 +1,62 @@
Browbeat-Crucible Network Workload
===================================
Introduction
------------
This document provides instructions for running the Browbeat-Crucible Network workload, which is designed to test network performance using Crucible remotehost endpoint.
Prerequisites
-------------
Before running the workload, ensure the following prerequisites are met:
1. **Crucible Controller Setup**: Set up a Crucible controller on a bare metal host by following the instructions provided in the repository: `crucible <https://github.com/perftool-incubator/crucible>`_. This involves cloning the repository and executing the installation script which is a zero touch installation.
2. **Masquerade Rule Configuration**: Enable masquerade rule on the host using the following commands:
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -o $(sudo ip r | grep default | awk '{print $5}') -j MASQUERADE
3. **Paramiko Installation**: Install Paramiko version 3.2.0 within the Rally virtual environment. Incorrect Paramiko versions may lead to SSH issues with VMs. Activate the virtual environment and install Paramiko as follows:
cd browbeat
source .rally-venv/bin/activate
pip3 uninstall paramiko
pip3 install paramiko==3.2.0
deactivate
4. **Image Setup**: Download a RHEL qcow2 image and upload it to Glance. Ensure necessary rhel repos are copied to the directory ``/home/stack/crucible_repos``.
Running the Workload
---------------------
Follow these steps to run the Browbeat-Crucible Network workload:
1. Edit ``browbeat-config.yaml`` to enable the Network workload and configure parameters according to your requirements. Adjust the parameters under the ``Network`` section, such as ``num_provider_networks``, ``cidr_prefix``, ``server_client_pairs_per_network``, ``hostname_or_ip``, ``user``, ``password``, ``crucible_repo_dir_path``, and ``ext_iface``.
2. If you have a custom traffic profile, copy it to the directory ``~/browbeat/rally/rally-plugins/workloads/crucible`` as ``mv_params.json``.
3. Execute the workload
./browbeat.py rally
Parameters
-----------
- **num_provider_networks**: Number of provider networks to be created for VM attachment.
- **cidr_prefix**: CIDR prefix used for the provider networks.
- **server_client_pairs_per_network**: Number of server and client pairs created per network.
- **hostname_or_ip**: Crucible controller hostname or IP address.
- **user**: Username for Crucible controller (root required).
- **password**: Root password for Crucible controller.
- **crucible_repo_dir_path**: Path to the directory containing ``.repo`` files specific to the image.
- **ext_iface**: External interface of Crucible controller with connectivity to provider networks.
Adjust these parameters according to your specific requirements.

View File

@ -0,0 +1,27 @@
---
- hosts: instances
gather_facts: false
remote_user: cloud-user
become: true
vars:
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
tasks:
- name: copy dns server
copy:
src: /etc/resolv.conf
dest: /etc/resolv.conf
mode: 0644
- name: Copy .repo files
copy:
src: "{{ item }}"
dest: /etc/yum.repos.d/
mode: 0644
with_fileglob:
- /root/*.repo
- name: copy .ssh dir to root
ansible.builtin.shell: cp -r /home/cloud-user/.ssh/ /root/ && chmod -R 0600 /root/.ssh/
- name: install podman and wget
ansible.builtin.shell: yum install wget -y && yum install podman -y

View File

@ -0,0 +1,22 @@
{
"global-options": [
{
"name": "common-params",
"params": [
{ "arg": "duration", "vals": ["60"] },
{ "arg": "protocol", "vals": ["udp"] },
{ "arg": "nthreads", "vals": ["1"] },
{ "arg": "ifname", "vals": ["eth0"], "role": "server" }
]
}
],
"sets": [
{
"include": "common-params",
"params": [
{ "arg": "test-type", "vals": ["stream","rr"] },
{ "arg": "wsize", "vals": ["64"] }
]
}
]
}

View File

@ -0,0 +1,16 @@
#!/bin/bash
{{ name_ip_mappings_str }}
client_userenv="{{ client_userenv }}"
tags="{{ tags }}"
profile="{{ profile }}"
num_samples={{ num_samples }}
time crucible run uperf \
--test-order r \
--mv-params $profile \
--tags "${tags}" \
--num-samples $num_samples \
--max-sample-failures 1 \
{{ endpoint_str }}

View File

@ -0,0 +1,54 @@
#!/bin/bash
# Check if script is run as root
if [ "$EUID" -ne 0 ]; then
echo "Please run as root (with sudo)."
exit 1
fi
# Check if action is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 [create|delete]"
exit 1
fi
action=$1 # First command-line argument
# Set variables
ext_iface="{{ ext_iface }}"
vlan_base_id=1
num_vlans={{ num_vlans }}
cidr_prefix="{{ cidr_prefix }}"
if [ "$action" == "create" ]; then
# Create VLAN interfaces
ip link set dev $ext_iface up
for ((i=0; i<$num_vlans; i++)); do
vlan_id=$((vlan_base_id + i))
vlan_interface="${ext_iface}.${vlan_id}"
ip link add link $ext_iface name $vlan_interface type vlan id $vlan_id
ip link set dev $vlan_interface up
external_gateway="${cidr_prefix}.$((vlan_base_id + i)).1/24"
ip addr add $external_gateway dev $vlan_interface
echo "VLAN $vlan_id configuration completed successfully."
done
echo "All configurations completed successfully."
elif [ "$action" == "delete" ]; then
# Delete VLAN interfaces
for ((i=0; i<$num_vlans; i++)); do
vlan_id=$((vlan_base_id + i))
vlan_interface="${ext_iface}.${vlan_id}"
ip link set dev $vlan_interface down
ip link delete $vlan_interface
echo "VLAN $vlan_id removed successfully."
done
echo "Cleanup completed successfully."
else
echo "Invalid action. Please provide 'create' or 'delete' as the argument."
exit 1
fi

View File

@ -0,0 +1,239 @@
# 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.task import context
from rally.common import logging
from rally.common import utils
from rally import consts
from rally_openstack.common import osclients
from rally_openstack.common.wrappers import network as network_wrapper
import os
from jinja2 import Environment
from jinja2 import FileSystemLoader
import paramiko
LOG = logging.getLogger(__name__)
@context.configure(name="crucible_provider_networks", order=1000)
class CreateExternalNetworksContext(context.Context):
"""This plugin creates provider networks with specified option."""
CONFIG_SCHEMA = {
"type": "object",
"$schema": consts.JSON_SCHEMA,
"additionalProperties": False,
"properties": {
"cidr_prefix": {
"type": "string",
},
"num_provider_networks": {
"type": "integer",
"minimum": 0
},
"provider_phys_net": {
"type": "string"
},
"hostname_or_ip": {
"type": "string"
},
"user": {
"type": "string"
},
"password": {
"type": "string"
},
"ext_iface": {
"type": "string"
}
}
}
def _create_subnet(self, tenant_id, network_id, network_number):
"""Create subnet for provider network
:param tenant_id: ID of tenant
:param network_id: ID of provider network
:param network_number: int, number for CIDR of subnet
:returns: subnet object
"""
subnet_args = {
"subnet": {
"tenant_id": tenant_id,
"network_id": network_id,
"name": self.net_wrapper.owner.generate_random_name(),
"ip_version": 4,
"cidr": "{}.{}.0/24".format(self.cidr_prefix, network_number),
"enable_dhcp": True,
"gateway_ip": "{}.{}.1".format(self.cidr_prefix, network_number),
"allocation_pools": [{"start": "{}.{}.2".format(self.cidr_prefix, network_number),
"end": "{}.{}.254".format(
self.cidr_prefix, network_number)}]
}
}
return self.net_wrapper.client.create_subnet(subnet_args)["subnet"]
def get_neutron_client(self):
return osclients.Clients(self.context["admin"]["credential"]).neutron()
def run_ssh_script(self, host, username, password, script_path , action):
try:
with paramiko.SSHClient() as ssh:
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password)
_, stdout, stderr = ssh.exec_command(f"bash {script_path} {action}")
# Check the exit status of the command
if stdout.channel.recv_exit_status() == 0:
LOG.info(f"Script on {host} executed successfully.")
return True
else:
raise Exception(
f"Script execution failed on {host}. Error: {stderr.read().decode()}"
)
except Exception as e:
raise Exception(f"Error in run_ssh_script: {e}")
def render_template(self, env, template, ext_iface, num_vlans, cidr_prefix,
output_file_path):
rendered_template = template.render(
ext_iface=ext_iface,
num_vlans=num_vlans,
cidr_prefix=cidr_prefix
)
with open(output_file_path, 'w') as file:
file.write(rendered_template)
def setup(self):
"""This method is called before the task starts."""
self.net_wrapper = network_wrapper.wrap(
osclients.Clients(self.context["admin"]["credential"]),
self,
config=self.config,
)
self.context["provider_networks"] = []
self.context["provider_subnets"] = {}
self.num_provider_networks = self.config.get("num_provider_networks", 16)
self.cidr_prefix = self.config.get("cidr_prefix", "192.18")
self.hostname_or_ip = self.config.get("hostname_or_ip", "hostname.example.com")
self.user = self.config.get("user", "root")
self.password = self.config.get("password", "passwd")
self.ext_iface = self.config.get("ext_iface", "ens2f1np1")
num_provider_networks_created = 0
while num_provider_networks_created < self.num_provider_networks:
has_error_occured = False
for user, tenant_id in utils.iterate_per_tenants(
self.context.get("users", [])
):
try:
kwargs = {
"network_create_args": {
"provider:network_type": "vlan",
"provider:physical_network": self.config.get("provider_phys_net",
"datacentre"),
"provider:segmentation_id": num_provider_networks_created + 1,
"router:external": False,
"port_security_enabled": False
}
}
self.context["provider_networks"].append(
self.net_wrapper.create_network(tenant_id, **kwargs)
)
LOG.debug(
"Provider network with id '%s' created as part of context"
% self.context["provider_networks"][-1]["id"]
)
# update network name
updated_name = 'provider_' + str(num_provider_networks_created + 1)
cmd = f"source /home/stack/overcloudrc && openstack network set --name " \
f"{updated_name} {self.context['provider_networks'][-1]['id']}"
os.system(cmd)
self.context["provider_networks"][-1]["name"] = updated_name
num_provider_networks_created += 1
except Exception as e:
msg = "Can't create provider network {} as part of context: {}".format(
num_provider_networks_created, e
)
LOG.exception(msg)
has_error_occured = True
break
try:
subnet = self._create_subnet(tenant_id,
self.context["provider_networks"][-1]["id"],
num_provider_networks_created)
self.context["provider_subnets"][
self.context["provider_networks"][-1]["id"]] = subnet
LOG.debug(
"provider subnet with id '%s' created as part of context"
% subnet["id"]
)
except Exception as e:
msg = "Can't create provider subnet {} as part of context: {}".format(
num_provider_networks_created, e
)
LOG.exception(msg)
has_error_occured = True
break
if has_error_occured:
break
# prepare the script
env = Environment(loader=FileSystemLoader(os.getcwd()))
template_path = './rally/rally-plugins/workloads/crucible/templates/vlans.sh.j2'
template = env.get_template(template_path)
self.output_file_path = './rally/rally-plugins/workloads/crucible/browbeat_vlans.sh'
self.render_template(env, template, self.ext_iface, self.num_provider_networks,
self.cidr_prefix, self.output_file_path)
# copy over scp
scp_command = (
f"sshpass -p '{self.password}' scp {self.output_file_path} "
f"{self.user}@{self.hostname_or_ip}:/root/"
)
os.system(scp_command)
# create vlan interfaces
self.run_ssh_script(self.hostname_or_ip, self.user, self.password,
"/root/browbeat_vlans.sh", "create")
def cleanup(self):
"""This method is called after the task finishes."""
for i in range(self.num_provider_networks):
try:
provider_net = self.context["provider_networks"][i]
provider_net_id = provider_net["id"]
provider_subnet = self.context["provider_subnets"][provider_net_id]
provider_subnet_id = provider_subnet["id"]
self.net_wrapper._delete_subnet(provider_subnet_id)
LOG.debug(
"Provider subnet with id '%s' deleted from context"
% provider_subnet_id
)
self.net_wrapper.delete_network(provider_net)
LOG.debug(
"Provider network with id '%s' deleted from context"
% provider_net_id
)
except Exception as e:
msg = "Can't delete provider network {} from context: {}".format(
provider_net_id, e
)
LOG.warning(msg)
# delete vlan interfaces
self.run_ssh_script(self.hostname_or_ip, self.user, self.password,
"/root/browbeat_vlans.sh", "delete")