underpost 2.8.799 → 2.8.812
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 +23 -21
- package/.github/workflows/npmpkg.yml +16 -11
- package/.github/workflows/pwa-microservices-template.page.yml +12 -3
- package/.github/workflows/pwa-microservices-template.test.yml +20 -17
- package/.vscode/extensions.json +1 -2
- package/.vscode/settings.json +3 -0
- package/Dockerfile +14 -33
- package/README.md +25 -24
- package/bin/deploy.js +409 -112
- package/bin/vs.js +10 -3
- package/cli.md +331 -219
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +18 -18
- package/manifests/lxd/underpost-setup.sh +1 -1
- package/manifests/maas/lxd-preseed.yaml +32 -0
- package/manifests/maas/maas-setup.sh +64 -0
- package/manifests/mariadb/statefulset.yaml +2 -1
- package/manifests/mariadb/storage-class.yaml +10 -0
- package/package.json +1 -1
- package/src/cli/baremetal.js +99 -0
- package/src/cli/cluster.js +14 -0
- package/src/cli/deploy.js +1 -1
- package/src/cli/env.js +2 -2
- package/src/cli/image.js +4 -3
- package/src/cli/index.js +244 -239
- package/src/index.js +9 -1
- package/src/runtime/lampp/Dockerfile +41 -47
- package/src/server/conf.js +58 -0
- 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,53 +51,139 @@ logger.info('argv', process.argv);
|
|
|
50
51
|
|
|
51
52
|
const [exe, dir, operator] = process.argv;
|
|
52
53
|
|
|
53
|
-
const updateVirtualRoot = async ({
|
|
54
|
-
|
|
54
|
+
const updateVirtualRoot = async ({ IP_ADDRESS, architecture, host, nfsHostPath, ipaddr, update, gatewayip }) => {
|
|
55
|
+
// <consumer_key>:<consumer_token>:<secret>
|
|
56
|
+
const MAAS_API_TOKEN = shellExec(`maas apikey --username ${process.env.MAAS_ADMIN_USERNAME}`, {
|
|
57
|
+
stdout: true,
|
|
58
|
+
}).trim();
|
|
59
|
+
const [consumer_key, consumer_token, secret] = MAAS_API_TOKEN.split(`\n`)[0].split(':');
|
|
60
|
+
const chronyConfPath = `/etc/chrony/chrony.conf`;
|
|
61
|
+
const timezone = 'America/New_York';
|
|
62
|
+
const timeZoneSteps = [
|
|
63
|
+
`apt-get update`,
|
|
64
|
+
|
|
65
|
+
`export DEBIAN_FRONTEND=noninteractive`,
|
|
66
|
+
|
|
67
|
+
`ln -fs /usr/share/zoneinfo/${timezone} /etc/localtime`,
|
|
68
|
+
|
|
69
|
+
`DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata`,
|
|
70
|
+
`dpkg-reconfigure --frontend noninteractive tzdata`,
|
|
71
|
+
];
|
|
72
|
+
const keyboardSteps = [
|
|
73
|
+
`sudo locale-gen en_US.UTF-8`,
|
|
74
|
+
`sudo update-locale LANG=en_US.UTF-8`,
|
|
75
|
+
`sudo sed -i 's/XKBLAYOUT="us"/XKBLAYOUT="es"/' /etc/default/keyboard`,
|
|
76
|
+
`sudo dpkg-reconfigure --frontend noninteractive keyboard-configuration`,
|
|
77
|
+
`sudo systemctl restart keyboard-setup.service`,
|
|
78
|
+
];
|
|
79
|
+
// # - ${JSON.stringify([...timeZoneSteps, ...chronySetUp(chronyConfPath)])}
|
|
80
|
+
const installSteps = [
|
|
55
81
|
`apt update`,
|
|
82
|
+
`apt install -y cloud-init systemd-sysv openssh-server sudo locales udev util-linux systemd-sysv iproute2 netplan.io ca-certificates curl wget chrony ntpdate keyboard-configuration`,
|
|
56
83
|
`ln -sf /lib/systemd/systemd /sbin/init`,
|
|
57
|
-
|
|
58
|
-
`
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
`
|
|
68
|
-
`
|
|
84
|
+
|
|
85
|
+
`echo 'deb http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse
|
|
86
|
+
deb http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse
|
|
87
|
+
deb http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse
|
|
88
|
+
|
|
89
|
+
# Uncomment the following lines if you also need source packages (for building from source)
|
|
90
|
+
# deb-src http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse
|
|
91
|
+
# deb-src http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse
|
|
92
|
+
# deb-src http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse
|
|
93
|
+
' > /etc/apt/sources.list`,
|
|
94
|
+
`apt update`,
|
|
95
|
+
`apt -y full-upgrade`,
|
|
96
|
+
// `apt install -y cloud-init=25.1.2-0ubuntu0~24.04.1`,
|
|
97
|
+
|
|
98
|
+
`systemctl enable ssh`,
|
|
99
|
+
|
|
100
|
+
`apt update -qq`,
|
|
101
|
+
`apt install -y xinput x11-xkb-utils usbutils`,
|
|
102
|
+
|
|
103
|
+
// `date -s "${shellExec(`date '+%Y-%m-%d %H:%M:%S'`, { stdout: true }).trim()}"`,
|
|
104
|
+
// `date`,
|
|
105
|
+
|
|
106
|
+
...timeZoneSteps,
|
|
107
|
+
...chronySetUp(chronyConfPath),
|
|
108
|
+
...keyboardSteps,
|
|
109
|
+
|
|
110
|
+
// Create root user
|
|
111
|
+
`useradd -m -s /bin/bash -G sudo root`,
|
|
112
|
+
`echo 'root:root' | chpasswd`,
|
|
69
113
|
`mkdir -p /home/root/.ssh`,
|
|
70
114
|
`echo '${fs.readFileSync(
|
|
71
115
|
`/home/dd/engine/engine-private/deploy/id_rsa.pub`,
|
|
72
116
|
'utf8',
|
|
73
|
-
)}'
|
|
117
|
+
)}' > /home/root/.ssh/authorized_keys`,
|
|
118
|
+
`chown -R root /home/root/.ssh`,
|
|
74
119
|
`chmod 700 /home/root/.ssh`,
|
|
75
120
|
`chmod 600 /home/root/.ssh/authorized_keys`,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
let steps = [
|
|
124
|
+
// Configure cloud-init for MAAS
|
|
80
125
|
`cat <<EOF_MAAS_CFG > /etc/cloud/cloud.cfg.d/90_maas.cfg
|
|
126
|
+
#cloud-config
|
|
127
|
+
|
|
128
|
+
hostname: ${host}
|
|
129
|
+
# fqdn: server01.midominio.cl
|
|
130
|
+
# prefer_fqdn_over_hostname: true
|
|
131
|
+
# metadata_url: http://${IP_ADDRESS}:5240/MAAS/metadata
|
|
132
|
+
# metadata_url: http://${IP_ADDRESS}:5248/MAAS/metadata
|
|
133
|
+
|
|
134
|
+
# Check:
|
|
135
|
+
# /MAAS/metadata/latest/enlist-preseed/?op=get_enlist_preseed
|
|
136
|
+
|
|
137
|
+
# Debug:
|
|
138
|
+
# https://maas.io/docs/how-to-use-logging
|
|
139
|
+
|
|
81
140
|
datasource_list: [ MAAS ]
|
|
82
141
|
datasource:
|
|
83
142
|
MAAS:
|
|
84
|
-
metadata_url: http://${IP_ADDRESS}:
|
|
143
|
+
metadata_url: http://${IP_ADDRESS}:5240/MAAS/metadata
|
|
144
|
+
consumer_key: ${consumer_key}
|
|
145
|
+
token_key: ${consumer_token}
|
|
146
|
+
token_secret: ${secret}
|
|
85
147
|
users:
|
|
86
|
-
- name:
|
|
148
|
+
- name: rpiadmin
|
|
149
|
+
sudo: ['ALL=(ALL) NOPASSWD:ALL']
|
|
150
|
+
shell: /bin/bash
|
|
151
|
+
lock_passwd: true
|
|
87
152
|
ssh_authorized_keys:
|
|
88
153
|
- ${fs.readFileSync(`/home/dd/engine/engine-private/deploy/id_rsa.pub`, 'utf8')}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# keyboard:
|
|
157
|
+
# layout: es
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# check timedatectl on host
|
|
161
|
+
# timezone: America/Santiago
|
|
162
|
+
timezone: ${timezone}
|
|
163
|
+
|
|
164
|
+
ntp:
|
|
165
|
+
enabled: true
|
|
166
|
+
servers:
|
|
167
|
+
- ${IP_ADDRESS}
|
|
168
|
+
ntp_client: chrony
|
|
169
|
+
config:
|
|
170
|
+
confpath: ${chronyConfPath}
|
|
171
|
+
packages:
|
|
172
|
+
- chrony
|
|
173
|
+
service_name: chrony
|
|
174
|
+
|
|
175
|
+
# ssh:
|
|
176
|
+
# allow-pw: false
|
|
177
|
+
# install-server: true
|
|
178
|
+
|
|
179
|
+
# ssh_pwauth: false
|
|
180
|
+
|
|
181
|
+
package_update: true
|
|
182
|
+
package_upgrade: true
|
|
92
183
|
packages:
|
|
93
184
|
- git
|
|
94
185
|
- htop
|
|
95
|
-
-
|
|
96
|
-
# package_update: true
|
|
97
|
-
runcmd:
|
|
98
|
-
- ufw enable
|
|
99
|
-
- ufw allow ssh
|
|
186
|
+
- snapd
|
|
100
187
|
resize_rootfs: false
|
|
101
188
|
growpart:
|
|
102
189
|
mode: off
|
|
@@ -104,26 +191,141 @@ network:
|
|
|
104
191
|
version: 2
|
|
105
192
|
ethernets:
|
|
106
193
|
${process.env.RPI4_INTERFACE_NAME}:
|
|
107
|
-
dhcp4:
|
|
194
|
+
dhcp4: false
|
|
108
195
|
addresses:
|
|
109
196
|
- ${ipaddr}/24
|
|
197
|
+
routes:
|
|
198
|
+
- to: default
|
|
199
|
+
via: ${gatewayip}
|
|
200
|
+
|
|
201
|
+
# chpasswd:
|
|
202
|
+
# expire: false
|
|
203
|
+
# users:
|
|
204
|
+
# - {name: rpiadmin, password: changeme, type: text}
|
|
205
|
+
|
|
206
|
+
final_message: "The system is up, after $UPTIME seconds"
|
|
207
|
+
|
|
208
|
+
# power_state:
|
|
209
|
+
# mode: reboot
|
|
210
|
+
# message: Rebooting after initial setup
|
|
211
|
+
# timeout: 30
|
|
212
|
+
# condition: True
|
|
213
|
+
bootcmd:
|
|
214
|
+
- echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
|
|
215
|
+
- echo "Init bootcmd"
|
|
216
|
+
- echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
|
|
217
|
+
- ntpdate -u ${IP_ADDRESS} || ntpdate -u ${process.env.MAAS_NTP_SERVER}
|
|
218
|
+
runcmd:
|
|
219
|
+
- echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
|
|
220
|
+
- echo "Init runcmd"
|
|
221
|
+
- echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
|
|
110
222
|
EOF_MAAS_CFG`,
|
|
111
223
|
];
|
|
112
224
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
${s}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
225
|
+
const runSteps = (steps = []) => {
|
|
226
|
+
const script = steps
|
|
227
|
+
.map(
|
|
228
|
+
(s, i) => `echo "step ${i + 1}/${steps.length}: ${s.split('\n')[0]}"
|
|
229
|
+
${s}`,
|
|
230
|
+
)
|
|
231
|
+
.join('\n');
|
|
232
|
+
|
|
233
|
+
const cmd = `sudo chroot ${nfsHostPath} /usr/bin/qemu-aarch64-static /bin/bash <<'EOF_OUTER'
|
|
234
|
+
${script}
|
|
235
|
+
EOF_OUTER`;
|
|
236
|
+
|
|
237
|
+
shellExec(cmd);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
if (update) {
|
|
241
|
+
// --reboot
|
|
242
|
+
shellExec(`sudo chroot ${nfsHostPath} /usr/bin/qemu-aarch64-static /bin/bash <<'EOF'
|
|
243
|
+
sudo cloud-init clean --logs --seed --configs all --machine-id
|
|
244
|
+
sudo rm -rf /var/lib/cloud/*
|
|
121
245
|
EOF`);
|
|
122
246
|
|
|
123
|
-
|
|
247
|
+
if (fs.existsSync(`${nfsHostPath}/var/log/`)) {
|
|
248
|
+
fs.writeFileSync(`${nfsHostPath}/var/log/cloud-init.log`, '', 'utf8');
|
|
249
|
+
fs.writeFileSync(`${nfsHostPath}/var/log/cloud-init-output.log`, '', 'utf8');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
runSteps(steps);
|
|
253
|
+
} else {
|
|
254
|
+
runSteps(installSteps.concat(steps));
|
|
255
|
+
|
|
256
|
+
shellExec(`sudo chroot ${nfsHostPath} /usr/bin/qemu-aarch64-static /bin/bash <<'EOF'
|
|
124
257
|
echo "nameserver ${process.env.MAAS_DNS}" | tee /etc/resolv.conf > /dev/null
|
|
125
258
|
apt update
|
|
126
259
|
EOF`);
|
|
260
|
+
fs.writeFileSync(
|
|
261
|
+
`${nfsHostPath}/dns.sh`,
|
|
262
|
+
`rm /etc/resolv.conf
|
|
263
|
+
echo 'nameserver 8.8.8.8' > /run/systemd/resolve/stub-resolv.conf
|
|
264
|
+
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf`,
|
|
265
|
+
'utf8',
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const chronySetUp = (path) => {
|
|
271
|
+
return [
|
|
272
|
+
`echo '
|
|
273
|
+
# Use public servers from the pool.ntp.org project.
|
|
274
|
+
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
|
|
275
|
+
# pool 2.pool.ntp.org iburst
|
|
276
|
+
server ${process.env.MAAS_NTP_SERVER} iburst
|
|
277
|
+
|
|
278
|
+
# Record the rate at which the system clock gains/losses time.
|
|
279
|
+
driftfile /var/lib/chrony/drift
|
|
280
|
+
|
|
281
|
+
# Allow the system clock to be stepped in the first three updates
|
|
282
|
+
# if its offset is larger than 1 second.
|
|
283
|
+
makestep 1.0 3
|
|
284
|
+
|
|
285
|
+
# Enable kernel synchronization of the real-time clock (RTC).
|
|
286
|
+
rtcsync
|
|
287
|
+
|
|
288
|
+
# Enable hardware timestamping on all interfaces that support it.
|
|
289
|
+
#hwtimestamp *
|
|
290
|
+
|
|
291
|
+
# Increase the minimum number of selectable sources required to adjust
|
|
292
|
+
# the system clock.
|
|
293
|
+
#minsources 2
|
|
294
|
+
|
|
295
|
+
# Allow NTP client access from local network.
|
|
296
|
+
#allow 192.168.0.0/16
|
|
297
|
+
|
|
298
|
+
# Serve time even if not synchronized to a time source.
|
|
299
|
+
#local stratum 10
|
|
300
|
+
|
|
301
|
+
# Specify file containing keys for NTP authentication.
|
|
302
|
+
keyfile /etc/chrony.keys
|
|
303
|
+
|
|
304
|
+
# Get TAI-UTC offset and leap seconds from the system tz database.
|
|
305
|
+
leapsectz right/UTC
|
|
306
|
+
|
|
307
|
+
# Specify directory for log files.
|
|
308
|
+
logdir /var/log/chrony
|
|
309
|
+
|
|
310
|
+
# Select which information is logged.
|
|
311
|
+
#log measurements statistics tracking
|
|
312
|
+
' > ${path} `,
|
|
313
|
+
`sudo systemctl stop chronyd`,
|
|
314
|
+
|
|
315
|
+
// `chronyd -q 'server 0.europe.pool.ntp.org iburst'`,
|
|
316
|
+
`chronyd -q 'server ntp.ubuntu.com iburst'`,
|
|
317
|
+
|
|
318
|
+
`sudo systemctl enable --now chronyd`,
|
|
319
|
+
`sudo systemctl restart chronyd`,
|
|
320
|
+
`sudo systemctl status chronyd`,
|
|
321
|
+
|
|
322
|
+
`chronyc sources`,
|
|
323
|
+
`chronyc tracking`,
|
|
324
|
+
// sudo firewall-cmd --add-service=ntp --permanent
|
|
325
|
+
// sudo firewall-cmd --reload
|
|
326
|
+
|
|
327
|
+
`chronyc sourcestats -v`,
|
|
328
|
+
];
|
|
127
329
|
};
|
|
128
330
|
|
|
129
331
|
try {
|
|
@@ -1158,7 +1360,7 @@ EOF`);
|
|
|
1158
1360
|
}
|
|
1159
1361
|
|
|
1160
1362
|
case 'cli-docs': {
|
|
1161
|
-
buildCliDoc();
|
|
1363
|
+
buildCliDoc(program);
|
|
1162
1364
|
break;
|
|
1163
1365
|
}
|
|
1164
1366
|
|
|
@@ -1210,12 +1412,63 @@ EOF`);
|
|
|
1210
1412
|
break;
|
|
1211
1413
|
}
|
|
1212
1414
|
|
|
1415
|
+
case 'postgresql-17': {
|
|
1416
|
+
if (process.argv.includes('install')) {
|
|
1417
|
+
shellExec(`sudo dnf module reset postgresql -y`);
|
|
1418
|
+
shellExec(`sudo dnf -qy module disable postgresql`);
|
|
1419
|
+
shellExec(
|
|
1420
|
+
`sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm`,
|
|
1421
|
+
);
|
|
1422
|
+
shellExec(`sudo dnf -qy module disable postgresql`);
|
|
1423
|
+
shellExec(`sudo dnf install -y postgresql17 postgresql17-server postgresql17-contrib`);
|
|
1424
|
+
|
|
1425
|
+
shellExec(`sudo /usr/pgsql-17/bin/postgresql-17-setup initdb`);
|
|
1426
|
+
}
|
|
1427
|
+
if (process.argv.includes('uninstall')) {
|
|
1428
|
+
shellExec(`sudo systemctl stop postgresql-17`);
|
|
1429
|
+
shellExec(`sudo systemctl disable postgresql-17`);
|
|
1430
|
+
|
|
1431
|
+
// Remove PostgreSQL 17 packages and repo
|
|
1432
|
+
shellExec(`sudo dnf remove -y postgresql17 postgresql17-server postgresql17-contrib`);
|
|
1433
|
+
shellExec(`sudo rpm -e pgdg-redhat-repo-$(rpm -q pgdg-redhat-repo --qf '%{VERSION}-%{RELEASE}') || true`);
|
|
1434
|
+
shellExec(`sudo rm -f /etc/yum.repos.d/pgdg-redhat-*.repo`);
|
|
1435
|
+
|
|
1436
|
+
// Clean up data, logs, config, and the postgres user
|
|
1437
|
+
shellExec(`sudo rm -rf /var/lib/pgsql/17 /var/log/pgsql`);
|
|
1438
|
+
shellExec(`sudo rm -rf /etc/postgresql`);
|
|
1439
|
+
} else {
|
|
1440
|
+
shellExec(`sudo systemctl enable postgresql-17`);
|
|
1441
|
+
shellExec(`sudo systemctl start postgresql-17`);
|
|
1442
|
+
}
|
|
1443
|
+
break;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1213
1446
|
case 'postgresql-14': {
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1447
|
+
if (process.argv.includes('install')) {
|
|
1448
|
+
shellExec(`sudo dnf module reset postgresql -y`);
|
|
1449
|
+
shellExec(`sudo dnf -qy module disable postgresql`);
|
|
1450
|
+
|
|
1451
|
+
shellExec(`sudo systemctl stop postgresql-14`);
|
|
1452
|
+
shellExec(`sudo systemctl disable postgresql-14`);
|
|
1453
|
+
|
|
1454
|
+
shellExec(`sudo dnf remove -y postgresql14 postgresql14-server postgresql14-contrib`);
|
|
1455
|
+
shellExec(`sudo rm -rf /var/lib/pgsql`);
|
|
1456
|
+
|
|
1457
|
+
shellExec(`sudo dnf install postgresql14 postgresql14-server postgresql14-contrib -y`);
|
|
1458
|
+
}
|
|
1459
|
+
if (process.argv.includes('uninstall')) {
|
|
1460
|
+
shellExec(`sudo systemctl stop postgresql-14`);
|
|
1461
|
+
shellExec(`sudo systemctl disable postgresql-14`);
|
|
1462
|
+
shellExec(`sudo dnf remove -y postgresql14 postgresql14-server postgresql14-contrib`);
|
|
1463
|
+
shellExec(`sudo rm -rf /var/lib/pgsql /var/log/pgsql /etc/postgresql`);
|
|
1464
|
+
} else {
|
|
1465
|
+
shellExec(`sudo /usr/pgsql-14/bin/postgresql-14-setup initdb`);
|
|
1466
|
+
shellExec(`sudo systemctl start postgresql-14`);
|
|
1467
|
+
shellExec(`sudo systemctl enable postgresql-14`);
|
|
1468
|
+
shellExec(`sudo systemctl status postgresql-14`);
|
|
1469
|
+
// sudo dnf install postgresql14-contrib
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1219
1472
|
break;
|
|
1220
1473
|
}
|
|
1221
1474
|
|
|
@@ -1252,6 +1505,9 @@ EOF`);
|
|
|
1252
1505
|
}
|
|
1253
1506
|
|
|
1254
1507
|
case 'maas': {
|
|
1508
|
+
shellExec(
|
|
1509
|
+
`underpost secret underpost --create-from-file /home/dd/engine/engine-private/conf/dd-cron/.env.production`,
|
|
1510
|
+
);
|
|
1255
1511
|
dotenv.config({ path: `${getUnderpostRootPath()}/.env`, override: true });
|
|
1256
1512
|
const IP_ADDRESS = getLocalIPv4Address();
|
|
1257
1513
|
const serverip = IP_ADDRESS;
|
|
@@ -1260,6 +1516,13 @@ EOF`);
|
|
|
1260
1516
|
const netmask = process.env.NETMASK;
|
|
1261
1517
|
const gatewayip = process.env.GATEWAY_IP;
|
|
1262
1518
|
|
|
1519
|
+
const machineFactory = (m) => ({
|
|
1520
|
+
system_id: m.interface_set[0].system_id,
|
|
1521
|
+
mac_address: m.interface_set[0].mac_address,
|
|
1522
|
+
hostname: m.hostname,
|
|
1523
|
+
status_name: m.status_name,
|
|
1524
|
+
});
|
|
1525
|
+
|
|
1263
1526
|
let resources;
|
|
1264
1527
|
try {
|
|
1265
1528
|
resources = JSON.parse(
|
|
@@ -1276,13 +1539,6 @@ EOF`);
|
|
|
1276
1539
|
logger.error(error);
|
|
1277
1540
|
}
|
|
1278
1541
|
|
|
1279
|
-
const machineFactory = (m) => ({
|
|
1280
|
-
system_id: m.interface_set[0].system_id,
|
|
1281
|
-
mac_address: m.interface_set[0].mac_address,
|
|
1282
|
-
hostname: m.hostname,
|
|
1283
|
-
status_name: m.status_name,
|
|
1284
|
-
});
|
|
1285
|
-
|
|
1286
1542
|
let machines;
|
|
1287
1543
|
try {
|
|
1288
1544
|
machines = JSON.parse(
|
|
@@ -1295,6 +1551,25 @@ EOF`);
|
|
|
1295
1551
|
logger.error(error);
|
|
1296
1552
|
}
|
|
1297
1553
|
|
|
1554
|
+
if (process.argv.includes('ls')) {
|
|
1555
|
+
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-sources read`);
|
|
1556
|
+
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} commissioning-scripts read`);
|
|
1557
|
+
// shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-source-selections read 60`);
|
|
1558
|
+
logger.info('Resources');
|
|
1559
|
+
console.table(resources);
|
|
1560
|
+
logger.info('Machines');
|
|
1561
|
+
console.table(machines);
|
|
1562
|
+
process.exit(0);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
if (process.argv.includes('config')) {
|
|
1566
|
+
shellExec(`sudo sed -i 's/^#Storage=auto/Storage=volatile/' /etc/systemd/journald.conf`);
|
|
1567
|
+
shellExec(`sudo systemctl daemon-reload`);
|
|
1568
|
+
shellExec(`sudo systemctl restart systemd-journald`);
|
|
1569
|
+
shellExec(`journalctl --disk-usage`);
|
|
1570
|
+
process.exit(0);
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1298
1573
|
if (process.argv.includes('db')) {
|
|
1299
1574
|
// DROP, ALTER, CREATE, WITH ENCRYPTED
|
|
1300
1575
|
// sudo -u <user> -h <host> psql <db-name>
|
|
@@ -1315,20 +1590,13 @@ EOF`);
|
|
|
1315
1590
|
shellExec(`sudo -i -u postgres createdb -O "$DB_PG_MAAS_USER" "$DB_PG_MAAS_NAME"`);
|
|
1316
1591
|
|
|
1317
1592
|
shellExec(`sudo -i -u postgres psql -c "\\l"`);
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
if (process.argv.includes('ls')) {
|
|
1321
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-sources read`);
|
|
1322
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} commissioning-scripts read`);
|
|
1323
|
-
// shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-source-selections read 60`);
|
|
1324
|
-
console.table(resources);
|
|
1325
|
-
console.table(machines);
|
|
1326
1593
|
process.exit(0);
|
|
1327
1594
|
}
|
|
1328
1595
|
|
|
1329
1596
|
// TODO: - Disable maas proxy (egress forwarding to public dns)
|
|
1597
|
+
// - Configure maas dhcp control server
|
|
1330
1598
|
// - Configure maas dns forwarding ${process.env.MAAS_DNS}
|
|
1331
|
-
// -
|
|
1599
|
+
// - Disable DNSSEC validation to No (Disable DNSSEC; useful when upstream DNS is misconfigured)
|
|
1332
1600
|
|
|
1333
1601
|
if (process.argv.includes('clear')) {
|
|
1334
1602
|
for (const machine of machines) {
|
|
@@ -1370,35 +1638,23 @@ EOF`);
|
|
|
1370
1638
|
pbcopy(cmd);
|
|
1371
1639
|
process.exit(0);
|
|
1372
1640
|
}
|
|
1373
|
-
if (process.argv.includes('dhcp')) {
|
|
1374
|
-
const snippets = JSON.parse(
|
|
1375
|
-
shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} dhcpsnippets read`, {
|
|
1376
|
-
stdout: true,
|
|
1377
|
-
silent: true,
|
|
1378
|
-
disableLog: true,
|
|
1379
|
-
}),
|
|
1380
|
-
);
|
|
1381
|
-
for (const snippet of snippets) {
|
|
1382
|
-
switch (snippet.name) {
|
|
1383
|
-
case 'arm64':
|
|
1384
|
-
snippet.value = snippet.value.split(`\n`);
|
|
1385
|
-
snippet.value[1] = ` filename "http://${IP_ADDRESS}:5248/images/bootloaders/uefi/arm64/grubaa64.efi";`;
|
|
1386
|
-
snippet.value[5] = ` filename "http://${IP_ADDRESS}:5248/images/bootloaders/uefi/arm64/grubaa64.efi";`;
|
|
1387
|
-
snippet.value = snippet.value.join(`\n`);
|
|
1388
|
-
shellExec(
|
|
1389
|
-
`maas ${process.env.MAAS_ADMIN_USERNAME} dhcpsnippet update ${snippet.name} value='${snippet.value}'`,
|
|
1390
|
-
);
|
|
1391
|
-
break;
|
|
1392
1641
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1642
|
+
if (process.argv.includes('restart')) {
|
|
1643
|
+
shellExec(`sudo snap restart maas.pebble`);
|
|
1644
|
+
let secs = 0;
|
|
1645
|
+
while (
|
|
1646
|
+
!(
|
|
1647
|
+
shellExec(`maas status`, { silent: true, disableLog: true, stdout: true })
|
|
1648
|
+
.split(' ')
|
|
1649
|
+
.filter((l) => l.match('inactive')).length === 1
|
|
1650
|
+
)
|
|
1651
|
+
) {
|
|
1652
|
+
await timer(1000);
|
|
1653
|
+
console.log(`Waiting... (${++secs}s)`);
|
|
1396
1654
|
}
|
|
1397
|
-
|
|
1398
|
-
console.log(snippets);
|
|
1399
|
-
|
|
1400
1655
|
process.exit(0);
|
|
1401
1656
|
}
|
|
1657
|
+
|
|
1402
1658
|
// shellExec(`MAAS_ADMIN_USERNAME=${process.env.MAAS_ADMIN_USERNAME}`);
|
|
1403
1659
|
// shellExec(`MAAS_ADMIN_EMAIL=${process.env.MAAS_ADMIN_EMAIL}`);
|
|
1404
1660
|
// shellExec(`maas createadmin --username $MAAS_ADMIN_USERNAME --email $MAAS_ADMIN_EMAIL`);
|
|
@@ -1509,7 +1765,6 @@ EOF`);
|
|
|
1509
1765
|
|
|
1510
1766
|
switch (process.argv[3]) {
|
|
1511
1767
|
case 'rpi4mb':
|
|
1512
|
-
const resourceId = process.argv[4] ?? '39';
|
|
1513
1768
|
tftpSubDir = '/rpi4mb';
|
|
1514
1769
|
zipFirmwareFileName = `RPi4_UEFI_Firmware_v1.41.zip`;
|
|
1515
1770
|
zipFirmwareName = zipFirmwareFileName.split('.zip')[0];
|
|
@@ -1521,7 +1776,7 @@ EOF`);
|
|
|
1521
1776
|
await Downloader(zipFirmwareUrl, `../${zipFirmwareFileName}`);
|
|
1522
1777
|
shellExec(`cd .. && mkdir ${zipFirmwareName} && cd ${zipFirmwareName} && unzip ../${zipFirmwareFileName}`);
|
|
1523
1778
|
}
|
|
1524
|
-
resource = resources.find((o) => o.
|
|
1779
|
+
resource = resources.find((o) => o.architecture === 'arm64/ga-24.04' && o.name === 'ubuntu/noble');
|
|
1525
1780
|
name = resource.name;
|
|
1526
1781
|
architecture = resource.architecture;
|
|
1527
1782
|
resource = resources.find((o) => o.name === name && o.architecture === architecture);
|
|
@@ -1594,13 +1849,48 @@ EOF`);
|
|
|
1594
1849
|
// 'boot=casper',
|
|
1595
1850
|
// 'ro',
|
|
1596
1851
|
'netboot=nfs',
|
|
1597
|
-
`
|
|
1852
|
+
`init=/sbin/init`,
|
|
1853
|
+
// `cloud-config-url=/dev/null`,
|
|
1598
1854
|
// 'ip=dhcp',
|
|
1599
1855
|
// 'ip=dfcp',
|
|
1600
1856
|
// 'autoinstall',
|
|
1601
1857
|
// 'rd.break',
|
|
1602
1858
|
];
|
|
1603
1859
|
|
|
1860
|
+
// TODO: use autoinstall cloud-config-url=http://<MAAS_IP>:5240/MAAS/metadata/latest
|
|
1861
|
+
// #cloud-config
|
|
1862
|
+
// autoinstall:
|
|
1863
|
+
// version: 1
|
|
1864
|
+
|
|
1865
|
+
// keyboard:
|
|
1866
|
+
// layout: es
|
|
1867
|
+
// variant: latinamerican
|
|
1868
|
+
|
|
1869
|
+
// identity:
|
|
1870
|
+
// hostname: rpi4
|
|
1871
|
+
// username: rpiadmin
|
|
1872
|
+
// password: "{{PASSWORD}}"
|
|
1873
|
+
|
|
1874
|
+
// ssh:
|
|
1875
|
+
// install-server: true
|
|
1876
|
+
// allow-pw: true
|
|
1877
|
+
// authorized-keys:
|
|
1878
|
+
// - "{{SSH_KEY}}"
|
|
1879
|
+
|
|
1880
|
+
// locale: es_ES.UTF-8
|
|
1881
|
+
// timezone: America/Santiago
|
|
1882
|
+
|
|
1883
|
+
// packages:
|
|
1884
|
+
// - cloud-init
|
|
1885
|
+
// - systemd-sysv
|
|
1886
|
+
// - openssh-server
|
|
1887
|
+
// - sudo
|
|
1888
|
+
// - udev
|
|
1889
|
+
// - netplan.io
|
|
1890
|
+
|
|
1891
|
+
// late-commands:
|
|
1892
|
+
// - curtin in-target --target=/target ln -sf /lib/systemd/systemd /sbin/init
|
|
1893
|
+
|
|
1604
1894
|
nfsConnectStr = cmd.join(' ');
|
|
1605
1895
|
bootConf = `[all]
|
|
1606
1896
|
MAC_ADDRESS=00:00:00:00:00:00
|
|
@@ -1618,7 +1908,8 @@ DHCP_TIMEOUT=45000
|
|
|
1618
1908
|
DHCP_REQ_TIMEOUT=4000
|
|
1619
1909
|
TFTP_FILE_TIMEOUT=30000
|
|
1620
1910
|
BOOT_ORDER=0x21`;
|
|
1621
|
-
|
|
1911
|
+
// CLIENT_IP=${ipaddr}
|
|
1912
|
+
// SUBNET=255.255.255.0
|
|
1622
1913
|
break;
|
|
1623
1914
|
|
|
1624
1915
|
default:
|
|
@@ -1635,21 +1926,6 @@ BOOT_ORDER=0x21`;
|
|
|
1635
1926
|
|
|
1636
1927
|
shellExec(`node bin/deploy nfs`);
|
|
1637
1928
|
|
|
1638
|
-
if (process.argv.includes('restart')) {
|
|
1639
|
-
shellExec(`sudo snap restart maas.pebble`);
|
|
1640
|
-
let secs = 0;
|
|
1641
|
-
while (
|
|
1642
|
-
!(
|
|
1643
|
-
shellExec(`maas status`, { silent: true, disableLog: true, stdout: true })
|
|
1644
|
-
.split(' ')
|
|
1645
|
-
.filter((l) => l.match('inactive')).length === 1
|
|
1646
|
-
)
|
|
1647
|
-
) {
|
|
1648
|
-
await timer(1000);
|
|
1649
|
-
console.log(`Waiting... (${++secs}s)`);
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
1929
|
switch (process.argv[3]) {
|
|
1654
1930
|
case 'rpi4mb':
|
|
1655
1931
|
{
|
|
@@ -1815,9 +2091,13 @@ BOOT_ORDER=0x21`;
|
|
|
1815
2091
|
newMachine = machineFactory(JSON.parse(newMachine));
|
|
1816
2092
|
machines.push(newMachine);
|
|
1817
2093
|
console.log(newMachine);
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
2094
|
+
// commissioning_scripts=90-verify-user.sh
|
|
2095
|
+
shellExec(
|
|
2096
|
+
`maas ${process.env.MAAS_ADMIN_USERNAME} machine commission ${newMachine.system_id} enable_ssh=1 skip_bmc_config=1 skip_networking=1 skip_storage=1`,
|
|
2097
|
+
{
|
|
2098
|
+
silent: true,
|
|
2099
|
+
},
|
|
2100
|
+
);
|
|
1821
2101
|
} catch (error) {
|
|
1822
2102
|
logger.error(error, error.stack);
|
|
1823
2103
|
}
|
|
@@ -1919,12 +2199,15 @@ udp-port = 32766
|
|
|
1919
2199
|
const host = process.argv[4];
|
|
1920
2200
|
const nfsHostPath = `${process.env.NFS_EXPORT_PATH}/${host}`;
|
|
1921
2201
|
const ipaddr = process.env.RPI4_IP;
|
|
2202
|
+
const gatewayip = process.env.GATEWAY_IP;
|
|
1922
2203
|
await updateVirtualRoot({
|
|
1923
2204
|
IP_ADDRESS,
|
|
1924
2205
|
architecture,
|
|
1925
2206
|
host,
|
|
1926
2207
|
nfsHostPath,
|
|
1927
2208
|
ipaddr,
|
|
2209
|
+
update: true,
|
|
2210
|
+
gatewayip,
|
|
1928
2211
|
});
|
|
1929
2212
|
break;
|
|
1930
2213
|
}
|
|
@@ -1934,6 +2217,7 @@ udp-port = 32766
|
|
|
1934
2217
|
const architecture = process.argv[3];
|
|
1935
2218
|
const host = process.argv[4];
|
|
1936
2219
|
const nfsHostPath = `${process.env.NFS_EXPORT_PATH}/${host}`;
|
|
2220
|
+
const gatewayip = process.env.GATEWAY_IP;
|
|
1937
2221
|
shellExec(`sudo dnf install -y iptables-legacy`);
|
|
1938
2222
|
shellExec(`sudo dnf install -y debootstrap`);
|
|
1939
2223
|
shellExec(`sudo dnf install kernel-modules-extra-$(uname -r)`);
|
|
@@ -1963,7 +2247,7 @@ udp-port = 32766
|
|
|
1963
2247
|
`--arch=arm64`,
|
|
1964
2248
|
`--variant=minbase`,
|
|
1965
2249
|
`--foreign`, // arm64 on amd64
|
|
1966
|
-
`noble`,
|
|
2250
|
+
[`noble`, `jammy`][0],
|
|
1967
2251
|
nfsHostPath,
|
|
1968
2252
|
`http://ports.ubuntu.com/ubuntu-ports/`,
|
|
1969
2253
|
];
|
|
@@ -1995,8 +2279,10 @@ EOF`);
|
|
|
1995
2279
|
}
|
|
1996
2280
|
if (process.argv.includes('mount')) {
|
|
1997
2281
|
shellExec(`sudo mount --bind /proc ${nfsHostPath}/proc`);
|
|
1998
|
-
shellExec(`sudo mount --bind /sys
|
|
1999
|
-
shellExec(`sudo mount --rbind /dev
|
|
2282
|
+
shellExec(`sudo mount --bind /sys ${nfsHostPath}/sys`);
|
|
2283
|
+
shellExec(`sudo mount --rbind /dev ${nfsHostPath}/dev`);
|
|
2284
|
+
shellExec(`sudo mount --rbind /dev/pts ${nfsHostPath}/dev/pts`);
|
|
2285
|
+
shellExec(`sudo mount --bind /run ${nfsHostPath}/run`);
|
|
2000
2286
|
}
|
|
2001
2287
|
|
|
2002
2288
|
if (process.argv.includes('build')) {
|
|
@@ -2010,6 +2296,7 @@ EOF`);
|
|
|
2010
2296
|
host,
|
|
2011
2297
|
nfsHostPath,
|
|
2012
2298
|
ipaddr,
|
|
2299
|
+
gatewayip,
|
|
2013
2300
|
});
|
|
2014
2301
|
|
|
2015
2302
|
break;
|
|
@@ -2031,7 +2318,9 @@ EOF`);
|
|
|
2031
2318
|
const nfsHostPath = `${process.env.NFS_EXPORT_PATH}/${host}`;
|
|
2032
2319
|
shellExec(`sudo umount ${nfsHostPath}/proc`);
|
|
2033
2320
|
shellExec(`sudo umount ${nfsHostPath}/sys`);
|
|
2321
|
+
shellExec(`sudo umount ${nfsHostPath}/dev/pts`);
|
|
2034
2322
|
shellExec(`sudo umount ${nfsHostPath}/dev`);
|
|
2323
|
+
shellExec(`sudo umount ${nfsHostPath}/run`);
|
|
2035
2324
|
// shellExec(`sudo umount ${nfsHostPath}/lib/modules`);
|
|
2036
2325
|
break;
|
|
2037
2326
|
}
|
|
@@ -2425,6 +2714,14 @@ nvidia/gpu-operator \
|
|
|
2425
2714
|
// sudo yum install sbt
|
|
2426
2715
|
break;
|
|
2427
2716
|
}
|
|
2717
|
+
|
|
2718
|
+
case 'chrony': {
|
|
2719
|
+
shellExec(`sudo dnf install chrony -y`);
|
|
2720
|
+
// debian chroot: sudo apt install chrony
|
|
2721
|
+
for (const cmd of chronySetUp(`/etc/chrony.conf`)) shellExec(cmd);
|
|
2722
|
+
|
|
2723
|
+
break;
|
|
2724
|
+
}
|
|
2428
2725
|
}
|
|
2429
2726
|
} catch (error) {
|
|
2430
2727
|
logger.error(error, error.stack);
|