Commit 49cebcc4 authored by Rémi Duraffort's avatar Rémi Duraffort

acquire: patch the device-typeon the fly

On some lab, the local device-type is not matching the official lava
device-type. Add a way to change the device-type on the fly so lavafed record
the official device-type.
Signed-off-by: Rémi Duraffort's avatarRémi Duraffort <remi.duraffort@linaro.org>
parent 88aab1b2
Pipeline #4387 passed with stages
in 3 minutes and 21 seconds
......@@ -28,3 +28,5 @@ devices:
patches:
- from: "telnet localhost"
to: "telnet dispatcher01"
- name: <device_03>
device-type: official-device-type
......@@ -216,7 +216,9 @@ class Command(LAVAFedCommand):
device_name, None, None, None, None, "MAINTENANCE", None
)
# Record the device health
dt, _ = DeviceType.objects.get_or_create(name=data["device_type"])
# Patch the device-type if needed
dt_name = device.get("device-type", data["device_type"])
dt, _ = DeviceType.objects.get_or_create(name=dt_name)
device, _ = Device.objects.get_or_create(
name=device_name, dt=dt, lab=lab
)
......
......@@ -57,6 +57,7 @@ def lab_schema():
{
Required("name"): str,
Optional("patches"): [{Required("from"): str, Required("to"): str}],
Optional("device-type"): str,
}
],
}
......
......@@ -104,6 +104,8 @@ certificates:
devices:
- name: device-01
- name: device-02
- name: device-03
device-type: dt-lava-03
"""
tmpdir.mkdir("labs")
(tmpdir / "labs").mkdir("lava.test")
......
......@@ -27,7 +27,7 @@ from django.core.management import call_command
import pytest
from lavafed import constants, utils
from lavafed.models import Job
from lavafed.models import Device, DeviceType, Job
@pytest.mark.django_db
......@@ -38,11 +38,15 @@ def test_acquire(caplog, monkeypatch, setup, tmpdir):
# This should be tested in another test
def fake_copy_device(device, master, lab, devices_cfg, log):
assert device.name == "device-01" # nosec - pytest
assert device.dt.name == "dt-01" # nosec - pytest
assert device.name in ["device-01", "device-03"] # nosec - pytest
if device.name == "device-01":
assert device.dt.name == "dt-01" # nosec - pytest
if device.name == "device-03":
assert device.dt.name == "dt-lava-03" # nosec - pytest
assert devices_cfg == [ # nosec - pytest
{"name": "device-01"},
{"name": "device-02"},
{"name": "device-03", "device-type": "dt-lava-03"},
]
monkeypatch.setattr(utils, "copy_device", fake_copy_device)
......@@ -50,9 +54,11 @@ def test_acquire(caplog, monkeypatch, setup, tmpdir):
# This should be tested in another test
def fake_wait_for_devices(proxy, log, devices, b):
assert b is False # nosec - pytest
assert len(devices) == 1 # nosec - pytest
assert len(devices) == 2 # nosec - pytest
assert devices[0].name == "device-01" # nosec - pytest
yield devices[0]
assert devices[1].name == "device-03" # nosec - pytest
yield devices[1]
monkeypatch.setattr(utils, "wait_for_devices", fake_wait_for_devices)
monkeypatch.setattr(
......@@ -123,6 +129,24 @@ def test_acquire(caplog, monkeypatch, setup, tmpdir):
),
"ret": None,
},
{
"request": "scheduler.devices.show",
"args": ("device-03@lava.test",),
"ret": {"health": "Maintenance"},
},
{
"request": "scheduler.devices.update",
"args": (
"device-03@lava.test",
None,
None,
None,
None,
"UNKNOWN",
None,
),
"ret": None,
},
],
)
monkeypatch.setattr(
......@@ -172,6 +196,16 @@ def test_acquire(caplog, monkeypatch, setup, tmpdir):
"args": ("device-02",),
"ret": {"health": "Maintenance"},
},
{
"request": "scheduler.devices.show",
"args": ("device-03",),
"ret": {"health": "Unknown", "device_type": "dt-03"},
},
{
"request": "scheduler.devices.update",
"args": ("device-03", None, None, None, None, "MAINTENANCE", None),
"ret": None,
},
],
)
call_command("acquire", "lava.test", "--config", tmpdir)
......@@ -190,14 +224,18 @@ def test_acquire(caplog, monkeypatch, setup, tmpdir):
("lavafed", 20, "- device-01"),
("lavafed", 20, "- device-02"),
("lavafed", 30, "--> health is not good, skip (Maintenance)"),
("lavafed", 20, "- device-03"),
("lavafed", 20, "[master] add in maintenance:"),
("lavafed", 20, "- device-01"),
("lavafed", 20, "- device-03"),
("lavafed", 20, "[master] submit:"),
("lavafed", 20, "- device-01"),
("lavafed", 20, "--> hc.jinja2 (qemu - health-check)"),
("lavafed", 10, "---> 42"),
("lavafed", 20, "- device-03"),
("lavafed", 20, "[lab] waiting for jobs to end:"),
("lavafed", 20, "--> [master] acquire 'device-01@lava.test'"),
("lavafed", 20, "--> [master] acquire 'device-03@lava.test'"),
]
assert Job.objects.count() == 2 # nosec - pytest
......@@ -218,6 +256,20 @@ def test_acquire(caplog, monkeypatch, setup, tmpdir):
assert j2.lava == 42 # nosec - pytest
assert j2.url == "" # nosec - pytest
assert Device.objects.count() == 3
(d1, d2, d3) = Device.objects.all()
assert d1.name == "lava-slave"
assert d2.name == "device-01"
assert d2.dt.name == "dt-01"
assert d2.lab.name == "lava.test"
assert d2.acquired
assert d2.health == Device.HEALTH_GOOD
assert d3.name == "device-03"
assert d3.dt.name == "dt-lava-03"
assert d3.lab.name == "lava.test"
assert d3.acquired
assert d3.health == Device.HEALTH_UNKNOWN
@pytest.mark.django_db
def test_acquire_missing_master_cfg(caplog, monkeypatch, setup, tmpdir):
......
......@@ -304,6 +304,98 @@ def test_copy_device(caplog, monkeypatch):
]
@pytest.mark.django_db
def test_copy_device_device_type(caplog, monkeypatch):
monkeypatch.setattr(xmlrpc.client, "ServerProxy", RecordingProxyFactory())
caplog.set_level(logging.DEBUG)
monkeypatch.setattr(
xmlrpc.client.ServerProxy,
"master",
[
{"request": "scheduler.device_types.list", "args": (), "ret": []},
{
"request": "scheduler.device_types.add",
"args": ("real-device-type", "", True, False, 24, "hours"),
"ret": None,
},
{"request": "scheduler.devices.list", "args": (), "ret": []},
{
"request": "scheduler.devices.add",
"args": (
"device-02@lab.test",
"real-device-type",
"lab.test",
None,
None,
True,
"MAINTENANCE",
None,
),
"ret": [],
},
{
"request": "scheduler.devices.tags.add",
"args": ("device-02@lab.test", "lab.test"),
"ret": [],
},
{
"request": "scheduler.devices.set_dictionary",
"args": (
"device-02@lab.test",
"{% extends 'dt-01.jinja2' %}\n{% set power_on = \"telnet localhost 7501\" %}",
),
"ret": [],
},
],
)
monkeypatch.setattr(
xmlrpc.client.ServerProxy,
"lab",
[
{
"request": "scheduler.devices.show",
"args": ("device-02",),
"ret": {"health": "Good", "device_type": "dt-01"},
},
{
"request": "scheduler.devices.get_dictionary",
"args": ("device-02", False),
"ret": "{% extends 'dt-01.jinja2' %}\n{% set power_on = \"telnet localhost 7501\" %}",
},
],
)
lab = Lab.objects.create(name="lab.test", url="http://lab.test.org")
dt = DeviceType.objects.create(name="dt-01")
device = Device.objects.create(name="device-02", dt=dt, lab=lab, acquired=False)
lab_proxy = build_proxy(
{
"url": "https://lava.test/RPC2",
"username": "lava_lab_user",
"token": "lava_lab_token",
}
)
master_proxy = build_proxy(
{
"url": "https://federation.lavasoftware.org/lava/RPC2/",
"username": "lava_master_user",
"token": "lava_master_token",
}
)
devices_cfg = [
{"name": "device-01"},
{"name": "device-02", "device-type": "real-device-type"},
]
copy_device(device, master_proxy, lab_proxy, devices_cfg, logging.getLogger())
assert xmlrpc.client.ServerProxy.master == [] # nosec - pytest
assert xmlrpc.client.ServerProxy.lab == [] # nosec - pytest
assert caplog.record_tuples == [ # nosec - pytest
("root", 10, "--> create device-type 'real-device-type'"),
("root", 10, "--> add device as 'device-02@lab.test'"),
("root", 10, "--> add tag 'lab.test'"),
("root", 10, "--> update device dict"),
]
@pytest.mark.django_db
def test_copy_device_patch(caplog, monkeypatch):
monkeypatch.setattr(xmlrpc.client, "ServerProxy", RecordingProxyFactory())
......
......@@ -210,9 +210,13 @@ def copy_device(device, master, lab, devices_config, logger):
device_config = lab.scheduler.devices.show(device.name)
device_dict = str(lab.scheduler.devices.get_dictionary(device.name, False))
d_name = device.master_name()
device_cfg = get_device_config(devices_config, device.name)
# Check that the device-type exist
dt = device_config["device_type"]
# If "device-type" is specified in the device config use it and defaults to
# the name coming from the api.
dt = device_cfg.get("device-type", device_config["device_type"])
if dt not in [d["name"] for d in master.scheduler.device_types.list()]:
logger.debug("--> create device-type '%s'", dt)
master.scheduler.device_types.add(dt, "", True, False, 24, "hours")
......@@ -227,10 +231,9 @@ def copy_device(device, master, lab, devices_config, logger):
)
logger.debug("--> add tag '%s'", device.lab.name)
master.scheduler.devices.tags.add(d_name, device.lab.name)
logger.debug("--> update device dict")
logger.debug("--> update device dict")
# Patch device dict if needed
device_cfg = get_device_config(devices_config, device.name)
for patch in device_cfg.get("patches", []):
device_dict = device_dict.replace(patch["from"], patch["to"])
master.scheduler.devices.set_dictionary(d_name, device_dict)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment