Skip to content

Commit

Permalink
Refactor hardware agents to separate file
Browse files Browse the repository at this point in the history
Signed-off-by: Joonas Rautiola <joonas.rautiola@unikie.com>
  • Loading branch information
joinemm committed Oct 23, 2024
1 parent 5edb0c5 commit b830c30
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 338 deletions.
149 changes: 149 additions & 0 deletions hosts/agents-common.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# SPDX-FileCopyrightText: 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0

{ pkgs, inputs, ... }:
let
# Vendored in, as brainstem isn't suitable for nixpkgs packaging upstream:
# https://github.com/NixOS/nixpkgs/pull/313643
brainstem = pkgs.callPackage ../pkgs/brainstem { };
in
{
services.udev.packages = [
brainstem
pkgs.usbsdmux
];

environment.systemPackages =
[
inputs.robot-framework.packages.${pkgs.system}.ghaf-robot
brainstem
]
++ (with pkgs; [
minicom
usbsdmux
]);

# The Jenkins slave service is very barebones
# it only installs java and sets up jenkins user
services.jenkinsSlave.enable = true;

# Jenkins needs sudo and serial rights to perform the HW tests
users.users.jenkins.extraGroups = [
"wheel"
"dialout"
"tty"
];

systemd.services =
let
# verifies that the environment file is properly configured
# and downloads agent.jar from the controller
jenkins-setup-script = pkgs.writeShellScript "jenkins-setup.sh" ''
if [[ ! -f jenkins.env ]]; then
install -m 600 /dev/null jenkins.env
echo "CONTROLLER=" > jenkins.env
echo "ADMIN_PASSWORD=" >> jenkins.env
echo "Please add jenkins controller details to $(pwd)/jenkins.env"
exit 1
fi
source jenkins.env
if [[ -z "$CONTROLLER" ]]; then
echo "Variable CONTROLLER not set in $(pwd)/jenkins.env"
exit 1
fi
if [[ -z "$ADMIN_PASSWORD" ]]; then
echo "Variable ADMIN_PASSWORD not set in $(pwd)/jenkins.env"
exit 1
fi
wget -N "$CONTROLLER/jnlpJars/agent.jar"
'';

# Helper function to create agent services for each hardware device
mkAgent =
device:
let
# opens a websocket connection to the jenkins controller from this agent
jenkins-connect-script = pkgs.writeShellScript "jenkins-connect.sh" ''
JENKINS_SECRET="$(
curl -L -s -u admin:$ADMIN_PASSWORD \
$CONTROLLER/computer/${device}/jenkins-agent.jnlp |
sed "s/.*<application-desc><argument>\([a-z0-9]*\).*/\1\n/"
)"
mkdir -p "/var/lib/jenkins/agents/${device}"
${pkgs.jdk}/bin/java \
-jar agent.jar \
-url "$CONTROLLER" \
-name "${device}" \
-secret "$JENKINS_SECRET" \
-workDir "/var/lib/jenkins/agents/${device}" \
-webSocket
'';
in
{
# agents require the setup service to run without errors before starting
requires = [ "setup-agents.service" ];
wantedBy = [ "setup-agents.service" ];
after = [ "setup-agents.service" ];

path =
[
brainstem
inputs.robot-framework.packages.${pkgs.system}.ghaf-robot
]
++ (with pkgs; [
curl
wget
jdk
git
bashInteractive
coreutils
util-linux
nix
zstd
jq
csvkit
sudo
openssh
iputils
netcat
python3
usbsdmux
]);

serviceConfig = {
Type = "simple";
User = "jenkins";
EnvironmentFile = "/var/lib/jenkins/jenkins.env";
WorkingDirectory = "/var/lib/jenkins";
ExecStart = "${jenkins-connect-script}";
};
};
in
{
# the setup service does not start automatically or it would fail activation
# of the system since jenkins.env is empty before manually set up
setup-agents = {
path = with pkgs; [ wget ];
serviceConfig = {
Type = "oneshot";
User = "jenkins";
RemainAfterExit = "yes";
WorkingDirectory = "/var/lib/jenkins";
ExecStart = "${jenkins-setup-script}";
};
};

# one agent per unique hardware device to act as a lock
agent-orin-agx = mkAgent "orin-agx";
agent-orin-nx = mkAgent "orin-nx";
agent-riscv = mkAgent "riscv";
agent-nuc = mkAgent "nuc";
agent-lenovo-x1 = mkAgent "lenovo-x1";
};
}
160 changes: 7 additions & 153 deletions hosts/testagent-dev/configuration.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
{
self,
inputs,
pkgs,
config,
...
}:
let
# Vendored in, as brainstem isn't suitable for nixpkgs packaging upstream:
# https://github.com/NixOS/nixpkgs/pull/313643
brainstem = pkgs.callPackage ../../pkgs/brainstem { };
in
{
imports =
[
./disk-config.nix
../agents-common.nix
inputs.sops-nix.nixosModules.sops
inputs.disko.nixosModules.disko
]
Expand Down Expand Up @@ -66,153 +61,12 @@ in
cpu.intel.updateMicrocode = true;
};

services.udev = {
# Enable Acroname USB Smart switch, as well as LXA USB-SD-Mux support.
packages = [
brainstem
pkgs.usbsdmux
];

# udev rules for test devices serial connections
extraRules = ''
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTD0W9KS", SYMLINK+="ttyORINNX1", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTD0WF8Y", SYMLINK+="ttyNUC1", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea71", ATTRS{serial}=="04A629B8AB87AB8111ECB2A38815028", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="ttyRISCV1", MODE="0666", GROUP="dialout"
'';
};

environment.systemPackages =
[
inputs.robot-framework.packages.${pkgs.system}.ghaf-robot
brainstem
]
++ (with pkgs; [
minicom
usbsdmux
]);

# The Jenkins slave service is very barebones
# it only installs java and sets up jenkins user
services.jenkinsSlave.enable = true;

# Jenkins needs sudo and serial rights to perform the HW tests
users.users.jenkins.extraGroups = [
"wheel"
"dialout"
"tty"
];

systemd.services =
let
# verifies that the environment file is properly configured
# and downloads agent.jar from the controller
jenkins-setup-script = pkgs.writeShellScript "jenkins-setup.sh" ''
if [[ ! -f jenkins.env ]]; then
echo "Please add jenkins controller details to $(pwd)/jenkins.env"
echo "CONTROLLER=" > jenkins.env
echo "ADMIN_PASSWORD=" >> jenkins.env
exit 1
fi
source jenkins.env
if [[ -z "$CONTROLLER" ]]; then
echo "Variable CONTROLLER not set in $(pwd)/jenkins.env"
exit 1
fi
if [[ -z "$ADMIN_PASSWORD" ]]; then
echo "Variable ADMIN_PASSWORD not set in $(pwd)/jenkins.env"
exit 1
fi
wget "$CONTROLLER/jnlpJars/agent.jar"
'';

# Helper function to create agent services for each hardware device
mkAgent =
device:
let
# opens a websocket connection to the jenkins controller from this agent
jenkins-connect-script = pkgs.writeShellScript "jenkins-connect.sh" ''
JENKINS_SECRET="$(
curl -L -s -u admin:$ADMIN_PASSWORD \
$CONTROLLER/computer/${device}/jenkins-agent.jnlp |
sed "s/.*<application-desc><argument>\([a-z0-9]*\).*/\1\n/"
)"
mkdir -p "/var/lib/jenkins/agents/${device}"
${pkgs.jdk}/bin/java \
-jar agent.jar \
-url "$CONTROLLER" \
-name "${device}" \
-secret "$JENKINS_SECRET" \
-workDir "/var/lib/jenkins/agents/${device}" \
-webSocket
'';
in
{
# agents require the setup service to run without errors before starting
requires = [ "setup-agents.service" ];
wantedBy = [ "setup-agents.service" ];
after = [ "setup-agents.service" ];

path =
[
brainstem
inputs.robot-framework.packages.${pkgs.system}.ghaf-robot
]
++ (with pkgs; [
curl
wget
jdk
git
bashInteractive
coreutils
util-linux
nix
zstd
jq
csvkit
sudo
openssh
iputils
netcat
python3
usbsdmux
]);

serviceConfig = {
Type = "simple";
User = "jenkins";
EnvironmentFile = "/var/lib/jenkins/jenkins.env";
WorkingDirectory = "/var/lib/jenkins";
ExecStart = "${jenkins-connect-script}";
};
};
in
{
# the setup service does not start automatically or it would fail activation
# of the system since jenkins.env is empty before manually set up
setup-agents = {
path = with pkgs; [ wget ];
serviceConfig = {
Type = "oneshot";
User = "jenkins";
RemainAfterExit = "yes";
WorkingDirectory = "/var/lib/jenkins";
ExecStart = "${jenkins-setup-script}";
};
};

# one agent per unique hardware device to act as a lock
agent-orin-agx = mkAgent "orin-agx";
agent-orin-nx = mkAgent "orin-nx";
agent-riscv = mkAgent "riscv";
agent-nuc = mkAgent "nuc";
agent-lenovo-x1 = mkAgent "lenovo-x1";
};
# udev rules for test devices serial connections
services.udev.extraRules = ''
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTD0W9KS", SYMLINK+="ttyORINNX1", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTD0WF8Y", SYMLINK+="ttyNUC1", MODE="0666", GROUP="dialout"
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea71", ATTRS{serial}=="04A629B8AB87AB8111ECB2A38815028", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="ttyRISCV1", MODE="0666", GROUP="dialout"
'';

# Details of the hardware devices connected to this host
environment.etc."jenkins/test_config.json".text =
Expand Down
Loading

0 comments on commit b830c30

Please sign in to comment.