Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

testutils/iotlab.py: Randomize the selected node #298

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
37 changes: 34 additions & 3 deletions testutils/iotlab.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import random
import re

from iotlabcli.auth import get_user_credentials
Expand All @@ -9,6 +10,7 @@
stop_experiment,
get_experiment,
exp_resources,
info_experiment,
AliasNodes,
)

Expand Down Expand Up @@ -151,6 +153,25 @@ def _wait(self):
ret = wait_experiment(Api(*self.user_credentials()), self.exp_id)
return ret

def _select_random_node(self, site, board):
api = Api(*self.user_credentials())
info = info_experiment(api, site=site)
choices = []
for iot_lab_nodes in info.values():
if not isinstance(iot_lab_nodes, list):
continue
for iot_lab_node in iot_lab_nodes:
if iot_lab_node.get("state", "") != "Alive":
continue
net_addr = iot_lab_node.get("network_address", "")
if board not in net_addr:
continue
choices.append(net_addr)
if not choices:
raise RuntimeError(f"No {board} found at {site}")
ret = random.choice(choices)
return ret

def _submit(self, site, duration):
"""Submit an experiment with required nodes"""
api = Api(*self.user_credentials())
Expand All @@ -159,9 +180,19 @@ def _submit(self, site, duration):
if ctrl.env.get('IOTLAB_NODE') is not None:
resources.append(exp_resources([ctrl.env.get('IOTLAB_NODE')]))
elif ctrl.board() is not None:
board = IoTLABExperiment._archi_from_board(ctrl.board())
alias = AliasNodes(1, site, board)
resources.append(exp_resources(alias))
# Since we cannot combine alias and phyical nodes in the same
# experiment and but we would prefer to use iotlab-m3 alias
# nodes because the m3 nodes can report that they are broken.
# Let's take the easiest solution and only use alias nodes
# if they are all iotlab-m3 nodes.
if all(ctrl.board() == 'iotlab-m3' for ctrl in self.ctrls):
board = IoTLABExperiment._archi_from_board(ctrl.board())
alias = AliasNodes(1, site, board)
resources.append(exp_resources(alias))
else:
board = IoTLABExperiment.BOARD_ARCHI_MAP[ctrl.board()]['name']
net_addr = self._select_random_node(site, board)
resources.append(exp_resources([net_addr]))
else:
raise ValueError("neither BOARD or IOTLAB_NODE are set")
return submit_experiment(api, self.name, duration, resources)['id']
Expand Down
13 changes: 13 additions & 0 deletions testutils/tests/test_iotlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def test_stop(monkeypatch, exp_id, expected):
"ctrl_envs, exp_nodes",
[
([{"BOARD": "nrf52dk"}], ["nrf52dk-5.saclay.iot-lab.info"]),
([{"BOARD": "iotlab-m3"}], ["m3-3.saclay.iot-lab.info"]),
(
[{"IOTLAB_NODE": "samr21-21.saclay.iot-lab.info"}],
["samr21-21.saclay.iot-lab.info"],
Expand All @@ -199,6 +200,18 @@ def test_start(monkeypatch, ctrl_envs, exp_nodes):
monkeypatch.setattr(
testutils.iotlab, "get_experiment", lambda api, exp_id: {"nodes": exp_nodes}
)
monkeypatch.setattr(
testutils.iotlab,
"info_experiment",
lambda api, site: {
"items": [
{
"state": "Alive",
"network_address": exp_nodes[0],
},
],
},
)
monkeypatch.setattr(testutils.iotlab, "wait_experiment", lambda api, exp_id: {})
ctrls = [MockRIOTCtrl(env) for env in ctrl_envs]
exp = testutils.iotlab.IoTLABExperiment("test", ctrls)
Expand Down
Loading