underpost 2.8.79 → 2.8.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ghpkg.yml +22 -20
- package/.github/workflows/npmpkg.yml +15 -10
- package/.github/workflows/pwa-microservices-template.page.yml +12 -3
- package/.github/workflows/pwa-microservices-template.test.yml +20 -17
- package/.vscode/extensions.json +2 -3
- package/.vscode/settings.json +2 -42
- package/Dockerfile +14 -33
- package/README.md +43 -25
- package/bin/db.js +1 -0
- package/bin/deploy.js +104 -797
- package/bin/file.js +18 -1
- package/bin/vs.js +18 -3
- package/cli.md +367 -207
- package/conf.js +4 -0
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +167 -0
- package/manifests/deployment/dd-template-development/proxy.yaml +46 -0
- package/manifests/deployment/tensorflow/tf-gpu-test.yaml +65 -0
- package/manifests/lxd/lxd-admin-profile.yaml +1 -0
- package/manifests/lxd/lxd-preseed.yaml +9 -37
- package/manifests/lxd/underpost-setup.sh +98 -81
- package/manifests/maas/device-scan.sh +43 -0
- package/manifests/maas/gpu-diag.sh +19 -0
- package/manifests/maas/lxd-preseed.yaml +32 -0
- package/manifests/maas/maas-setup.sh +120 -0
- package/manifests/maas/nat-iptables.sh +26 -0
- package/manifests/maas/snap-clean.sh +26 -0
- package/manifests/mariadb/statefulset.yaml +2 -1
- package/manifests/mariadb/storage-class.yaml +10 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +2 -2
- package/manifests/valkey/service.yaml +3 -9
- package/manifests/valkey/statefulset.yaml +10 -12
- package/package.json +1 -1
- package/src/cli/baremetal.js +1280 -0
- package/src/cli/cloud-init.js +537 -0
- package/src/cli/cluster.js +506 -243
- package/src/cli/deploy.js +41 -3
- package/src/cli/env.js +2 -2
- package/src/cli/image.js +57 -9
- package/src/cli/index.js +271 -232
- package/src/cli/lxd.js +314 -81
- package/src/cli/repository.js +7 -4
- package/src/cli/run.js +262 -0
- package/src/cli/test.js +1 -1
- package/src/index.js +28 -1
- package/src/runtime/lampp/Dockerfile +41 -47
- package/src/server/conf.js +61 -0
- package/src/server/logger.js +3 -3
- package/src/server/process.js +16 -19
- package/src/server/runtime.js +1 -6
- package/src/server/ssl.js +1 -12
- package/src/server/valkey.js +3 -3
- package/supervisord-openssh-server.conf +0 -5
package/bin/deploy.js
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
setUpProxyMaintenanceServer,
|
|
28
28
|
writeEnv,
|
|
29
29
|
getUnderpostRootPath,
|
|
30
|
+
buildCliDoc,
|
|
30
31
|
} from '../src/server/conf.js';
|
|
31
32
|
import { buildClient } from '../src/server/client-build.js';
|
|
32
33
|
import { range, s4, setPad, timer, uniqueArray } from '../src/client/components/core/CommonJs.js';
|
|
@@ -37,10 +38,10 @@ import { JSONweb } from '../src/server/client-formatted.js';
|
|
|
37
38
|
|
|
38
39
|
import { Xampp } from '../src/runtime/xampp/Xampp.js';
|
|
39
40
|
import { ejs } from '../src/server/json-schema.js';
|
|
40
|
-
import { buildCliDoc } from '../src/cli/index.js';
|
|
41
41
|
import { getLocalIPv4Address, ip } from '../src/server/dns.js';
|
|
42
42
|
import { Downloader } from '../src/server/downloader.js';
|
|
43
43
|
import colors from 'colors';
|
|
44
|
+
import { program } from '../src/cli/index.js';
|
|
44
45
|
|
|
45
46
|
colors.enable();
|
|
46
47
|
|
|
@@ -50,82 +51,6 @@ logger.info('argv', process.argv);
|
|
|
50
51
|
|
|
51
52
|
const [exe, dir, operator] = process.argv;
|
|
52
53
|
|
|
53
|
-
const updateVirtualRoot = async ({ nfsHostPath, IP_ADDRESS, ipaddr }) => {
|
|
54
|
-
const steps = [
|
|
55
|
-
`apt update`,
|
|
56
|
-
`ln -sf /lib/systemd/systemd /sbin/init`,
|
|
57
|
-
// `sudo apt install linux-modules-extra-6.8.0-31-generic`,
|
|
58
|
-
`apt install -y sudo`,
|
|
59
|
-
`apt install -y ntp`,
|
|
60
|
-
`apt install -y openssh-server`,
|
|
61
|
-
`apt install -y iptables`,
|
|
62
|
-
`update-alternatives --set iptables /usr/sbin/iptables-legacy`,
|
|
63
|
-
`update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy`,
|
|
64
|
-
`apt install -y locales`,
|
|
65
|
-
`apt install -y cloud-init`,
|
|
66
|
-
`mkdir -p /var/lib/cloud`,
|
|
67
|
-
`chown -R root:root /var/lib/cloud`,
|
|
68
|
-
`chmod -R 0755 /var/lib/cloud`,
|
|
69
|
-
`mkdir -p /home/root/.ssh`,
|
|
70
|
-
`echo '${fs.readFileSync(
|
|
71
|
-
`/home/dd/engine/engine-private/deploy/id_rsa.pub`,
|
|
72
|
-
'utf8',
|
|
73
|
-
)}' >> /home/root/.ssh/authorized_keys`,
|
|
74
|
-
`chmod 700 /home/root/.ssh`,
|
|
75
|
-
`chmod 600 /home/root/.ssh/authorized_keys`,
|
|
76
|
-
`systemctl enable ssh`,
|
|
77
|
-
`systemctl enable ntp`,
|
|
78
|
-
`apt install -y linux-generic-hwe-24.04`,
|
|
79
|
-
`modprobe ip_tables`,
|
|
80
|
-
`cat <<EOF_MAAS_CFG > /etc/cloud/cloud.cfg.d/90_maas.cfg
|
|
81
|
-
datasource_list: [ MAAS ]
|
|
82
|
-
datasource:
|
|
83
|
-
MAAS:
|
|
84
|
-
metadata_url: http://${IP_ADDRESS}:5248/MAAS/metadata
|
|
85
|
-
users:
|
|
86
|
-
- name: ${process.env.MAAS_ADMIN_USERNAME}
|
|
87
|
-
ssh_authorized_keys:
|
|
88
|
-
- ${fs.readFileSync(`/home/dd/engine/engine-private/deploy/id_rsa.pub`, 'utf8')}
|
|
89
|
-
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
|
90
|
-
groups: sudo
|
|
91
|
-
shell: /bin/bash
|
|
92
|
-
packages:
|
|
93
|
-
- git
|
|
94
|
-
- htop
|
|
95
|
-
- ufw
|
|
96
|
-
# package_update: true
|
|
97
|
-
runcmd:
|
|
98
|
-
- ufw enable
|
|
99
|
-
- ufw allow ssh
|
|
100
|
-
resize_rootfs: false
|
|
101
|
-
growpart:
|
|
102
|
-
mode: off
|
|
103
|
-
network:
|
|
104
|
-
version: 2
|
|
105
|
-
ethernets:
|
|
106
|
-
${process.env.RPI4_INTERFACE_NAME}:
|
|
107
|
-
dhcp4: true
|
|
108
|
-
addresses:
|
|
109
|
-
- ${ipaddr}/24
|
|
110
|
-
EOF_MAAS_CFG`,
|
|
111
|
-
];
|
|
112
|
-
|
|
113
|
-
shellExec(`sudo chroot ${nfsHostPath} /usr/bin/qemu-aarch64-static /bin/bash <<'EOF'
|
|
114
|
-
${steps
|
|
115
|
-
.map(
|
|
116
|
-
(s, i) => `echo "step ${i + 1}/${steps.length}: ${s.split('\n')[0]}"
|
|
117
|
-
${s}
|
|
118
|
-
`,
|
|
119
|
-
)
|
|
120
|
-
.join(``)}
|
|
121
|
-
EOF`);
|
|
122
|
-
|
|
123
|
-
shellExec(`sudo chroot ${nfsHostPath} /usr/bin/qemu-aarch64-static /bin/bash <<'EOF'
|
|
124
|
-
echo "nameserver ${process.env.MAAS_DNS}" | tee /etc/resolv.conf > /dev/null
|
|
125
|
-
apt update
|
|
126
|
-
EOF`);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
54
|
try {
|
|
130
55
|
switch (operator) {
|
|
131
56
|
case 'save':
|
|
@@ -797,6 +722,13 @@ try {
|
|
|
797
722
|
.replaceAll(`engine.version: '${version}'`, `engine.version: '${newVersion}'`),
|
|
798
723
|
'utf8',
|
|
799
724
|
);
|
|
725
|
+
fs.writeFileSync(
|
|
726
|
+
`./manifests/deployment/dd-template-development/deployment.yaml`,
|
|
727
|
+
fs
|
|
728
|
+
.readFileSync(`./manifests/deployment/dd-template-development/deployment.yaml`, 'utf8')
|
|
729
|
+
.replaceAll(`underpost:v${version}`, `underpost:v${newVersion}`),
|
|
730
|
+
'utf8',
|
|
731
|
+
);
|
|
800
732
|
|
|
801
733
|
if (fs.existsSync(`./.github/workflows/docker-image.yml`))
|
|
802
734
|
fs.writeFileSync(
|
|
@@ -812,7 +744,7 @@ try {
|
|
|
812
744
|
fs.readFileSync(`./src/index.js`, 'utf8').replaceAll(`${version}`, `${newVersion}`),
|
|
813
745
|
'utf8',
|
|
814
746
|
);
|
|
815
|
-
shellExec(`node bin/deploy cli-docs`);
|
|
747
|
+
shellExec(`node bin/deploy cli-docs ${version} ${newVersion}`);
|
|
816
748
|
shellExec(`node bin/deploy update-dependencies`);
|
|
817
749
|
shellExec(`auto-changelog`);
|
|
818
750
|
shellExec(`node bin/build dd`);
|
|
@@ -921,6 +853,16 @@ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).jo
|
|
|
921
853
|
};
|
|
922
854
|
DefaultConf.server[host][path].apiBaseProxyPath = '/';
|
|
923
855
|
DefaultConf.server[host][path].apiBaseHost = 'www.nexodev.org';
|
|
856
|
+
} else if (confName === 'template') {
|
|
857
|
+
const host = 'default.net';
|
|
858
|
+
const path = '/';
|
|
859
|
+
DefaultConf.server[host][path].valkey = {
|
|
860
|
+
port: 6379,
|
|
861
|
+
host: 'valkey-service.default.svc.cluster.local',
|
|
862
|
+
};
|
|
863
|
+
// mongodb-0.mongodb-service
|
|
864
|
+
DefaultConf.server[host][path].db.host = 'mongodb://mongodb-service:27017';
|
|
865
|
+
confName = '';
|
|
924
866
|
} else if (confName) {
|
|
925
867
|
DefaultConf.client = JSON.parse(fs.readFileSync(`./engine-private/conf/${confName}/conf.client.json`, 'utf8'));
|
|
926
868
|
DefaultConf.server = JSON.parse(fs.readFileSync(`./engine-private/conf/${confName}/conf.server.json`, 'utf8'));
|
|
@@ -1072,6 +1014,29 @@ EOF`);
|
|
|
1072
1014
|
break;
|
|
1073
1015
|
}
|
|
1074
1016
|
|
|
1017
|
+
case 'maas-db': {
|
|
1018
|
+
// DROP, ALTER, CREATE, WITH ENCRYPTED
|
|
1019
|
+
// sudo -u <user> -h <host> psql <db-name>
|
|
1020
|
+
shellExec(`DB_PG_MAAS_NAME=${process.env.DB_PG_MAAS_NAME}`);
|
|
1021
|
+
shellExec(`DB_PG_MAAS_PASS=${process.env.DB_PG_MAAS_PASS}`);
|
|
1022
|
+
shellExec(`DB_PG_MAAS_USER=${process.env.DB_PG_MAAS_USER}`);
|
|
1023
|
+
shellExec(`DB_PG_MAAS_HOST=${process.env.DB_PG_MAAS_HOST}`);
|
|
1024
|
+
shellExec(
|
|
1025
|
+
`sudo -i -u postgres psql -c "CREATE USER \"$DB_PG_MAAS_USER\" WITH ENCRYPTED PASSWORD '$DB_PG_MAAS_PASS'"`,
|
|
1026
|
+
);
|
|
1027
|
+
shellExec(
|
|
1028
|
+
`sudo -i -u postgres psql -c "ALTER USER \"$DB_PG_MAAS_USER\" WITH ENCRYPTED PASSWORD '$DB_PG_MAAS_PASS'"`,
|
|
1029
|
+
);
|
|
1030
|
+
const actions = ['LOGIN', 'SUPERUSER', 'INHERIT', 'CREATEDB', 'CREATEROLE', 'REPLICATION'];
|
|
1031
|
+
shellExec(`sudo -i -u postgres psql -c "ALTER USER \"$DB_PG_MAAS_USER\" WITH ${actions.join(' ')}"`);
|
|
1032
|
+
shellExec(`sudo -i -u postgres psql -c "\\du"`);
|
|
1033
|
+
|
|
1034
|
+
shellExec(`sudo -i -u postgres createdb -O "$DB_PG_MAAS_USER" "$DB_PG_MAAS_NAME"`);
|
|
1035
|
+
|
|
1036
|
+
shellExec(`sudo -i -u postgres psql -c "\\l"`);
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1075
1040
|
case 'valkey': {
|
|
1076
1041
|
if (!process.argv.includes('server')) {
|
|
1077
1042
|
if (process.argv.includes('rocky')) {
|
|
@@ -1141,7 +1106,7 @@ EOF`);
|
|
|
1141
1106
|
}
|
|
1142
1107
|
|
|
1143
1108
|
case 'cli-docs': {
|
|
1144
|
-
buildCliDoc();
|
|
1109
|
+
buildCliDoc(program, process.argv[3], process.argv[4]);
|
|
1145
1110
|
break;
|
|
1146
1111
|
}
|
|
1147
1112
|
|
|
@@ -1193,12 +1158,63 @@ EOF`);
|
|
|
1193
1158
|
break;
|
|
1194
1159
|
}
|
|
1195
1160
|
|
|
1161
|
+
case 'postgresql-17': {
|
|
1162
|
+
if (process.argv.includes('install')) {
|
|
1163
|
+
shellExec(`sudo dnf module reset postgresql -y`);
|
|
1164
|
+
shellExec(`sudo dnf -qy module disable postgresql`);
|
|
1165
|
+
shellExec(
|
|
1166
|
+
`sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm`,
|
|
1167
|
+
);
|
|
1168
|
+
shellExec(`sudo dnf -qy module disable postgresql`);
|
|
1169
|
+
shellExec(`sudo dnf install -y postgresql17 postgresql17-server postgresql17-contrib`);
|
|
1170
|
+
|
|
1171
|
+
shellExec(`sudo /usr/pgsql-17/bin/postgresql-17-setup initdb`);
|
|
1172
|
+
}
|
|
1173
|
+
if (process.argv.includes('uninstall')) {
|
|
1174
|
+
shellExec(`sudo systemctl stop postgresql-17`);
|
|
1175
|
+
shellExec(`sudo systemctl disable postgresql-17`);
|
|
1176
|
+
|
|
1177
|
+
// Remove PostgreSQL 17 packages and repo
|
|
1178
|
+
shellExec(`sudo dnf remove -y postgresql17 postgresql17-server postgresql17-contrib`);
|
|
1179
|
+
shellExec(`sudo rpm -e pgdg-redhat-repo-$(rpm -q pgdg-redhat-repo --qf '%{VERSION}-%{RELEASE}') || true`);
|
|
1180
|
+
shellExec(`sudo rm -f /etc/yum.repos.d/pgdg-redhat-*.repo`);
|
|
1181
|
+
|
|
1182
|
+
// Clean up data, logs, config, and the postgres user
|
|
1183
|
+
shellExec(`sudo rm -rf /var/lib/pgsql/17 /var/log/pgsql`);
|
|
1184
|
+
shellExec(`sudo rm -rf /etc/postgresql`);
|
|
1185
|
+
} else {
|
|
1186
|
+
shellExec(`sudo systemctl enable postgresql-17`);
|
|
1187
|
+
shellExec(`sudo systemctl start postgresql-17`);
|
|
1188
|
+
}
|
|
1189
|
+
break;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1196
1192
|
case 'postgresql-14': {
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1193
|
+
if (process.argv.includes('install')) {
|
|
1194
|
+
shellExec(`sudo dnf module reset postgresql -y`);
|
|
1195
|
+
shellExec(`sudo dnf -qy module disable postgresql`);
|
|
1196
|
+
|
|
1197
|
+
shellExec(`sudo systemctl stop postgresql-14`);
|
|
1198
|
+
shellExec(`sudo systemctl disable postgresql-14`);
|
|
1199
|
+
|
|
1200
|
+
shellExec(`sudo dnf remove -y postgresql14 postgresql14-server postgresql14-contrib`);
|
|
1201
|
+
shellExec(`sudo rm -rf /var/lib/pgsql`);
|
|
1202
|
+
|
|
1203
|
+
shellExec(`sudo dnf install postgresql14 postgresql14-server postgresql14-contrib -y`);
|
|
1204
|
+
}
|
|
1205
|
+
if (process.argv.includes('uninstall')) {
|
|
1206
|
+
shellExec(`sudo systemctl stop postgresql-14`);
|
|
1207
|
+
shellExec(`sudo systemctl disable postgresql-14`);
|
|
1208
|
+
shellExec(`sudo dnf remove -y postgresql14 postgresql14-server postgresql14-contrib`);
|
|
1209
|
+
shellExec(`sudo rm -rf /var/lib/pgsql /var/log/pgsql /etc/postgresql`);
|
|
1210
|
+
} else {
|
|
1211
|
+
shellExec(`sudo /usr/pgsql-14/bin/postgresql-14-setup initdb`);
|
|
1212
|
+
shellExec(`sudo systemctl start postgresql-14`);
|
|
1213
|
+
shellExec(`sudo systemctl enable postgresql-14`);
|
|
1214
|
+
shellExec(`sudo systemctl status postgresql-14`);
|
|
1215
|
+
// sudo dnf install postgresql14-contrib
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1202
1218
|
break;
|
|
1203
1219
|
}
|
|
1204
1220
|
|
|
@@ -1234,592 +1250,6 @@ EOF`);
|
|
|
1234
1250
|
break;
|
|
1235
1251
|
}
|
|
1236
1252
|
|
|
1237
|
-
case 'maas': {
|
|
1238
|
-
dotenv.config({ path: `${getUnderpostRootPath()}/.env`, override: true });
|
|
1239
|
-
const IP_ADDRESS = getLocalIPv4Address();
|
|
1240
|
-
const serverip = IP_ADDRESS;
|
|
1241
|
-
const tftpRoot = process.env.TFTP_ROOT;
|
|
1242
|
-
const ipaddr = process.env.RPI4_IP;
|
|
1243
|
-
const netmask = process.env.NETMASK;
|
|
1244
|
-
const gatewayip = process.env.GATEWAY_IP;
|
|
1245
|
-
|
|
1246
|
-
let resources;
|
|
1247
|
-
try {
|
|
1248
|
-
resources = JSON.parse(
|
|
1249
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-resources read`, {
|
|
1250
|
-
silent: true,
|
|
1251
|
-
stdout: true,
|
|
1252
|
-
}),
|
|
1253
|
-
).map((o) => ({
|
|
1254
|
-
id: o.id,
|
|
1255
|
-
name: o.name,
|
|
1256
|
-
architecture: o.architecture,
|
|
1257
|
-
}));
|
|
1258
|
-
} catch (error) {
|
|
1259
|
-
logger.error(error);
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
const machineFactory = (m) => ({
|
|
1263
|
-
system_id: m.interface_set[0].system_id,
|
|
1264
|
-
mac_address: m.interface_set[0].mac_address,
|
|
1265
|
-
hostname: m.hostname,
|
|
1266
|
-
status_name: m.status_name,
|
|
1267
|
-
});
|
|
1268
|
-
|
|
1269
|
-
let machines;
|
|
1270
|
-
try {
|
|
1271
|
-
machines = JSON.parse(
|
|
1272
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machines read`, {
|
|
1273
|
-
stdout: true,
|
|
1274
|
-
silent: true,
|
|
1275
|
-
}),
|
|
1276
|
-
).map((m) => machineFactory(m));
|
|
1277
|
-
} catch (error) {
|
|
1278
|
-
logger.error(error);
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
if (process.argv.includes('db')) {
|
|
1282
|
-
// DROP, ALTER, CREATE, WITH ENCRYPTED
|
|
1283
|
-
// sudo -u <user> -h <host> psql <db-name>
|
|
1284
|
-
shellExec(`DB_PG_MAAS_NAME=${process.env.DB_PG_MAAS_NAME}`);
|
|
1285
|
-
shellExec(`DB_PG_MAAS_PASS=${process.env.DB_PG_MAAS_PASS}`);
|
|
1286
|
-
shellExec(`DB_PG_MAAS_USER=${process.env.DB_PG_MAAS_USER}`);
|
|
1287
|
-
shellExec(`DB_PG_MAAS_HOST=${process.env.DB_PG_MAAS_HOST}`);
|
|
1288
|
-
shellExec(
|
|
1289
|
-
`sudo -i -u postgres psql -c "CREATE USER \"$DB_PG_MAAS_USER\" WITH ENCRYPTED PASSWORD '$DB_PG_MAAS_PASS'"`,
|
|
1290
|
-
);
|
|
1291
|
-
shellExec(
|
|
1292
|
-
`sudo -i -u postgres psql -c "ALTER USER \"$DB_PG_MAAS_USER\" WITH ENCRYPTED PASSWORD '$DB_PG_MAAS_PASS'"`,
|
|
1293
|
-
);
|
|
1294
|
-
const actions = ['LOGIN', 'SUPERUSER', 'INHERIT', 'CREATEDB', 'CREATEROLE', 'REPLICATION'];
|
|
1295
|
-
shellExec(`sudo -i -u postgres psql -c "ALTER USER \"$DB_PG_MAAS_USER\" WITH ${actions.join(' ')}"`);
|
|
1296
|
-
shellExec(`sudo -i -u postgres psql -c "\\du"`);
|
|
1297
|
-
|
|
1298
|
-
shellExec(`sudo -i -u postgres createdb -O "$DB_PG_MAAS_USER" "$DB_PG_MAAS_NAME"`);
|
|
1299
|
-
|
|
1300
|
-
shellExec(`sudo -i -u postgres psql -c "\\l"`);
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
if (process.argv.includes('ls')) {
|
|
1304
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-sources read`);
|
|
1305
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} commissioning-scripts read`);
|
|
1306
|
-
// shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-source-selections read 60`);
|
|
1307
|
-
console.table(resources);
|
|
1308
|
-
console.table(machines);
|
|
1309
|
-
process.exit(0);
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
// TODO: - Disable maas proxy (egress forwarding to public dns)
|
|
1313
|
-
// - Configure maas dns forwarding ${process.env.MAAS_DNS}
|
|
1314
|
-
// - Enable DNSSEC validation of upstream zones: Automatic (use default root key)
|
|
1315
|
-
|
|
1316
|
-
if (process.argv.includes('clear')) {
|
|
1317
|
-
for (const machine of machines) {
|
|
1318
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machine delete ${machine.system_id}`);
|
|
1319
|
-
}
|
|
1320
|
-
// machines = [];
|
|
1321
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} discoveries clear all=true`);
|
|
1322
|
-
if (process.argv.includes('force')) {
|
|
1323
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} discoveries scan force=true`);
|
|
1324
|
-
}
|
|
1325
|
-
process.exit(0);
|
|
1326
|
-
}
|
|
1327
|
-
if (process.argv.includes('grub-arm64')) {
|
|
1328
|
-
shellExec(`sudo dnf install grub2-efi-aa64-modules`);
|
|
1329
|
-
shellExec(`sudo dnf install grub2-efi-x64-modules`);
|
|
1330
|
-
// sudo grub2-mknetdir --net-directory=${tftpRoot} --subdir=/boot/grub --module-path=/usr/lib/grub/arm64-efi arm64-efi
|
|
1331
|
-
process.exit(0);
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
if (process.argv.includes('psql')) {
|
|
1335
|
-
const cmd = `psql -U ${process.env.DB_PG_MAAS_USER} -h ${process.env.DB_PG_MAAS_HOST} -W ${process.env.DB_PG_MAAS_NAME}`;
|
|
1336
|
-
pbcopy(cmd);
|
|
1337
|
-
process.exit(0);
|
|
1338
|
-
}
|
|
1339
|
-
if (process.argv.includes('logs')) {
|
|
1340
|
-
shellExec(`maas status`);
|
|
1341
|
-
const cmd = `journalctl -f -t dhcpd -u snap.maas.pebble.service`;
|
|
1342
|
-
pbcopy(cmd);
|
|
1343
|
-
process.exit(0);
|
|
1344
|
-
}
|
|
1345
|
-
if (process.argv.includes('reset')) {
|
|
1346
|
-
// shellExec(
|
|
1347
|
-
// `maas init region+rack --database-uri "postgres://$DB_PG_MAAS_USER:$DB_PG_MAAS_PASS@$DB_PG_MAAS_HOST/$DB_PG_MAAS_NAME"` +
|
|
1348
|
-
// ` --maas-url http://${IP_ADDRESS}:5240/MAAS`,
|
|
1349
|
-
// );
|
|
1350
|
-
const cmd =
|
|
1351
|
-
`maas init region+rack --database-uri "postgres://${process.env.DB_PG_MAAS_USER}:${process.env.DB_PG_MAAS_PASS}@${process.env.DB_PG_MAAS_HOST}/${process.env.DB_PG_MAAS_NAME}"` +
|
|
1352
|
-
` --maas-url http://${IP_ADDRESS}:5240/MAAS`;
|
|
1353
|
-
pbcopy(cmd);
|
|
1354
|
-
process.exit(0);
|
|
1355
|
-
}
|
|
1356
|
-
if (process.argv.includes('dhcp')) {
|
|
1357
|
-
const snippets = JSON.parse(
|
|
1358
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} dhcpsnippets read`, {
|
|
1359
|
-
stdout: true,
|
|
1360
|
-
silent: true,
|
|
1361
|
-
disableLog: true,
|
|
1362
|
-
}),
|
|
1363
|
-
);
|
|
1364
|
-
for (const snippet of snippets) {
|
|
1365
|
-
switch (snippet.name) {
|
|
1366
|
-
case 'arm64':
|
|
1367
|
-
snippet.value = snippet.value.split(`\n`);
|
|
1368
|
-
snippet.value[1] = ` filename "http://${IP_ADDRESS}:5248/images/bootloaders/uefi/arm64/grubaa64.efi";`;
|
|
1369
|
-
snippet.value[5] = ` filename "http://${IP_ADDRESS}:5248/images/bootloaders/uefi/arm64/grubaa64.efi";`;
|
|
1370
|
-
snippet.value = snippet.value.join(`\n`);
|
|
1371
|
-
shellExec(
|
|
1372
|
-
`maas ${process.env.MAAS_ADMIN_USERNAME} dhcpsnippet update ${snippet.name} value='${snippet.value}'`,
|
|
1373
|
-
);
|
|
1374
|
-
break;
|
|
1375
|
-
|
|
1376
|
-
default:
|
|
1377
|
-
break;
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
console.log(snippets);
|
|
1382
|
-
|
|
1383
|
-
process.exit(0);
|
|
1384
|
-
}
|
|
1385
|
-
// shellExec(`MAAS_ADMIN_USERNAME=${process.env.MAAS_ADMIN_USERNAME}`);
|
|
1386
|
-
// shellExec(`MAAS_ADMIN_EMAIL=${process.env.MAAS_ADMIN_EMAIL}`);
|
|
1387
|
-
// shellExec(`maas createadmin --username $MAAS_ADMIN_USERNAME --email $MAAS_ADMIN_EMAIL`);
|
|
1388
|
-
|
|
1389
|
-
// MaaS admin CLI:
|
|
1390
|
-
// maas login <maas-admin-username> http://localhost:5240/MAAS
|
|
1391
|
-
// paste GUI API KEY (profile section)
|
|
1392
|
-
|
|
1393
|
-
// Import custom image
|
|
1394
|
-
// maas <maas-admin-username> boot-resources create name='custom/RockyLinuxRpi4' \
|
|
1395
|
-
// title='RockyLinuxRpi4' \
|
|
1396
|
-
// architecture='arm64/generic' \
|
|
1397
|
-
// filetype='tgz' \
|
|
1398
|
-
// content@=/home/RockyLinuxRpi_9-latest.tar.gz
|
|
1399
|
-
|
|
1400
|
-
// Image boot resource:
|
|
1401
|
-
// /var/snap/maas/current/root/snap/maas
|
|
1402
|
-
// /var/snap/maas/common/maas/tftp_root
|
|
1403
|
-
// sudo chmod 755 /var/snap/maas/common/maas/tftp_root
|
|
1404
|
-
|
|
1405
|
-
// /var/snap/maas/common/maas/dhcpd.conf
|
|
1406
|
-
// sudo snap restart maas.pebble
|
|
1407
|
-
|
|
1408
|
-
// PXE Linux files:
|
|
1409
|
-
// /var/snap/maas/common/maas/image-storage/bootloaders/pxe/i386
|
|
1410
|
-
// sudo nmcli con modify <interface-device-name-connection-id> ethtool.feature-rx on ethtool.feature-tx off
|
|
1411
|
-
// sudo nmcli connection up <interface-device-name-connection-id>
|
|
1412
|
-
|
|
1413
|
-
// man nm-settings |grep feature-tx-checksum
|
|
1414
|
-
|
|
1415
|
-
// nmcli c modify <interface-device-name-connection-id> \
|
|
1416
|
-
// ethtool.feature-tx-checksum-fcoe-crc off \
|
|
1417
|
-
// ethtool.feature-tx-checksum-ip-generic off \
|
|
1418
|
-
// ethtool.feature-tx-checksum-ipv4 off \
|
|
1419
|
-
// ethtool.feature-tx-checksum-ipv6 off \
|
|
1420
|
-
// ethtool.feature-tx-checksum-sctp off
|
|
1421
|
-
|
|
1422
|
-
// Ensure Rocky NFS server and /etc/exports configured
|
|
1423
|
-
// sudo systemctl restart nfs-server
|
|
1424
|
-
// Check mounts: showmount -e <server-ip>
|
|
1425
|
-
// Check nfs ports: rpcinfo -p
|
|
1426
|
-
// sudo chown -R root:root ${process.env.NFS_EXPORT_PATH}/rpi4mb
|
|
1427
|
-
// sudo chmod 755 ${process.env.NFS_EXPORT_PATH}/rpi4mb
|
|
1428
|
-
|
|
1429
|
-
// tftp server
|
|
1430
|
-
// sudo chown -R root:root /var/snap/maas/common/maas/tftp_root/rpi4mb
|
|
1431
|
-
|
|
1432
|
-
// tftp client
|
|
1433
|
-
// sudo dnf install tftp
|
|
1434
|
-
// tftp <server-ip> -c get <path>
|
|
1435
|
-
|
|
1436
|
-
// Check firewall-cmd
|
|
1437
|
-
// firewall-cmd --permanent --add-service=rpc-bind
|
|
1438
|
-
// firewall-cmd --reload
|
|
1439
|
-
// systemctl disable firewalld
|
|
1440
|
-
// sudo firewall-cmd --permanent --add-port=10259/tcp --zone=public
|
|
1441
|
-
|
|
1442
|
-
// Image extension transform (.img.xz to .tar.gz):
|
|
1443
|
-
// tar -cvzf image-name.tar.gz image-name.img.xz
|
|
1444
|
-
|
|
1445
|
-
// Rocky network configuration:
|
|
1446
|
-
// /etc/NetworkManager/system-connections
|
|
1447
|
-
|
|
1448
|
-
// Rocky kernel params update
|
|
1449
|
-
// sudo grubby --args="<key>=<value> <key>=<value>" --update-kernel=ALL
|
|
1450
|
-
// sudo reboot now
|
|
1451
|
-
|
|
1452
|
-
// Temporal:
|
|
1453
|
-
// sudo snap install temporal
|
|
1454
|
-
// journalctl -u snap.maas.pebble -t maas-regiond
|
|
1455
|
-
// journalctl -u snap.maas.pebble -t maas-temporal -n 100 --no-pager -f
|
|
1456
|
-
|
|
1457
|
-
// Remove:
|
|
1458
|
-
// sudo dnf remove <package> -y; sudo dnf autoremove -y; sudo dnf clean packages
|
|
1459
|
-
// check: ~
|
|
1460
|
-
// check: ~./cache
|
|
1461
|
-
// check: ~./config
|
|
1462
|
-
|
|
1463
|
-
// Check file logs
|
|
1464
|
-
// grep -i -E -C 1 '<key-a>|<key-b>' /example.log | tail -n 600
|
|
1465
|
-
|
|
1466
|
-
// Back into your firmware setup (UEFI or BIOS config screen).
|
|
1467
|
-
// grub> fwsetup
|
|
1468
|
-
|
|
1469
|
-
// Poweroff:
|
|
1470
|
-
// grub > halt
|
|
1471
|
-
// initramfs > poweroff
|
|
1472
|
-
|
|
1473
|
-
// Check interface
|
|
1474
|
-
// ip link show
|
|
1475
|
-
// nmcli con show
|
|
1476
|
-
|
|
1477
|
-
let firmwarePath,
|
|
1478
|
-
tftpSubDir,
|
|
1479
|
-
kernelFilesPaths,
|
|
1480
|
-
name,
|
|
1481
|
-
architecture,
|
|
1482
|
-
resource,
|
|
1483
|
-
nfsConnectStr,
|
|
1484
|
-
etcExports,
|
|
1485
|
-
nfsServerRootPath,
|
|
1486
|
-
bootConf,
|
|
1487
|
-
zipFirmwareFileName,
|
|
1488
|
-
zipFirmwareName,
|
|
1489
|
-
zipFirmwareUrl,
|
|
1490
|
-
interfaceName,
|
|
1491
|
-
nfsHost;
|
|
1492
|
-
|
|
1493
|
-
switch (process.argv[3]) {
|
|
1494
|
-
case 'rpi4mb':
|
|
1495
|
-
const resourceId = process.argv[4] ?? '39';
|
|
1496
|
-
tftpSubDir = '/rpi4mb';
|
|
1497
|
-
zipFirmwareFileName = `RPi4_UEFI_Firmware_v1.41.zip`;
|
|
1498
|
-
zipFirmwareName = zipFirmwareFileName.split('.zip')[0];
|
|
1499
|
-
zipFirmwareUrl = `https://github.com/pftf/RPi4/releases/download/v1.41/RPi4_UEFI_Firmware_v1.41.zip`;
|
|
1500
|
-
firmwarePath = `../${zipFirmwareName}`;
|
|
1501
|
-
interfaceName = process.env.RPI4_INTERFACE_NAME;
|
|
1502
|
-
nfsHost = 'rpi4mb';
|
|
1503
|
-
if (!fs.existsSync(firmwarePath)) {
|
|
1504
|
-
await Downloader(zipFirmwareUrl, `../${zipFirmwareFileName}`);
|
|
1505
|
-
shellExec(`cd .. && mkdir ${zipFirmwareName} && cd ${zipFirmwareName} && unzip ../${zipFirmwareFileName}`);
|
|
1506
|
-
}
|
|
1507
|
-
resource = resources.find((o) => o.id == resourceId);
|
|
1508
|
-
name = resource.name;
|
|
1509
|
-
architecture = resource.architecture;
|
|
1510
|
-
resource = resources.find((o) => o.name === name && o.architecture === architecture);
|
|
1511
|
-
nfsServerRootPath = `${process.env.NFS_EXPORT_PATH}/rpi4mb`;
|
|
1512
|
-
// ,anonuid=1001,anongid=100
|
|
1513
|
-
// etcExports = `${nfsServerRootPath} *(rw,all_squash,sync,no_root_squash,insecure)`;
|
|
1514
|
-
etcExports = `${nfsServerRootPath} 192.168.1.0/24(${[
|
|
1515
|
-
'rw',
|
|
1516
|
-
// 'all_squash',
|
|
1517
|
-
'sync',
|
|
1518
|
-
'no_root_squash',
|
|
1519
|
-
'no_subtree_check',
|
|
1520
|
-
'insecure',
|
|
1521
|
-
]})`;
|
|
1522
|
-
const resourceData = JSON.parse(
|
|
1523
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-resource read ${resource.id}`, {
|
|
1524
|
-
stdout: true,
|
|
1525
|
-
silent: true,
|
|
1526
|
-
disableLog: true,
|
|
1527
|
-
}),
|
|
1528
|
-
);
|
|
1529
|
-
const bootFiles = resourceData.sets[Object.keys(resourceData.sets)[0]].files;
|
|
1530
|
-
const suffix = architecture.match('xgene') ? '.xgene' : '';
|
|
1531
|
-
|
|
1532
|
-
kernelFilesPaths = {
|
|
1533
|
-
'vmlinuz-efi': bootFiles['boot-kernel' + suffix].filename_on_disk,
|
|
1534
|
-
'initrd.img': bootFiles['boot-initrd' + suffix].filename_on_disk,
|
|
1535
|
-
squashfs: bootFiles['squashfs'].filename_on_disk,
|
|
1536
|
-
};
|
|
1537
|
-
const protocol = 'tcp'; // v3 -> tcp, v4 -> udp
|
|
1538
|
-
|
|
1539
|
-
const mountOptions = [
|
|
1540
|
-
protocol,
|
|
1541
|
-
'vers=3',
|
|
1542
|
-
'nfsvers=3',
|
|
1543
|
-
'nolock',
|
|
1544
|
-
// 'protocol=tcp',
|
|
1545
|
-
// 'hard=true',
|
|
1546
|
-
'port=2049',
|
|
1547
|
-
// 'sec=none',
|
|
1548
|
-
'rw',
|
|
1549
|
-
'hard',
|
|
1550
|
-
'intr',
|
|
1551
|
-
'rsize=32768',
|
|
1552
|
-
'wsize=32768',
|
|
1553
|
-
'acregmin=0',
|
|
1554
|
-
'acregmax=0',
|
|
1555
|
-
'acdirmin=0',
|
|
1556
|
-
'acdirmax=0',
|
|
1557
|
-
'noac',
|
|
1558
|
-
// 'nodev',
|
|
1559
|
-
// 'nosuid',
|
|
1560
|
-
];
|
|
1561
|
-
const cmd = [
|
|
1562
|
-
`console=serial0,115200`,
|
|
1563
|
-
`console=tty1`,
|
|
1564
|
-
// `initrd=-1`,
|
|
1565
|
-
// `net.ifnames=0`,
|
|
1566
|
-
// `dwc_otg.lpm_enable=0`,
|
|
1567
|
-
// `elevator=deadline`,
|
|
1568
|
-
`root=/dev/nfs`,
|
|
1569
|
-
`nfsroot=${serverip}:${process.env.NFS_EXPORT_PATH}/rpi4mb,${mountOptions}`,
|
|
1570
|
-
// `nfsroot=${serverip}:${process.env.NFS_EXPORT_PATH}/rpi4mb`,
|
|
1571
|
-
`ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${nfsHost}:${interfaceName}:static`,
|
|
1572
|
-
`rootfstype=nfs`,
|
|
1573
|
-
`rw`,
|
|
1574
|
-
`rootwait`,
|
|
1575
|
-
`fixrtc`,
|
|
1576
|
-
'initrd=initrd.img',
|
|
1577
|
-
// 'boot=casper',
|
|
1578
|
-
// 'ro',
|
|
1579
|
-
'netboot=nfs',
|
|
1580
|
-
`cloud-config-url=/dev/null`,
|
|
1581
|
-
// 'ip=dhcp',
|
|
1582
|
-
// 'ip=dfcp',
|
|
1583
|
-
// 'autoinstall',
|
|
1584
|
-
// 'rd.break',
|
|
1585
|
-
];
|
|
1586
|
-
|
|
1587
|
-
nfsConnectStr = cmd.join(' ');
|
|
1588
|
-
bootConf = `[all]
|
|
1589
|
-
MAC_ADDRESS=00:00:00:00:00:00
|
|
1590
|
-
MAC_ADDRESS_OTP=0,1
|
|
1591
|
-
BOOT_UART=0
|
|
1592
|
-
WAKE_ON_GPIO=1
|
|
1593
|
-
POWER_OFF_ON_HALT=0
|
|
1594
|
-
ENABLE_SELF_UPDATE=1
|
|
1595
|
-
DISABLE_HDMI=0
|
|
1596
|
-
TFTP_IP=${serverip}
|
|
1597
|
-
TFTP_PREFIX=1
|
|
1598
|
-
TFTP_PREFIX_STR=${tftpSubDir.slice(1)}/
|
|
1599
|
-
NET_INSTALL_ENABLED=1
|
|
1600
|
-
DHCP_TIMEOUT=45000
|
|
1601
|
-
DHCP_REQ_TIMEOUT=4000
|
|
1602
|
-
TFTP_FILE_TIMEOUT=30000
|
|
1603
|
-
BOOT_ORDER=0x21`;
|
|
1604
|
-
|
|
1605
|
-
break;
|
|
1606
|
-
|
|
1607
|
-
default:
|
|
1608
|
-
break;
|
|
1609
|
-
}
|
|
1610
|
-
shellExec(`sudo chmod 755 ${process.env.NFS_EXPORT_PATH}/${nfsHost}`);
|
|
1611
|
-
|
|
1612
|
-
shellExec(`sudo rm -rf ${tftpRoot}${tftpSubDir}`);
|
|
1613
|
-
shellExec(`sudo cp -a ${firmwarePath} ${tftpRoot}${tftpSubDir}`);
|
|
1614
|
-
shellExec(`mkdir -p ${tftpRoot}${tftpSubDir}/pxe`);
|
|
1615
|
-
|
|
1616
|
-
fs.writeFileSync(`/etc/exports`, etcExports, 'utf8');
|
|
1617
|
-
if (bootConf) fs.writeFileSync(`${tftpRoot}${tftpSubDir}/boot.conf`, bootConf, 'utf8');
|
|
1618
|
-
|
|
1619
|
-
shellExec(`node bin/deploy nfs`);
|
|
1620
|
-
|
|
1621
|
-
if (process.argv.includes('restart')) {
|
|
1622
|
-
shellExec(`sudo snap restart maas.pebble`);
|
|
1623
|
-
let secs = 0;
|
|
1624
|
-
while (
|
|
1625
|
-
!(
|
|
1626
|
-
shellExec(`maas status`, { silent: true, disableLog: true, stdout: true })
|
|
1627
|
-
.split(' ')
|
|
1628
|
-
.filter((l) => l.match('inactive')).length === 1
|
|
1629
|
-
)
|
|
1630
|
-
) {
|
|
1631
|
-
await timer(1000);
|
|
1632
|
-
console.log(`Waiting... (${++secs}s)`);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
|
|
1636
|
-
switch (process.argv[3]) {
|
|
1637
|
-
case 'rpi4mb':
|
|
1638
|
-
{
|
|
1639
|
-
// subnet DHCP snippets
|
|
1640
|
-
// # UEFI ARM64
|
|
1641
|
-
// if option arch = 00:0B {
|
|
1642
|
-
// filename "rpi4mb/pxe/grubaa64.efi";
|
|
1643
|
-
// }
|
|
1644
|
-
// elsif option arch = 00:13 {
|
|
1645
|
-
// filename "http://<IP_ADDRESS>:5248/images/bootloaders/uefi/arm64/grubaa64.efi";
|
|
1646
|
-
// option vendor-class-identifier "HTTPClient";
|
|
1647
|
-
// }
|
|
1648
|
-
for (const file of ['bootaa64.efi', 'grubaa64.efi']) {
|
|
1649
|
-
shellExec(
|
|
1650
|
-
`sudo cp -a /var/snap/maas/common/maas/image-storage/bootloaders/uefi/arm64/${file} ${tftpRoot}${tftpSubDir}/pxe/${file}`,
|
|
1651
|
-
);
|
|
1652
|
-
}
|
|
1653
|
-
// const file = 'bcm2711-rpi-4-b.dtb';
|
|
1654
|
-
// shellExec(
|
|
1655
|
-
// `sudo cp -a ${firmwarePath}/${file} /var/snap/maas/common/maas/image-storage/bootloaders/uefi/arm64/${file}`,
|
|
1656
|
-
// );
|
|
1657
|
-
|
|
1658
|
-
// const ipxeSrc = fs
|
|
1659
|
-
// .readFileSync(`${tftpRoot}/ipxe.cfg`, 'utf8')
|
|
1660
|
-
// .replaceAll('amd64', 'arm64')
|
|
1661
|
-
// .replaceAll('${next-server}', IP_ADDRESS);
|
|
1662
|
-
// fs.writeFileSync(`${tftpRoot}/ipxe.cfg`, ipxeSrc, 'utf8');
|
|
1663
|
-
|
|
1664
|
-
{
|
|
1665
|
-
for (const file of Object.keys(kernelFilesPaths)) {
|
|
1666
|
-
shellExec(
|
|
1667
|
-
`sudo cp -a /var/snap/maas/common/maas/image-storage/${kernelFilesPaths[file]} ${tftpRoot}${tftpSubDir}/pxe/${file}`,
|
|
1668
|
-
);
|
|
1669
|
-
}
|
|
1670
|
-
// const configTxtSrc = fs.readFileSync(`${firmwarePath}/config.txt`, 'utf8');
|
|
1671
|
-
// fs.writeFileSync(
|
|
1672
|
-
// `${tftpRoot}${tftpSubDir}/config.txt`,
|
|
1673
|
-
// configTxtSrc
|
|
1674
|
-
// .replace(`kernel=kernel8.img`, `kernel=vmlinuz`)
|
|
1675
|
-
// .replace(`# max_framebuffers=2`, `max_framebuffers=2`)
|
|
1676
|
-
// .replace(`initramfs initramfs8 followkernel`, `initramfs initrd.img followkernel`),
|
|
1677
|
-
// 'utf8',
|
|
1678
|
-
// );
|
|
1679
|
-
|
|
1680
|
-
// grub:
|
|
1681
|
-
// set root=(pxe)
|
|
1682
|
-
|
|
1683
|
-
// UNDERPOST.NET UEFI/GRUB/MAAS RPi4 commissioning (ARM64)
|
|
1684
|
-
const menuentryStr = 'underpost.net rpi4mb maas commissioning (ARM64)';
|
|
1685
|
-
const grubCfgPath = `${tftpRoot}/grub/grub.cfg`;
|
|
1686
|
-
fs.writeFileSync(
|
|
1687
|
-
grubCfgPath,
|
|
1688
|
-
`
|
|
1689
|
-
insmod gzio
|
|
1690
|
-
insmod http
|
|
1691
|
-
insmod nfs
|
|
1692
|
-
set timeout=5
|
|
1693
|
-
set default=0
|
|
1694
|
-
|
|
1695
|
-
menuentry '${menuentryStr}' {
|
|
1696
|
-
set root=(tftp,${serverip})
|
|
1697
|
-
linux ${tftpSubDir}/pxe/vmlinuz-efi ${nfsConnectStr}
|
|
1698
|
-
initrd ${tftpSubDir}/pxe/initrd.img
|
|
1699
|
-
boot
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
`,
|
|
1703
|
-
'utf8',
|
|
1704
|
-
);
|
|
1705
|
-
}
|
|
1706
|
-
const arm64EfiPath = `${tftpRoot}/grub/arm64-efi`;
|
|
1707
|
-
if (fs.existsSync(arm64EfiPath)) shellExec(`sudo rm -rf ${arm64EfiPath}`);
|
|
1708
|
-
shellExec(`sudo cp -a /usr/lib/grub/arm64-efi ${arm64EfiPath}`);
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
|
-
break;
|
|
1712
|
-
|
|
1713
|
-
default:
|
|
1714
|
-
break;
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
logger.info('succes maas deploy', {
|
|
1718
|
-
resource,
|
|
1719
|
-
kernelFilesPaths,
|
|
1720
|
-
tftpRoot,
|
|
1721
|
-
tftpSubDir,
|
|
1722
|
-
firmwarePath,
|
|
1723
|
-
etcExports,
|
|
1724
|
-
nfsServerRootPath,
|
|
1725
|
-
nfsConnectStr,
|
|
1726
|
-
});
|
|
1727
|
-
if (process.argv.includes('restart')) {
|
|
1728
|
-
if (fs.existsSync(`node engine-private/r.js`)) shellExec(`node engine-private/r`);
|
|
1729
|
-
shellExec(`node bin/deploy maas dhcp`);
|
|
1730
|
-
shellExec(`sudo chown -R root:root ${tftpRoot}`);
|
|
1731
|
-
shellExec(`sudo sudo chmod 755 ${tftpRoot}`);
|
|
1732
|
-
}
|
|
1733
|
-
// for (const machine of machines) {
|
|
1734
|
-
// // shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machine delete ${machine.system_id}`);
|
|
1735
|
-
// shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machine commission ${machine.system_id}`, {
|
|
1736
|
-
// silent: true,
|
|
1737
|
-
// });
|
|
1738
|
-
// }
|
|
1739
|
-
// machines = [];
|
|
1740
|
-
|
|
1741
|
-
const monitor = async () => {
|
|
1742
|
-
// discoveries Query observed discoveries.
|
|
1743
|
-
// discovery Read or delete an observed discovery.
|
|
1744
|
-
|
|
1745
|
-
const discoveries = JSON.parse(
|
|
1746
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} discoveries read`, {
|
|
1747
|
-
silent: true,
|
|
1748
|
-
stdout: true,
|
|
1749
|
-
}),
|
|
1750
|
-
).filter(
|
|
1751
|
-
(o) => o.ip !== IP_ADDRESS && o.ip !== gatewayip && !machines.find((_o) => _o.mac_address === o.mac_address),
|
|
1752
|
-
);
|
|
1753
|
-
|
|
1754
|
-
// {
|
|
1755
|
-
// "discovery_id": "",
|
|
1756
|
-
// "ip": "192.168.1.189",
|
|
1757
|
-
// "mac_address": "00:00:00:00:00:00",
|
|
1758
|
-
// "last_seen": "2025-05-05T14:17:37.354",
|
|
1759
|
-
// "hostname": null,
|
|
1760
|
-
// "fabric_name": "",
|
|
1761
|
-
// "vid": null,
|
|
1762
|
-
// "mac_organization": "",
|
|
1763
|
-
// "observer": {
|
|
1764
|
-
// "system_id": "",
|
|
1765
|
-
// "hostname": "",
|
|
1766
|
-
// "interface_id": 1,
|
|
1767
|
-
// "interface_name": ""
|
|
1768
|
-
// },
|
|
1769
|
-
// "resource_uri": "/MAAS/api/2.0/discovery/MTkyLjE2OC4xLjE4OSwwMDowMDowMDowMDowMDowMA==/"
|
|
1770
|
-
// },
|
|
1771
|
-
|
|
1772
|
-
for (const discovery of discoveries) {
|
|
1773
|
-
const machine = {
|
|
1774
|
-
architecture: architecture.match('amd') ? 'amd64/generic' : 'arm64/generic',
|
|
1775
|
-
mac_address: discovery.mac_address,
|
|
1776
|
-
hostname: discovery.hostname ?? discovery.mac_organization ?? discovery.domain ?? `generic-host-${s4()}`,
|
|
1777
|
-
// discovery.ip.match(ipaddr)
|
|
1778
|
-
// ? nfsHost
|
|
1779
|
-
// : `unknown-${s4()}`,
|
|
1780
|
-
// description: '',
|
|
1781
|
-
// https://maas.io/docs/reference-power-drivers
|
|
1782
|
-
power_type: 'manual', // manual
|
|
1783
|
-
// power_parameters_power_address: discovery.ip,
|
|
1784
|
-
mac_addresses: discovery.mac_address,
|
|
1785
|
-
};
|
|
1786
|
-
machine.hostname = machine.hostname.replaceAll(' ', '').replaceAll('.', '');
|
|
1787
|
-
|
|
1788
|
-
try {
|
|
1789
|
-
let newMachine = shellExec(
|
|
1790
|
-
`maas ${process.env.MAAS_ADMIN_USERNAME} machines create ${Object.keys(machine)
|
|
1791
|
-
.map((k) => `${k}="${machine[k]}"`)
|
|
1792
|
-
.join(' ')}`,
|
|
1793
|
-
{
|
|
1794
|
-
silent: true,
|
|
1795
|
-
stdout: true,
|
|
1796
|
-
},
|
|
1797
|
-
);
|
|
1798
|
-
newMachine = machineFactory(JSON.parse(newMachine));
|
|
1799
|
-
machines.push(newMachine);
|
|
1800
|
-
console.log(newMachine);
|
|
1801
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machine commission ${newMachine.system_id}`, {
|
|
1802
|
-
silent: true,
|
|
1803
|
-
});
|
|
1804
|
-
} catch (error) {
|
|
1805
|
-
logger.error(error, error.stack);
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
// if (discoveries.length > 0) {
|
|
1809
|
-
// shellExec(
|
|
1810
|
-
// `maas ${process.env.MAAS_ADMIN_USERNAME} machines read | jq '.[] | {system_id: .interface_set[0].system_id, hostname, status_name, mac_address: .interface_set[0].mac_address}'`,
|
|
1811
|
-
// );
|
|
1812
|
-
// }
|
|
1813
|
-
await timer(1000);
|
|
1814
|
-
monitor();
|
|
1815
|
-
};
|
|
1816
|
-
// shellExec(`node bin/deploy open-virtual-root ${architecture.match('amd') ? 'amd64' : 'arm64'} ${nfsHost}`);
|
|
1817
|
-
machines = [];
|
|
1818
|
-
shellExec(`node bin/deploy maas clear`);
|
|
1819
|
-
monitor();
|
|
1820
|
-
break;
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
1253
|
case 'nfs': {
|
|
1824
1254
|
// Daemon RPC NFSv3. ports:
|
|
1825
1255
|
|
|
@@ -1895,129 +1325,6 @@ udp-port = 32766
|
|
|
1895
1325
|
shellExec(`sudo systemctl restart nfs-server`);
|
|
1896
1326
|
break;
|
|
1897
1327
|
}
|
|
1898
|
-
case 'update-virtual-root': {
|
|
1899
|
-
dotenv.config({ path: `${getUnderpostRootPath()}/.env`, override: true });
|
|
1900
|
-
const IP_ADDRESS = getLocalIPv4Address();
|
|
1901
|
-
const architecture = process.argv[3];
|
|
1902
|
-
const host = process.argv[4];
|
|
1903
|
-
const nfsHostPath = `${process.env.NFS_EXPORT_PATH}/${host}`;
|
|
1904
|
-
const ipaddr = process.env.RPI4_IP;
|
|
1905
|
-
await updateVirtualRoot({
|
|
1906
|
-
IP_ADDRESS,
|
|
1907
|
-
architecture,
|
|
1908
|
-
host,
|
|
1909
|
-
nfsHostPath,
|
|
1910
|
-
ipaddr,
|
|
1911
|
-
});
|
|
1912
|
-
break;
|
|
1913
|
-
}
|
|
1914
|
-
case 'open-virtual-root': {
|
|
1915
|
-
dotenv.config({ path: `${getUnderpostRootPath()}/.env`, override: true });
|
|
1916
|
-
const IP_ADDRESS = getLocalIPv4Address();
|
|
1917
|
-
const architecture = process.argv[3];
|
|
1918
|
-
const host = process.argv[4];
|
|
1919
|
-
const nfsHostPath = `${process.env.NFS_EXPORT_PATH}/${host}`;
|
|
1920
|
-
shellExec(`sudo dnf install -y iptables-legacy`);
|
|
1921
|
-
shellExec(`sudo dnf install -y debootstrap`);
|
|
1922
|
-
shellExec(`sudo dnf install kernel-modules-extra-$(uname -r)`);
|
|
1923
|
-
switch (architecture) {
|
|
1924
|
-
case 'arm64':
|
|
1925
|
-
shellExec(`sudo podman run --rm --privileged multiarch/qemu-user-static --reset -p yes`);
|
|
1926
|
-
|
|
1927
|
-
break;
|
|
1928
|
-
|
|
1929
|
-
default:
|
|
1930
|
-
break;
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
shellExec(`sudo modprobe binfmt_misc`);
|
|
1934
|
-
shellExec(`sudo mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc`);
|
|
1935
|
-
|
|
1936
|
-
if (process.argv.includes('build')) {
|
|
1937
|
-
// shellExec(`depmod -a`);
|
|
1938
|
-
shellExec(`mkdir -p ${nfsHostPath}`);
|
|
1939
|
-
let cmd;
|
|
1940
|
-
switch (host) {
|
|
1941
|
-
case 'rpi4mb':
|
|
1942
|
-
shellExec(`sudo rm -rf ${nfsHostPath}/*`);
|
|
1943
|
-
shellExec(`sudo chown -R root:root ${nfsHostPath}`);
|
|
1944
|
-
cmd = [
|
|
1945
|
-
`sudo debootstrap`,
|
|
1946
|
-
`--arch=arm64`,
|
|
1947
|
-
`--variant=minbase`,
|
|
1948
|
-
`--foreign`, // arm64 on amd64
|
|
1949
|
-
`noble`,
|
|
1950
|
-
nfsHostPath,
|
|
1951
|
-
`http://ports.ubuntu.com/ubuntu-ports/`,
|
|
1952
|
-
];
|
|
1953
|
-
break;
|
|
1954
|
-
|
|
1955
|
-
default:
|
|
1956
|
-
break;
|
|
1957
|
-
}
|
|
1958
|
-
shellExec(cmd.join(' '));
|
|
1959
|
-
|
|
1960
|
-
shellExec(`sudo podman create --name extract multiarch/qemu-user-static`);
|
|
1961
|
-
shellExec(`podman ps -a`);
|
|
1962
|
-
shellExec(`sudo podman cp extract:/usr/bin/qemu-aarch64-static ${nfsHostPath}/usr/bin/`);
|
|
1963
|
-
shellExec(`sudo podman rm extract`);
|
|
1964
|
-
shellExec(`podman ps -a`);
|
|
1965
|
-
|
|
1966
|
-
switch (host) {
|
|
1967
|
-
case 'rpi4mb':
|
|
1968
|
-
shellExec(`file ${nfsHostPath}/bin/bash`); // expected: ELF 64-bit LSB pie executable, ARM aarch64 …
|
|
1969
|
-
break;
|
|
1970
|
-
|
|
1971
|
-
default:
|
|
1972
|
-
break;
|
|
1973
|
-
}
|
|
1974
|
-
|
|
1975
|
-
shellExec(`sudo chroot ${nfsHostPath} /usr/bin/qemu-aarch64-static /bin/bash <<'EOF'
|
|
1976
|
-
/debootstrap/debootstrap --second-stage
|
|
1977
|
-
EOF`);
|
|
1978
|
-
}
|
|
1979
|
-
if (process.argv.includes('mount')) {
|
|
1980
|
-
shellExec(`sudo mount --bind /proc ${nfsHostPath}/proc`);
|
|
1981
|
-
shellExec(`sudo mount --bind /sys ${nfsHostPath}/sys`);
|
|
1982
|
-
shellExec(`sudo mount --rbind /dev ${nfsHostPath}/dev`);
|
|
1983
|
-
}
|
|
1984
|
-
|
|
1985
|
-
if (process.argv.includes('build')) {
|
|
1986
|
-
switch (host) {
|
|
1987
|
-
case 'rpi4mb':
|
|
1988
|
-
const ipaddr = process.env.RPI4_IP;
|
|
1989
|
-
|
|
1990
|
-
await updateVirtualRoot({
|
|
1991
|
-
IP_ADDRESS,
|
|
1992
|
-
architecture,
|
|
1993
|
-
host,
|
|
1994
|
-
nfsHostPath,
|
|
1995
|
-
ipaddr,
|
|
1996
|
-
});
|
|
1997
|
-
|
|
1998
|
-
break;
|
|
1999
|
-
|
|
2000
|
-
default:
|
|
2001
|
-
break;
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
// if (process.argv.includes('mount')) {
|
|
2005
|
-
// shellExec(`sudo mount --bind /lib/modules ${nfsHostPath}/lib/modules`);
|
|
2006
|
-
// }
|
|
2007
|
-
|
|
2008
|
-
break;
|
|
2009
|
-
}
|
|
2010
|
-
|
|
2011
|
-
case 'close-virtual-root': {
|
|
2012
|
-
const architecture = process.argv[3];
|
|
2013
|
-
const host = process.argv[4];
|
|
2014
|
-
const nfsHostPath = `${process.env.NFS_EXPORT_PATH}/${host}`;
|
|
2015
|
-
shellExec(`sudo umount ${nfsHostPath}/proc`);
|
|
2016
|
-
shellExec(`sudo umount ${nfsHostPath}/sys`);
|
|
2017
|
-
shellExec(`sudo umount ${nfsHostPath}/dev`);
|
|
2018
|
-
// shellExec(`sudo umount ${nfsHostPath}/lib/modules`);
|
|
2019
|
-
break;
|
|
2020
|
-
}
|
|
2021
1328
|
|
|
2022
1329
|
case 'mount': {
|
|
2023
1330
|
const mounts = shellExec(`mount`).split(`\n`);
|
|
@@ -2040,10 +1347,10 @@ EOF`);
|
|
|
2040
1347
|
|
|
2041
1348
|
case 'create-ports': {
|
|
2042
1349
|
const cmd = [];
|
|
2043
|
-
const
|
|
1350
|
+
const commissioningDeviceIp = getLocalIPv4Address();
|
|
2044
1351
|
for (const port of ['5240']) {
|
|
2045
1352
|
const name = 'maas';
|
|
2046
|
-
cmd.push(`${name}:${port}-${port}:${
|
|
1353
|
+
cmd.push(`${name}:${port}-${port}:${commissioningDeviceIp}`);
|
|
2047
1354
|
}
|
|
2048
1355
|
pbcopy(`node engine-private/r create-port ${cmd}`);
|
|
2049
1356
|
break;
|
|
@@ -2223,7 +1530,7 @@ EOF`);
|
|
|
2223
1530
|
const args = [
|
|
2224
1531
|
`node bin dockerfile-image-build --path ${path}/backend/`,
|
|
2225
1532
|
`--image-name=${imageName} --image-path=${path}`,
|
|
2226
|
-
`--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --
|
|
1533
|
+
`--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --reset`,
|
|
2227
1534
|
];
|
|
2228
1535
|
shellExec(args.join(' '));
|
|
2229
1536
|
}
|
|
@@ -2235,7 +1542,7 @@ EOF`);
|
|
|
2235
1542
|
const args = [
|
|
2236
1543
|
`node bin dockerfile-image-build --path ${path}/frontend/`,
|
|
2237
1544
|
`--image-name=${imageName} --image-path=${path}`,
|
|
2238
|
-
`--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --
|
|
1545
|
+
`--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --reset`,
|
|
2239
1546
|
];
|
|
2240
1547
|
shellExec(args.join(' '));
|
|
2241
1548
|
}
|