Skip to content

Commit 1d36dd3

Browse files
authored
Port tool from hardware-landscape to this repo (#1)
* restructure and refactor --------- Signed-off-by: Marc Schöchlin <[email protected]>
1 parent d23a5a2 commit 1d36dd3

File tree

20 files changed

+1490
-0
lines changed

20 files changed

+1490
-0
lines changed

.flake8

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
max-line-length = 140
3+
per-file-ignores = __init__.py:F401,F403

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
venv
2+
__pycache__

Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
SHELL = bash
2+
3+
activate = source venv/bin/activate
4+
python = python3
5+
6+
check:
7+
@# run sequentially so the output is easier to read
8+
${MAKE} --no-print-directory lint
9+
${MAKE} --no-print-directory type-check
10+
${MAKE} --no-print-directory test
11+
.PHONY: check
12+
13+
14+
venv/bin/activate: requirements.txt
15+
./openstack_workload_generator deps
16+
17+
deps: venv/bin/activate
18+
.PHONY: deps
19+
20+
lint: deps
21+
${activate} && ${python} -m flake8 src
22+
.PHONY: lint
23+
24+
type-check: deps
25+
${activate} && ${python} -m mypy --no-color-output --pretty src
26+
.PHONY: type-check
27+
28+
test: deps
29+
${activate} && ${python} -m pytest test
30+
.PHONY: test
31+

README.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,199 @@
11
# openstack-workload-generator
2+
3+
The openstack-workload-generator is a tool to generate test workloads on openstack clusters
4+
for the following purposes:
5+
6+
- test new clusters to ensure that basic functionalities are working
7+
- launch a certain workload for performance and reliability tests
8+
- create test setups for openstack tools to test with larger amounts of domains, projects and servers
9+
10+
# General Behavior
11+
12+
The tool uses the Openstack API or the Python Openstack SDK to automatically create and destroy resources in Openstack.
13+
14+
When creating, the specified resources (e.g. domains, projects, servers, ...) are created if they have not already
15+
been created. In this way, several creation processes can also be executed in a sequence to create a specific setup
16+
with certain variants of server properties. If provider network is defined the first host in the project gets a floati
17+
18+
The parameters that are used during an execution can be defined
19+
via a YAML file.
20+
21+
When deleting, the tool proceeds recursively, automatically identifying and deleting all contained resources.
22+
23+
In addition to the servers created, an Ansible inventory directory can also be created, which can be used as the
24+
basis for later automation.
25+
26+
# Usage
27+
28+
```
29+
```
30+
31+
# Testing Scenarios
32+
33+
## Example usage: A minimal scenario
34+
35+
* 1 domain with
36+
* one admin user
37+
* with 1 project
38+
* assigned roles
39+
* which then each contain 1 server
40+
* block storage volume
41+
* first server has a floating ip
42+
* one public SSH key
43+
* a network
44+
* a subnet
45+
* a router
46+
* a security group for ssh ingress access
47+
* a security group for egress access
48+
49+
### Example output of the creation process
50+
51+
```bash
52+
$ ./openstack_workload_generator --create_domains smoketest1 --create_projects smoketest-project1 --create_machines smoketest-testvm1
53+
2024-11-22 11:16:22 - INFO - helpers.py:69 - The effective configuration from /home/marc/src/github/osba/scs/openstack-workload-generator/src/openstack_workload_generator/entities/../../../profiles/default.yaml :
54+
>>>
55+
{ 'admin_domain_password': 'yolobanana',
56+
'admin_vm_password': 'yolobanana',
57+
'admin_vm_ssh_key': 'ssh-ed25519 '
58+
'AAAAC3NzaC1lZDI1NTE5AAAAIACLmNpHitBkZGVbWAFxZjUATNvLjSktAKwokFIQ9Z1k '
59+
60+
'admin_vm_ssh_keypair_name': 'my_ssh_public_key',
61+
'project_ipv4_subnet': '192.168.200.0/24',
62+
'vm_flavor': 'SCS-1L-1',
63+
'vm_image': 'Ubuntu 24.04',
64+
'vm_volume_size_gb': 10}
65+
<<<
66+
2024-11-22 11:16:22 - INFO - __main__.py:80 - Creating 1 domains, with 1 projects, with 1 machines in summary
67+
2024-11-22 11:16:23 - INFO - domain.py:51 - Created domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
68+
2024-11-22 11:16:24 - INFO - user.py:22 - Assigned role 'manager' to user 'smoketest1-admin' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
69+
2024-11-22 11:16:24 - INFO - user.py:37 - Created user smoketest1-admin / e8c1427ec25547dd9d8eab6a942b0805 with password yolobanana in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
70+
2024-11-22 11:16:25 - INFO - project.py:158 - Created project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
71+
2024-11-22 11:16:25 - INFO - project.py:136 - Compute quotas for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd' not changed
72+
2024-11-22 11:16:26 - INFO - project.py:136 - Volume quotas for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd' not changed
73+
2024-11-22 11:16:26 - INFO - project.py:136 - Network quotas for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd' not changed
74+
2024-11-22 11:16:26 - INFO - project.py:92 - Assigned manager to e8c1427ec25547dd9d8eab6a942b0805 for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
75+
2024-11-22 11:16:26 - INFO - project.py:92 - Assigned load-balancer_member to e8c1427ec25547dd9d8eab6a942b0805 for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
76+
2024-11-22 11:16:26 - INFO - project.py:92 - Assigned member to e8c1427ec25547dd9d8eab6a942b0805 for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
77+
2024-11-22 11:16:26 - INFO - project.py:49 - Establishing a connection for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
78+
2024-11-22 11:16:29 - INFO - network.py:116 - Created network localnet-smoketest-project1/a5e92142-9842-476e-8bd7-d19b10ddd603 in smoketest-project1/ed5d39e2b5084565991a8c537eae46ae
79+
2024-11-22 11:16:31 - INFO - network.py:133 - Created subnet localnet-smoketest-project1/5d9ebc28-87a2-4622-9882-7629fce8c93d in smoketest-project1/ed5d39e2b5084565991a8c537eae46ae
80+
2024-11-22 11:16:32 - INFO - network.py:97 - Router 'localrouter-smoketest-project1' created with ID: c90fb0af-54c9-42b3-94bc-c9fca9de1a0b
81+
2024-11-22 11:16:35 - INFO - network.py:101 - Router 'localrouter-smoketest-project1' gateway set to external network: public
82+
2024-11-22 11:16:43 - INFO - network.py:103 - Subnet 'localnet-smoketest-project1' added to router 'localrouter-smoketest-project1' as an interface
83+
2024-11-22 11:16:43 - INFO - network.py:180 - Creating ingress security group ingress-ssh-smoketest-project1 for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
84+
2024-11-22 11:16:44 - INFO - network.py:209 - Creating egress security group egress-any-smoketest-project1 for project smoketest-project1/4a6a49520d0848c9a1a8925b64742efd
85+
2024-11-22 11:16:46 - INFO - project.py:241 - Create SSH keypair 'my_ssh_public_key in project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
86+
2024-11-22 11:16:46 - INFO - project.py:248 - Closing connection for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
87+
2024-11-22 11:16:46 - INFO - project.py:49 - Establishing a connection for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
88+
2024-11-22 11:16:48 - INFO - helpers.py:32 - config does not contain : ROOT -> cloud_init_extra_script, using >>>#!/bin/bash
89+
echo "HELLO WORLD"; date > READY; whoami >> READY<<<
90+
2024-11-22 11:16:51 - INFO - machine.py:83 - Created server smoketest-testvm1/4196cd5f-b5e8-47cd-a496-6e63d268b506 in project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
91+
2024-11-22 11:16:51 - INFO - helpers.py:32 - config does not contain : ROOT -> public_network, using >>>public<<<
92+
2024-11-22 11:16:51 - INFO - machine.py:124 - Add floating ip smoketest-testvm1/4196cd5f-b5e8-47cd-a496-6e63d268b506 in project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
93+
2024-11-22 11:16:51 - INFO - helpers.py:32 - config does not contain : ROOT -> wait_for_server_timeout, using >>>300<<<
94+
2024-11-22 11:18:18 - INFO - project.py:248 - Closing connection for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
95+
2024-11-22 11:18:18 - INFO - __main__.py:101 - Execution finished after 1 minutes, item rate 0.6443141142527262/item
96+
```
97+
98+
### Example of the cleanup process
99+
```
100+
./openstack_workload_generator --delete_domains smoketest1
101+
2024-11-22 12:32:16 - WARNING - machine.py:48 - Deleting machine smoketest-testvm1 in project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
102+
2024-11-22 12:32:21 - WARNING - machine.py:53 - Machine smoketest-testvm1 in ed5d39e2b5084565991a8c537eae46ae is deleted now
103+
2024-11-22 12:32:25 - WARNING - network.py:146 - Removed interface from subnet: 5d9ebc28-87a2-4622-9882-7629fce8c93d
104+
2024-11-22 12:32:27 - WARNING - network.py:148 - Removed gateway from router c90fb0af-54c9-42b3-94bc-c9fca9de1a0b
105+
2024-11-22 12:32:27 - WARNING - network.py:150 - Deleted router c90fb0af-54c9-42b3-94bc-c9fca9de1a0b/localrouter-smoketest-project1
106+
2024-11-22 12:32:28 - WARNING - network.py:161 - Delete port 3168dba8-0735-47e5-84da-59f9d508b49a
107+
2024-11-22 12:32:29 - WARNING - network.py:167 - Delete subnet localnet-smoketest-project1 of project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
108+
2024-11-22 12:32:29 - WARNING - network.py:174 - Deleted network localnet-smoketest-project1 / a5e92142-9842-476e-8bd7-d19b10ddd603
109+
2024-11-22 12:32:29 - WARNING - project.py:183 - Cleanup of project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
110+
2024-11-22 12:32:29 - INFO - project.py:49 - Establishing a connection for project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
111+
2024-11-22 12:32:35 - WARNING - project.py:190 - Deleting project 'smoketest-project1/ed5d39e2b5084565991a8c537eae46ae' in domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
112+
2024-11-22 12:32:35 - WARNING - project.py:200 - Deleting security group: default (88ceab77-b2c7-4986-8463-a157fbafbcfc)
113+
2024-11-22 12:32:36 - WARNING - user.py:45 - Deleted user: smoketest1-admin / e8c1427ec25547dd9d8eab6a942b0805
114+
2024-11-22 12:32:36 - WARNING - domain.py:70 - Deleted domain 'smoketest1/4a6a49520d0848c9a1a8925b64742efd'
115+
```
116+
117+
## Example usage: A tiny scenario
118+
119+
* 2 domains with
120+
* one admin user
121+
* each with 2 projects
122+
* assigned roles
123+
* which then each contain 2 servers
124+
* block storage volume
125+
* first server has a floating ip
126+
* one public SSH key
127+
* a network
128+
* a subnet
129+
* a router
130+
* a security group for ssh ingress access
131+
* a security group for egress access
132+
133+
```
134+
./openstack_workload_generator \
135+
--create_domains smoketest{1..2} \
136+
--create_projects smoketest-project{1..2} \
137+
--create_machines smoketest-testvm{1..2}
138+
```
139+
140+
141+
## Example usage: A huge stresstest scenario
142+
143+
### Scenario Details
144+
145+
* 10 domains, with 6 projects each , with 9 machines each.
146+
* 9 domains
147+
* 45 projects
148+
* 540 virtual machines
149+
* 4GB RAM per machine, 2.1TB RAM in total
150+
* 10GB Disk per machine, 5.5TB DISK in total
151+
* [The configuration profile](profiles/stresstest.yaml)
152+
* Downloads a [shellscript](http://10.10.23.254:28080/stresstest.sh) from a server which is reachable by all virtual machines
153+
* Executes the script in a screen session
154+
* Prevents to execute multiple scripts in parallel by checking if there is already a screen named "execute"
155+
156+
### Testing procedure
157+
158+
1. Move stresstestfile out of the way at the central server
159+
```
160+
ssh scs-manager1
161+
mv /srv/www/stresstest.sh /srv/www/stresstest.sh.disabled
162+
```
163+
2. Test the scenario creation
164+
```
165+
./openstack_workload_generator \
166+
--config stresstest.yaml \
167+
--create_domains stresstest1 \
168+
--create_projects stresstest-project1 \
169+
--create_machines stresstestvm1
170+
```
171+
3. Create the full scenario
172+
```
173+
./openstack_workload_generator \
174+
--config stresstest.yaml \
175+
--create_domains stresstest{1..10} \
176+
--create_projects stresstest-project{1..6} \
177+
--create_machines stresstestvm{1..9} \
178+
--ansible_inventory /tmp/stresstest-inventory
179+
```
180+
4. Check the created scenario
181+
```
182+
openstack domain list
183+
openstack project list --long
184+
openstack server list --all-projects --long
185+
```
186+
5. Activate the stresstestfile
187+
```
188+
ssh scs-manager1
189+
cat <<EOF
190+
#!/bin/bash
191+
stress-ng --vm 8 --vm-bytes 80% -t 1h
192+
EOF
193+
mv /srv/www/stresstest.sh.disabled /srv/www/stresstest.sh
194+
```
195+
6. Purge the scenario
196+
```
197+
./openstack_workload_generator --delete_domains stresstest{1..10}
198+
```
199+

mypy.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[mypy]
2+
3+
[mypy-coloredlogs.*]
4+
ignore_missing_imports = True

openstack_workload_generator

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
3+
rundir="$(dirname $(readlink -f $0))/"
4+
cd "$rundir" || exit 1
5+
6+
modification_time(){
7+
python3 -c "import os; print(int(os.path.getmtime('$1')))"
8+
}
9+
10+
create_env(){
11+
set -e
12+
rm -rf "${rundir}/venv"
13+
python3 -m venv "${rundir}/venv"
14+
source "${rundir}/venv/bin/activate"
15+
pip install -r "${rundir}/requirements.txt"
16+
touch -r "${rundir}/requirements.txt" "${rundir}/venv/bin/activate"
17+
set +e
18+
}
19+
20+
21+
if ! [ -d "${rundir}/venv" ] ;then
22+
echo "Creating venv: ${rundir}/venv" >&2
23+
echo
24+
create_env
25+
elif [[ "$(modification_time "${rundir}/requirements.txt")" -gt "$(modification_time "${rundir}/venv/bin/activate")" ]];then
26+
echo "Recreating venv: ${rundir}/venv" >&2
27+
echo
28+
create_env
29+
else
30+
source "${rundir}/venv/bin/activate"
31+
fi
32+
33+
34+
if [ "$1" = "deps" ];then
35+
exit 0
36+
fi
37+
cd "$rundir" || exit 1
38+
source venv/bin/activate
39+
exec python3 $rundir/src/openstack_workload_generator/__main__.py "$@"

profiles/default.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
admin_domain_password: "yolobanana"
3+
admin_vm_ssh_keypair_name: "my_ssh_public_key"
4+
admin_vm_ssh_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIACLmNpHitBkZGVbWAFxZjUATNvLjSktAKwokFIQ9Z1k [email protected]"
5+
admin_vm_password: "yolobanana"
6+
vm_flavor: "SCS-1L-1"
7+
vm_image: "Ubuntu 24.04"
8+
vm_volume_size_gb: 10
9+
project_ipv4_subnet: "192.168.200.0/24"

profiles/smoketest.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
admin_domain_password: "yolobanana"
3+
admin_vm_ssh_key: |
4+
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIACLmNpHitBkZGVbWAFxZjUATNvLjSktAKwokFIQ9Z1k [email protected]
5+
admin_vm_password: "yolobanana"
6+
vm_flavor: "SCS-2V-4"
7+
vm_image: "Ubuntu 24.04"
8+
vm_volume_size_gb: 10
9+
project_ipv4_subnet: "192.168.200.0/24"
10+
compute_quotas:
11+
cores: 64
12+
instances: 30
13+
ram: 512000
14+
cloud_init_extra_script: |
15+
#!/bin/bash
16+
pwd
17+
touch SMOKETEST
18+
env > SMOKETEST-env

profiles/stresstest.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
admin_domain_password: "yolobanana"
3+
admin_vm_ssh_key: |
4+
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIACLmNpHitBkZGVbWAFxZjUATNvLjSktAKwokFIQ9Z1k [email protected]
5+
admin_vm_password: "yolobanana"
6+
vm_flavor: "SCS-2V-4"
7+
vm_image: "Ubuntu 24.04"
8+
vm_volume_size_gb: 10
9+
project_ipv4_subnet: "192.168.200.0/24"
10+
compute_quotas:
11+
cores: 1000
12+
instances: 200
13+
ram: 512000
14+
block_storage_quotas:
15+
volumes: 100
16+
gigabytes: 5000
17+
network_quotas:
18+
security_groups: 50
19+
cloud_init_extra_script: |
20+
#!/bin/bash
21+
set -x
22+
apt-get update
23+
apt-get install stress-ng iperf flowgrind fio screen -y
24+
echo '*/1 * * * * root screen -ls execute || (curl -f -o "/tmp/execute.sh" http://10.10.23.254:28080/stresstest.sh; screen -S execute -d -m bash -c "bash /tmp/execute.sh 2>&1|tee /root/execute.log")' > /etc/cron.d/execute-stresstest

requirements.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
requests==2.32.2
2+
cachetools==5.3.2
3+
requests==2.32.2
4+
coloredlogs==15.0.1
5+
setuptools==70.0.0
6+
Jinja2==3.1.4
7+
PyYAML==6.0.1
8+
types-pyyaml
9+
openstacksdk==3.3.0
10+
pytest==7.4.0
11+
mypy==1.4.1
12+
flake8==6.1.0

0 commit comments

Comments
 (0)