Skip to content

Commit ccfd657

Browse files
more work around new model name and version abstraction
1 parent 47a3aea commit ccfd657

File tree

8 files changed

+227
-17
lines changed

8 files changed

+227
-17
lines changed

pioreactor/background_jobs/dosing_automation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ def __init__(
253253
"It's recommended to have stirring on to improve mixing during dosing events."
254254
)
255255

256-
if self.max_volume_ml > self.MAX_VIAL_VOLUME_TO_STOP:
257-
# possibly the user messed up thier configuration. We warn them.
256+
if self.max_volume_ml >= self.MAX_VIAL_VOLUME_TO_STOP:
257+
# possibly the user messed up their configuration. We warn them.
258258
self.logger.warning(
259259
"The parameter max_volume_ml should be less than max_volume_to_stop (otherwise your pumping will stop too soon)."
260260
)

pioreactor/cluster_management/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ def get_active_workers_in_experiment(experiment: str) -> tuple[str, ...]:
4444
@click.command(name="add", short_help="add a pioreactor worker")
4545
@click.argument("hostname")
4646
@click.option("--password", "-p", default="raspberry")
47-
@click.option("--version", "-v", default="1.1")
48-
@click.option("--model", "-m", default="pioreactor_20ml")
47+
@click.option("--model-version", "-v", default="1.1")
48+
@click.option("--model-name", "-m", default="pioreactor_20ml")
4949
@click.option("--address", "-a")
50-
def add_worker(hostname: str, password: str, version: str, model: str, address: str | None) -> None:
50+
def add_worker(
51+
hostname: str, password: str, model_version: str, model_name: str, address: str | None
52+
) -> None:
5153
"""
5254
Add a new pioreactor worker to the cluster. The pioreactor should already have the worker image installed and is turned on.
5355
"""
@@ -89,8 +91,6 @@ def add_worker(hostname: str, password: str, version: str, model: str, address:
8991
"/usr/local/bin/add_new_pioreactor_worker_from_leader.sh",
9092
hostname,
9193
password,
92-
version,
93-
model,
9494
possible_address,
9595
],
9696
capture_output=True,
@@ -103,7 +103,7 @@ def add_worker(hostname: str, password: str, version: str, model: str, address:
103103
try:
104104
r = put_into_leader(
105105
"/api/workers",
106-
json={"pioreactor_unit": hostname},
106+
json={"pioreactor_unit": hostname, "model_name": model_name, "model_version": model_version},
107107
)
108108
r.raise_for_status()
109109
except HTTPErrorStatus:

pioreactor/whoami.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,24 +154,44 @@ def am_I_a_worker() -> bool:
154154

155155
@cache
156156
def get_pioreactor_version() -> tuple[int, int]:
157-
if os.environ.get("PIO_VERSION"):
157+
if os.environ.get("MODEL_VERSION"):
158158
return version_text_to_tuple(os.environ["PIO_VERSION"])
159159

160-
from pioreactor.config import config
160+
from pioreactor.pubsub import get_from_leader
161161

162-
return version_text_to_tuple(config.get("pioreactor", "version", fallback="1.0")) # type: ignore
162+
try:
163+
result = get_from_leader(f"/api/workers/{get_unit_name()}")
164+
result.raise_for_status()
165+
data = result.json()
166+
return data["model_version"]
167+
except mureq.HTTPErrorStatus as e:
168+
if e.status_code == 404:
169+
raise NoWorkerFoundError(f"Worker {get_unit_name()} is not present in leader's inventory")
170+
else:
171+
raise e
172+
except mureq.HTTPException as e:
173+
raise e
163174

164175

165176
@cache
166177
def get_pioreactor_model() -> str | None:
167-
from pioreactor.config import config
178+
if os.environ.get("MODEL_NAME"):
179+
return os.environ["MODEL_NAME"]
168180

169-
maybe_model = config.get("pioreactor", "model", fallback=None)
170-
if maybe_model:
171-
return maybe_model
181+
from pioreactor.pubsub import get_from_leader
172182

173-
else:
174-
return None
183+
try:
184+
result = get_from_leader(f"/api/workers/{get_unit_name()}")
185+
result.raise_for_status()
186+
data = result.json()
187+
return data["model_name"]
188+
except mureq.HTTPErrorStatus as e:
189+
if e.status_code == 404:
190+
raise NoWorkerFoundError(f"Worker {get_unit_name()} is not present in leader's inventory")
191+
else:
192+
raise e
193+
except mureq.HTTPException as e:
194+
raise e
175195

176196

177197
@cache
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/bin/bash
2+
# this script "connects" the leader to the worker.
3+
# first argument is the name of the new/hostname pioreactor worker
4+
# second optional argument is the worker password, default "raspberry"
5+
# third optional argument is the address of the new Pioreactor, default "<hostname>.local"
6+
7+
set -x
8+
set -e
9+
export LC_ALL=C
10+
11+
HOSTNAME=$1
12+
SSHPASS=${2:-raspberry}
13+
ADDRESS=${3:-"$HOSTNAME".local}
14+
15+
USERNAME=pioreactor
16+
17+
LEADER_ADDRESS=$(crudini --get /home/$USERNAME/.pioreactor/config.ini cluster.topology leader_address)
18+
19+
20+
# remove from known_hosts if already present
21+
ssh-keygen -R "$ADDRESS" >/dev/null 2>&1
22+
ssh-keygen -R "$HOSTNAME" >/dev/null 2>&1
23+
ssh-keygen -R "$(getent hosts "$ADDRESS" | cut -d' ' -f1)" >/dev/null 2>&1
24+
25+
26+
# allow us to SSH in, but make sure we can first before continuing.
27+
# check we have .pioreactor folder to confirm the device has the pioreactor image
28+
N=120
29+
counter=0
30+
31+
while ! sshpass -p "$SSHPASS" ssh "$USERNAME"@"$ADDRESS" "test -d /home/$USERNAME/.pioreactor && echo 'exists'"
32+
do
33+
echo "Connection to $ADDRESS missed - $(date)"
34+
35+
if sshpass -v -p "$SSHPASS" ssh "$USERNAME"@"$ADDRESS" |& grep "Wrong password"; then
36+
echo "Wrong password provided."
37+
fi
38+
39+
counter=$((counter + 1))
40+
41+
if [ "$counter" -eq "$N" ]; then
42+
echo "Attempted to connect $N times, but failed. Exiting."
43+
exit 1
44+
fi
45+
46+
sleep 1
47+
done
48+
49+
50+
# Verify exact hostname match
51+
ACTUAL_HOSTNAME=$(sshpass -p "$SSHPASS" ssh "$USERNAME"@"$ADDRESS" "hostname")
52+
if [ "$ACTUAL_HOSTNAME" != "$HOSTNAME" ]; then
53+
echo "Hostname mismatch: expected '$HOSTNAME', but got '$ACTUAL_HOSTNAME'. Exiting."
54+
exit 1
55+
fi
56+
57+
# copy public key over
58+
sshpass -p "$SSHPASS" ssh-copy-id "$USERNAME"@"$ADDRESS"
59+
60+
# remove any existing config (for idempotent)
61+
# we do this first so the user can see it on the Pioreactors/ page
62+
UNIT_CONFIG=/home/$USERNAME/.pioreactor/config_"$HOSTNAME".ini
63+
64+
rm -f "$UNIT_CONFIG"
65+
touch "$UNIT_CONFIG"
66+
echo -e "# Any settings here are specific to $HOSTNAME, and override the settings in shared config.ini" >> "$UNIT_CONFIG"
67+
68+
# add worker's address to config
69+
CONFIG=/home/$USERNAME/.pioreactor/config.ini
70+
crudini --set "$CONFIG" cluster.addresses "$HOSTNAME" "$ADDRESS"
71+
72+
# add worker to known hosts on leader
73+
ssh-keyscan "$ADDRESS" >> "/home/$USERNAME/.ssh/known_hosts"
74+
75+
76+
# sync-configs
77+
pios sync-configs --units "$HOSTNAME" --skip-save
78+
sleep 1
79+
80+
# check we have config.ini file to confirm the device has the necessary configuration
81+
N=120
82+
counter=0
83+
84+
while ! sshpass -p "$SSHPASS" ssh "$USERNAME"@"$ADDRESS" "test -f /home/$USERNAME/.pioreactor/config.ini && echo 'exists'"
85+
do
86+
echo "Looking for config.ini - $(date)"
87+
88+
counter=$((counter + 1))
89+
90+
if [ "$counter" -eq "$N" ]; then
91+
echo "Attempted to find config.ini $N times, but failed. Exiting."
92+
exit 1
93+
fi
94+
95+
sleep 1
96+
done
97+
98+
# sync date & times, specifically for LAP see https://github.com/Pioreactor/pioreactor/issues/269
99+
ssh "$USERNAME"@"$ADDRESS" "sudo date --set \"$(date)\" && sudo fake-hwclock save"
100+
ssh "$USERNAME"@"$ADDRESS" "echo \"server $LEADER_ADDRESS iburst prefer\" | sudo tee -a /etc/chrony/chrony.conf || :"
101+
102+
103+
# reboot to set configuration
104+
# the || true is because the connection fails, which returns as -1.
105+
ssh "$USERNAME"@"$ADDRESS" 'sudo reboot;' || true
106+
107+
exit 0
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
3+
set -xeu
4+
5+
6+
export LC_ALL=C
7+
8+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
LEADER_HOSTNAME=$(crudini --get /home/pioreactor/.pioreactor/config.ini cluster.topology leader_hostname)
10+
11+
# if leader
12+
if [ "$HOSTNAME" = "$LEADER_HOSTNAME" ]; then
13+
14+
DB_PATH=$(crudini --get /home/pioreactor/.pioreactor/config.ini storage database)
15+
CONFIG_DIR="/home/pioreactor/.pioreactor"
16+
17+
# Loop through config files in the directory
18+
for config_file in "$CONFIG_DIR"/config_*.ini; do
19+
if [[ -f "$config_file" ]]; then
20+
pioreactor_unit=$(basename "$config_file" | sed 's/config_\(.*\)\.ini/\1/')
21+
model_name=$(crudini --get "$config_file" pioreactor model 2>/dev/null)
22+
model_version=$(crudini --get "$config_file" pioreactor version 2>/dev/null)
23+
24+
if [[ -n "$model_name" && -n "$model_version" ]]; then
25+
sqlite3 "$DB_PATH" <<EOF
26+
UPDATE workers SET
27+
model_name = '$model_name',
28+
model_version = '$model_version'
29+
WHERE pioreactor_unit = '$pioreactor_unit';
30+
EOF
31+
echo "Updated: $pioreactor_unit ($model_name, $model_version)"
32+
crudini --del "$config_file" pioreactor
33+
else
34+
echo "Skipping $config_file: Missing model or version"
35+
fi
36+
fi
37+
done
38+
sudo -u pioreactor pios sync-configs || :
39+
fi
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
3+
set -xeu
4+
5+
6+
export LC_ALL=C
7+
8+
# Lower bound version
9+
min_version="25.3.5"
10+
11+
# Get the current version of pio
12+
current_version=$(sudo -u pioreactor pio version)
13+
14+
# Use sorting to determine if the current version is less than the minimum version
15+
is_valid=$(printf "%s\n%s" "$current_version" "$min_version" | sort -V | head -n1)
16+
17+
# If the smallest version isn't the minimum version, then current version is too low
18+
if [ "$is_valid" != "$min_version" ]; then
19+
sudo -u pioreactor pio log -l ERROR -m "Version error: installed version $current_version is lower than the minimum required version $min_version."
20+
exit 1
21+
fi
22+
23+
echo "Version check passed: $current_version"

update_scripts/upcoming/update.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
set -xeu
4+
5+
6+
export LC_ALL=C
7+
8+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
LEADER_HOSTNAME=$(crudini --get /home/pioreactor/.pioreactor/config.ini cluster.topology leader_hostname)
10+
11+
# if leader
12+
if [ "$HOSTNAME" = "$LEADER_HOSTNAME" ]; then
13+
14+
# new add_worker script
15+
ADD_WORKER_FILE="/usr/local/bin/add_new_pioreactor_worker_from_leader.sh"
16+
sudo cp "$SCRIPT_DIR"/add_new_pioreactor_worker_from_leader.sh $ADD_WORKER_FILE
17+
echo "Added new add_new_pioreactor_worker_from_leader.sh."
18+
19+
fi

update_scripts/upcoming/update.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE workers ADD COLUMN model_version TEXT;
2+
ALTER TABLE workers ADD COLUMN model_name TEXT;

0 commit comments

Comments
 (0)