Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions suse_ha-formula/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SUSE HA test suite

Due to its complexity, this formula employs a dedicated test setup allowing the various feature and configuration combinations to be individually examined.

All tests utilize Pytest, Testinfra and Vagrant to be available on the host system (usually your workstation or CI system).
30 changes: 30 additions & 0 deletions suse_ha-formula/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os
import pytest
pytest.register_assert_rewrite('helpers')
from helpers import modes, vagenv, _vagrant



@pytest.fixture(scope='session')
def save():
v = _vagrant()
v.env = vagenv()
v.snapshot_push()


@pytest.fixture()
def reset():
v = _vagrant()
v.env = vagenv()
v.snapshot_pop()
#v.destroy()
#v.up()
#ssh_config = v.ssh_config().replace('FATAL', 'VERBOSE')
#with open('.scullery_ssh', 'w') as fh:
# fh.write(ssh_config)


@pytest.fixture(params=modes())
def mode(request):
return request.param

87 changes: 87 additions & 0 deletions suse_ha-formula/tests/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import dotenv
import json
import os
import vagrant

env = os.environ.copy()

def modes():
# 'medium' removed -> FIXME results in error about fence_base being undefined ?
# 'large' removed -> FIXME handle error about no defined STONITH resources
# 'large_sbd' removed -> FIXME implement SBD simulation -> WIP
return ['small', 'large_ipmi', 'large_ipmi_custom', 'large_sbd']

def _vagrant():
return vagrant.Vagrant(quiet_stderr=False)

# https://stackoverflow.com/a/9808122
def find(key, value):
for k, v in value.items():
if k == key:
yield v
elif isinstance(v, dict):
for result in find(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in find(key, d):
yield result


def find_changes(result, count=False):
found = find('changes', result)
changed = False
counter = 0
for change in list(found):
if change:
changed = True
if count is False:
break
count += 1
if count is False:
return changed
return changed, counter


def setgrains(grains, host, target=None):
for grainpair in grains:
grain='test:{}'.format(grainpair[0])
value=str(grainpair[1])
if target is None:
setgrain = host.salt('grains.set', [grain, value, 'force=True'])
else:
host.run(f'salt --out=json --static {target} grains.set {grain} {value} force=True').stdout


def vagenv():
envmap = dotenv.dotenv_values('.scullery_env')
for variable, value in envmap.items():
env[variable] = value
return env



def bootstrap_sbd(host):
target='iqn.2003-01.org.linux-iscsi.scullery-master0.x8664:sn.5034edf18f27'
initiators={'scullery-master0': 'iqn.1996-04.de.suse:01:3d33457f6212', 'scullery-minion0': 'iqn.1996-04.de.suse:01:dc7732f79cb2', 'scullery-minion1': 'iqn.1996-04.de.suse:01:35bb829ac08'}
#with open('suse_ha-formula/tests/configs/target.json', 'r') as fh:
# config = fh.read()
#run_config = host.run("echo '{}' > /etc/target/saveconfig.json && echo '{}' > /etc/iscsi/initiatorname.iscsi && mkdir /data/lun".format(config, initiators['scullery-master0']))
#assert run_config.stdout == ''
run_start = host.run("rctarget start && rctarget status")
assert run_start.exit_status == 0
assert 'status=0/SUCCESS' in run_start.stdout
for client in ['scullery-minion0', 'scullery-minion1']:
run_client = host.run("sudo salt --out=json --static {} cmd.run 'echo {} > /etc/iscsi/initiatorname.iscsi'".format(client, initiators[client]))
print('run_client: '.format(str(run_client.stdout)))
run_login = host.run("sudo salt --out=json --static \* cmd.run 'iscsiadm -m node -T {} -p scullery-master0 --login'".format(target))
run_login_parsed = json.loads(run_login.stdout)
print('run_login: '.format(str(run_login_parsed)))
#assert run_login.stdout.startswith('Logging in to')
assert run_login.exit_status == 0
#assert run_login.stdout.endswith('successful.\n')
run_scan = host.run("sudo salt --out=json --static \* cmd.run 'rescan-scsi-bus.sh'")
run_scan_parsed = json.loads(run_scan.stdout)
print('run_scan: '.format(str(run_scan_parsed)))
assert run_scan.exit_status == 0

60 changes: 60 additions & 0 deletions suse_ha-formula/tests/pillars/init.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
mine_functions:
network.get_hostname: []

suse_ha:
cluster:
name: scullery
ip_version: ipv4
nodeid: {{ salt['grains.get']('id')[-1] | int + 1 }}
cluster_secret: !!binary |
LGljyn1fBRRcxLxFEgOmhILNTFY/13Cn3EwqqaBN6ynrX6flhiGyTjfW8eAQ1zlJex3uO9kssIcANw9uXLLpOCJ/Fvia3yzHNzCIxfW0zayUOBSMypN1TMKjad5/n8frAFZWNBhTcbk1Cwi764yBj8ErhsPh264qEreRzznJFGI=
# FIXME: test with IPv6
multicast:
address: 239.0.0.1
bind_address: {{ grains['ip4_interfaces']['eth0'][0] }}
resources_dir: /data/resources
{%- if salt['grains.get']('test:with_fencing') == true %}
fencing:
{%- if salt['grains.get']('test:with_stonith') == true %}
stonith_enable: true
{%- endif %}
{%- if salt['grains.get']('test:with_sbd') == true %}
sbd:
instances:
minion0:
pcmk_host_list: minion0
pcmk_delay_base: 0
minion1:
pcmk_host_list: minion1
pcmk_delay_base: 0
dynamic:
pcmk_delay_max: 5
devices:
- /dev/sda
- /dev/sdb
- /dev/sdc
{%- endif %}
{%- if salt['grains.get']('test:with_ipmi') == true %}
ipmi:
{%- if salt['grains.get']('test:with_ipmi_custom') == true %}
primitive:
operations:
start:
timeout: 30
{%- endif %}
hosts:
{%- for i in [0, 1] %}
dev-ipmi{{ i }}:
ip: 192.168.120.1
port: 6001{{ i }}
user: admin
interface: lanplus
priv: ADMINISTRATOR
secret: password
{%- endfor %}
{%- endif %}
{%- endif %}
sysconfig:
sbd:
# FIXME: implement hardware/software watchdog support in the formula + test with software watchdog
SBD_WATCHDOG_DEV: /dev/null
Loading