underpost 2.8.838 → 2.8.841
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/README.md +8 -2
- package/cli.md +13 -21
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +2 -2
- package/manifests/maas/gpu-diag.sh +19 -0
- package/package.json +1 -1
- package/src/cli/cluster.js +36 -27
- package/src/cli/deploy.js +9 -0
- package/src/cli/index.js +2 -1
- package/src/cli/run.js +82 -36
- package/src/index.js +1 -1
- package/src/runtime/lampp/Dockerfile +30 -39
- package/src/runtime/lampp/Lampp.js +11 -2
- package/src/server/process.js +9 -2
package/README.md
CHANGED
|
@@ -25,10 +25,13 @@ template
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
28
31
|
<!-- badges -->
|
|
29
32
|
|
|
30
33
|
|
|
31
|
-
[](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [](https://www.npmjs.com/package/underpost) [](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [](https://www.npmjs.com/package/underpost) [](https://socket.dev/npm/package/underpost/overview/2.8.841) [](https://coveralls.io/github/underpostnet/engine?branch=master) [](https://www.npmjs.org/package/underpost) [](https://www.npmjs.com/package/underpost)
|
|
32
35
|
|
|
33
36
|
|
|
34
37
|
<!-- end-badges -->
|
|
@@ -36,6 +39,9 @@ template
|
|
|
36
39
|
|
|
37
40
|
|
|
38
41
|
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
39
45
|
</div>
|
|
40
46
|
|
|
41
47
|
<div align="center">
|
|
@@ -80,7 +86,7 @@ Run dev client server
|
|
|
80
86
|
npm run dev
|
|
81
87
|
```
|
|
82
88
|
<!-- -->
|
|
83
|
-
## underpost ci/cd cli v2.8.
|
|
89
|
+
## underpost ci/cd cli v2.8.841
|
|
84
90
|
|
|
85
91
|
### Usage: `underpost [options] [command]`
|
|
86
92
|
```
|
package/cli.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## underpost ci/cd cli v2.8.
|
|
1
|
+
## underpost ci/cd cli v2.8.8411
|
|
2
2
|
|
|
3
3
|
### Usage: `underpost [options] [command]`
|
|
4
4
|
```
|
|
@@ -554,28 +554,20 @@ Options:
|
|
|
554
554
|
Runs a script from the specified path.
|
|
555
555
|
|
|
556
556
|
Arguments:
|
|
557
|
-
runner-id
|
|
558
|
-
|
|
559
|
-
monitor, tf-vae-test, deploy-job.
|
|
560
|
-
path The absolute or relative directory path
|
|
561
|
-
where the script is located.
|
|
557
|
+
runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, gpu-env, tf-gpu-test, ide, monitor, tf-vae-test, deploy-job.
|
|
558
|
+
path The absolute or relative directory path where the script is located.
|
|
562
559
|
|
|
563
560
|
Options:
|
|
564
|
-
--command <command-array>
|
|
565
|
-
--args <args-array>
|
|
566
|
-
--dev
|
|
567
|
-
|
|
568
|
-
--
|
|
569
|
-
|
|
570
|
-
--
|
|
571
|
-
|
|
572
|
-
--
|
|
573
|
-
|
|
574
|
-
--container-name <container-name> Optional: Specifies the container name for
|
|
575
|
-
test execution.
|
|
576
|
-
--namespace <namespace> Optional: Specifies the namespace for test
|
|
577
|
-
execution.
|
|
578
|
-
-h, --help display help for command
|
|
561
|
+
--command <command-array> Array of commands to run.
|
|
562
|
+
--args <args-array> Array of arguments to pass to the command.
|
|
563
|
+
--dev Sets the development context environment for the script.
|
|
564
|
+
--pod-name <pod-name> Optional: Specifies the pod name for test execution.
|
|
565
|
+
--volume-host-path <volume-host-path> Optional: Specifies the volume host path for test execution.
|
|
566
|
+
--volume-mount-path <volume-mount-path> Optional: Specifies the volume mount path for test execution.
|
|
567
|
+
--image-name <image-name> Optional: Specifies the image name for test execution.
|
|
568
|
+
--container-name <container-name> Optional: Specifies the container name for test execution.
|
|
569
|
+
--namespace <namespace> Optional: Specifies the namespace for test execution.
|
|
570
|
+
-h, --help display help for command
|
|
579
571
|
|
|
580
572
|
```
|
|
581
573
|
|
package/docker-compose.yml
CHANGED
|
@@ -17,7 +17,7 @@ spec:
|
|
|
17
17
|
spec:
|
|
18
18
|
containers:
|
|
19
19
|
- name: dd-template-development-blue
|
|
20
|
-
image: localhost/rockylinux9-underpost:v2.8.
|
|
20
|
+
image: localhost/rockylinux9-underpost:v2.8.841
|
|
21
21
|
# resources:
|
|
22
22
|
# requests:
|
|
23
23
|
# memory: "124Ki"
|
|
@@ -100,7 +100,7 @@ spec:
|
|
|
100
100
|
spec:
|
|
101
101
|
containers:
|
|
102
102
|
- name: dd-template-development-green
|
|
103
|
-
image: localhost/rockylinux9-underpost:v2.8.
|
|
103
|
+
image: localhost/rockylinux9-underpost:v2.8.841
|
|
104
104
|
# resources:
|
|
105
105
|
# requests:
|
|
106
106
|
# memory: "124Ki"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# GPUs and drivers in use
|
|
2
|
+
sudo lspci -nnk | egrep -i 'vga|3d' -A3
|
|
3
|
+
|
|
4
|
+
# modules loaded relevant
|
|
5
|
+
lsmod | egrep 'nvidia|nouveau|amdgpu' || true
|
|
6
|
+
|
|
7
|
+
# if exists nvidia tool
|
|
8
|
+
nvidia-smi 2>/dev/null || echo "nvidia-smi no disponible / driver no cargado"
|
|
9
|
+
|
|
10
|
+
# kernel related errors
|
|
11
|
+
sudo dmesg | egrep -i 'nvidia|nouveau|amdgpu' --color=auto
|
|
12
|
+
|
|
13
|
+
# recent system errors / gdm / mutter / X
|
|
14
|
+
sudo journalctl -b -p err --no-pager | head -n 200
|
|
15
|
+
journalctl -b _COMM=gdm --no-pager | tail -n 200
|
|
16
|
+
journalctl -b _COMM=Xorg --no-pager | tail -n 200
|
|
17
|
+
|
|
18
|
+
# X log (if exists)
|
|
19
|
+
sudo grep -E "(EE|WW|NVIDIA|nouveau|amdgpu)" /var/log/Xorg.0.log || true
|
package/package.json
CHANGED
package/src/cli/cluster.js
CHANGED
|
@@ -260,12 +260,12 @@ class UnderpostCluster {
|
|
|
260
260
|
|
|
261
261
|
if (options.full === true || options.valkey === true) {
|
|
262
262
|
if (options.pullImage === true) {
|
|
263
|
-
shellExec(`
|
|
264
|
-
|
|
265
|
-
if (!options.kubeadm && !options.k3s)
|
|
263
|
+
// shellExec(`sudo podman pull valkey/valkey:latest`);
|
|
264
|
+
if (!options.kubeadm && !options.k3s) {
|
|
266
265
|
// Only load if not kubeadm/k3s (Kind needs it)
|
|
266
|
+
shellExec(`docker pull valkey/valkey:latest`);
|
|
267
267
|
shellExec(`sudo kind load docker-image valkey/valkey:latest`);
|
|
268
|
-
else if (options.kubeadm || options.k3s)
|
|
268
|
+
} else if (options.kubeadm || options.k3s)
|
|
269
269
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
270
270
|
shellExec(`sudo crictl pull valkey/valkey:latest`);
|
|
271
271
|
}
|
|
@@ -279,12 +279,12 @@ class UnderpostCluster {
|
|
|
279
279
|
shellExec(`kubectl delete statefulset mariadb-statefulset --ignore-not-found`);
|
|
280
280
|
|
|
281
281
|
if (options.pullImage === true) {
|
|
282
|
-
shellExec(`
|
|
283
|
-
|
|
284
|
-
if (!options.kubeadm && !options.k3s)
|
|
282
|
+
// shellExec(`sudo podman pull mariadb:latest`);
|
|
283
|
+
if (!options.kubeadm && !options.k3s) {
|
|
285
284
|
// Only load if not kubeadm/k3s (Kind needs it)
|
|
285
|
+
shellExec(`docker pull mariadb:latest`);
|
|
286
286
|
shellExec(`sudo kind load docker-image mariadb:latest`);
|
|
287
|
-
else if (options.kubeadm || options.k3s)
|
|
287
|
+
} else if (options.kubeadm || options.k3s)
|
|
288
288
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
289
289
|
shellExec(`sudo crictl pull mariadb:latest`);
|
|
290
290
|
}
|
|
@@ -304,11 +304,11 @@ class UnderpostCluster {
|
|
|
304
304
|
}
|
|
305
305
|
if (options.full === true || options.postgresql === true) {
|
|
306
306
|
if (options.pullImage === true) {
|
|
307
|
-
|
|
308
|
-
if (!options.kubeadm && !options.k3s)
|
|
307
|
+
if (!options.kubeadm && !options.k3s) {
|
|
309
308
|
// Only load if not kubeadm/k3s (Kind needs it)
|
|
309
|
+
shellExec(`docker pull postgres:latest`);
|
|
310
310
|
shellExec(`sudo kind load docker-image postgres:latest`);
|
|
311
|
-
else if (options.kubeadm || options.k3s)
|
|
311
|
+
} else if (options.kubeadm || options.k3s)
|
|
312
312
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
313
313
|
shellExec(`sudo crictl pull postgres:latest`);
|
|
314
314
|
}
|
|
@@ -319,11 +319,11 @@ class UnderpostCluster {
|
|
|
319
319
|
}
|
|
320
320
|
if (options.mongodb4 === true) {
|
|
321
321
|
if (options.pullImage === true) {
|
|
322
|
-
|
|
323
|
-
if (!options.kubeadm && !options.k3s)
|
|
322
|
+
if (!options.kubeadm && !options.k3s) {
|
|
324
323
|
// Only load if not kubeadm/k3s (Kind needs it)
|
|
324
|
+
shellExec(`docker pull mongo:4.4`);
|
|
325
325
|
shellExec(`sudo kind load docker-image mongo:4.4`);
|
|
326
|
-
else if (options.kubeadm || options.k3s)
|
|
326
|
+
} else if (options.kubeadm || options.k3s)
|
|
327
327
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
328
328
|
shellExec(`sudo crictl pull mongo:4.4`);
|
|
329
329
|
}
|
|
@@ -348,11 +348,11 @@ class UnderpostCluster {
|
|
|
348
348
|
}
|
|
349
349
|
} else if (options.full === true || options.mongodb === true) {
|
|
350
350
|
if (options.pullImage === true) {
|
|
351
|
-
|
|
352
|
-
if (!options.kubeadm && !options.k3s)
|
|
351
|
+
if (!options.kubeadm && !options.k3s) {
|
|
353
352
|
// Only load if not kubeadm/k3s (Kind needs it)
|
|
353
|
+
shellExec(`docker pull mongo:latest`);
|
|
354
354
|
shellExec(`sudo kind load docker-image mongo:latest`);
|
|
355
|
-
else if (options.kubeadm || options.k3s)
|
|
355
|
+
} else if (options.kubeadm || options.k3s)
|
|
356
356
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
357
357
|
shellExec(`sudo crictl pull mongo:latest`);
|
|
358
358
|
}
|
|
@@ -425,7 +425,7 @@ class UnderpostCluster {
|
|
|
425
425
|
* @param {string} underpostRoot - The root directory of the underpost project.
|
|
426
426
|
*/
|
|
427
427
|
config(options = { underpostRoot: '.' }) {
|
|
428
|
-
const underpostRoot = options;
|
|
428
|
+
const { underpostRoot } = options;
|
|
429
429
|
console.log('Applying host configuration: SELinux, Docker, Containerd, and Sysctl settings.');
|
|
430
430
|
// Disable SELinux (permissive mode)
|
|
431
431
|
shellExec(`sudo setenforce 0`);
|
|
@@ -460,10 +460,13 @@ class UnderpostCluster {
|
|
|
460
460
|
`/etc/sysctl.d/99-k8s-ipforward.conf`,
|
|
461
461
|
`/etc/sysctl.d/99-k8s.conf`,
|
|
462
462
|
])
|
|
463
|
-
shellExec(
|
|
463
|
+
shellExec(
|
|
464
|
+
`echo 'net.bridge.bridge-nf-call-iptables = 1
|
|
464
465
|
net.bridge.bridge-nf-call-ip6tables = 1
|
|
465
466
|
net.bridge.bridge-nf-call-arptables = 1
|
|
466
|
-
net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}
|
|
467
|
+
net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`,
|
|
468
|
+
{ silent: true },
|
|
469
|
+
);
|
|
467
470
|
// shellExec(`sudo sysctl --system`); // Apply sysctl changes immediately
|
|
468
471
|
// Apply NAT iptables rules.
|
|
469
472
|
shellExec(`${underpostRoot}/manifests/maas/nat-iptables.sh`, { silent: true });
|
|
@@ -519,7 +522,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
|
|
|
519
522
|
|
|
520
523
|
try {
|
|
521
524
|
// Phase 0: Truncate large logs under /var/log to free up immediate space
|
|
522
|
-
logger.info('Phase 0/
|
|
525
|
+
logger.info('Phase 0/7: Truncating large log files under /var/log...');
|
|
523
526
|
try {
|
|
524
527
|
const cleanPath = `/var/log/`;
|
|
525
528
|
const largeLogsFiles = shellExec(
|
|
@@ -540,7 +543,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
|
|
|
540
543
|
|
|
541
544
|
// Phase 1: Clean up Persistent Volumes with hostPath
|
|
542
545
|
// This targets data created by Kubernetes Persistent Volumes that use hostPath.
|
|
543
|
-
logger.info('Phase 1/
|
|
546
|
+
logger.info('Phase 1/7: Cleaning Kubernetes hostPath volumes...');
|
|
544
547
|
try {
|
|
545
548
|
const pvListJson = shellExec(`kubectl get pv -o json || echo '{"items":[]}'`, { stdout: true, silent: true });
|
|
546
549
|
const pvList = JSON.parse(pvListJson);
|
|
@@ -563,7 +566,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
|
|
|
563
566
|
// Phase 2: Restore SELinux and stop services
|
|
564
567
|
// This is critical for fixing the 'permission denied' error you experienced.
|
|
565
568
|
// Enable SELinux permissive mode and restore file contexts.
|
|
566
|
-
logger.info('Phase 2/
|
|
569
|
+
logger.info('Phase 2/7: Stopping services and fixing SELinux...');
|
|
567
570
|
logger.info(' -> Ensuring SELinux is in permissive mode...');
|
|
568
571
|
shellExec(`sudo setenforce 0 || true`);
|
|
569
572
|
shellExec(`sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config || true`);
|
|
@@ -580,7 +583,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
|
|
|
580
583
|
shellExec('sudo umount -f /var/lib/kubelet/pods/*/* || true');
|
|
581
584
|
|
|
582
585
|
// Phase 3: Execute official uninstallation commands
|
|
583
|
-
logger.info('Phase 3/
|
|
586
|
+
logger.info('Phase 3/7: Executing official reset and uninstallation commands...');
|
|
584
587
|
logger.info(' -> Executing kubeadm reset...');
|
|
585
588
|
shellExec('sudo kubeadm reset --force || true');
|
|
586
589
|
logger.info(' -> Executing K3s uninstallation script if it exists...');
|
|
@@ -589,7 +592,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
|
|
|
589
592
|
shellExec('kind get clusters | xargs -r -t -n1 kind delete cluster || true');
|
|
590
593
|
|
|
591
594
|
// Phase 4: File system cleanup
|
|
592
|
-
logger.info('Phase 4/
|
|
595
|
+
logger.info('Phase 4/7: Cleaning up remaining file system artifacts...');
|
|
593
596
|
// Remove any leftover configurations and data.
|
|
594
597
|
shellExec('sudo rm -rf /etc/kubernetes/* || true');
|
|
595
598
|
shellExec('sudo rm -rf /etc/cni/net.d/* || true');
|
|
@@ -602,15 +605,21 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
|
|
|
602
605
|
shellExec('rm -rf $HOME/.kube || true');
|
|
603
606
|
|
|
604
607
|
// Phase 5: Host network cleanup
|
|
605
|
-
logger.info('Phase 5/
|
|
608
|
+
logger.info('Phase 5/7: Cleaning up host network configurations...');
|
|
606
609
|
// Remove iptables rules and CNI network interfaces.
|
|
607
610
|
shellExec('sudo iptables -F || true');
|
|
608
611
|
shellExec('sudo iptables -t nat -F || true');
|
|
612
|
+
// Restore iptables rules
|
|
613
|
+
shellExec(`chmod +x ${options.underpostRoot}/manifests/maas/nat-iptables.sh`);
|
|
614
|
+
shellExec(`${options.underpostRoot}/manifests/maas/nat-iptables.sh`, { silent: true });
|
|
609
615
|
shellExec('sudo ip link del cni0 || true');
|
|
610
616
|
shellExec('sudo ip link del flannel.1 || true');
|
|
611
617
|
|
|
618
|
+
logger.info('Phase 6/7: Clean up images');
|
|
619
|
+
shellExec(`podman rmi $(podman images -qa) --force`);
|
|
620
|
+
|
|
612
621
|
// Phase 6: Reload daemon and finalize
|
|
613
|
-
logger.info('Phase
|
|
622
|
+
logger.info('Phase 7/7: Reloading the system daemon and finalizing...');
|
|
614
623
|
// shellExec('sudo systemctl daemon-reload');
|
|
615
624
|
UnderpostCluster.API.config();
|
|
616
625
|
logger.info('Safe and complete reset finished. The system is ready for a new cluster initialization.');
|
package/src/cli/deploy.js
CHANGED
|
@@ -519,6 +519,15 @@ node bin/deploy build-full-client ${deployId}
|
|
|
519
519
|
logger.error(error, error.stack);
|
|
520
520
|
}
|
|
521
521
|
},
|
|
522
|
+
existsContainerFile({ podName, path }) {
|
|
523
|
+
return JSON.parse(
|
|
524
|
+
shellExec(`kubectl exec ${podName} -- test -f ${path} && echo "true" || echo "false"`, {
|
|
525
|
+
stdout: true,
|
|
526
|
+
disableLog: true,
|
|
527
|
+
silent: true,
|
|
528
|
+
}).trim(),
|
|
529
|
+
);
|
|
530
|
+
},
|
|
522
531
|
};
|
|
523
532
|
}
|
|
524
533
|
|
package/src/cli/index.js
CHANGED
|
@@ -324,7 +324,8 @@ program
|
|
|
324
324
|
.option('--args <args-array>', 'Array of arguments to pass to the command.')
|
|
325
325
|
.option('--dev', 'Sets the development context environment for the script.')
|
|
326
326
|
.option('--pod-name <pod-name>', 'Optional: Specifies the pod name for test execution.')
|
|
327
|
-
.option('--volume-
|
|
327
|
+
.option('--volume-host-path <volume-host-path>', 'Optional: Specifies the volume host path for test execution.')
|
|
328
|
+
.option('--volume-mount-path <volume-mount-path>', 'Optional: Specifies the volume mount path for test execution.')
|
|
328
329
|
.option('--image-name <image-name>', 'Optional: Specifies the image name for test execution.')
|
|
329
330
|
.option('--container-name <container-name>', 'Optional: Specifies the container name for test execution.')
|
|
330
331
|
.option('--namespace <namespace>', 'Optional: Specifies the namespace for test execution.')
|
package/src/cli/run.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
|
|
1
|
+
import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
|
|
2
2
|
import read from 'read';
|
|
3
3
|
import { getNpmRootPath } from '../server/conf.js';
|
|
4
4
|
import { loggerFactory } from '../server/logger.js';
|
|
5
5
|
import UnderpostTest from './test.js';
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
|
-
import { timer } from '../client/components/core/CommonJs.js';
|
|
7
|
+
import { range, setPad, timer } from '../client/components/core/CommonJs.js';
|
|
8
|
+
import UnderpostDeploy from './deploy.js';
|
|
9
|
+
import UnderpostRootEnv from './env.js';
|
|
8
10
|
|
|
9
11
|
const logger = loggerFactory(import.meta);
|
|
10
12
|
|
|
@@ -12,7 +14,8 @@ class UnderpostRun {
|
|
|
12
14
|
static DEFAULT_OPTION = {
|
|
13
15
|
dev: false,
|
|
14
16
|
podName: '',
|
|
15
|
-
|
|
17
|
+
volumeHostPath: '',
|
|
18
|
+
volumeMountPath: '',
|
|
16
19
|
imageName: '',
|
|
17
20
|
containerName: '',
|
|
18
21
|
namespace: '',
|
|
@@ -38,6 +41,19 @@ class UnderpostRun {
|
|
|
38
41
|
|
|
39
42
|
shellCd('/home/dd/engine');
|
|
40
43
|
},
|
|
44
|
+
rmi: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
45
|
+
shellExec(`podman rmi $(podman images -qa) --force`);
|
|
46
|
+
},
|
|
47
|
+
kill: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
48
|
+
shellExec(`sudo kill -9 $(lsof -t -i:${path})`);
|
|
49
|
+
},
|
|
50
|
+
secret: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
51
|
+
shellExec(
|
|
52
|
+
`underpost secret underpost --create-from-file ${
|
|
53
|
+
path ? path : `/home/dd/engine/engine-private/conf/dd-cron/.env.production`
|
|
54
|
+
}`,
|
|
55
|
+
);
|
|
56
|
+
},
|
|
41
57
|
'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
42
58
|
shellExec(
|
|
43
59
|
`node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
|
|
@@ -58,13 +74,7 @@ class UnderpostRun {
|
|
|
58
74
|
logger.info('monitor pid', pid);
|
|
59
75
|
const checkPath = '/await';
|
|
60
76
|
const _monitor = async () => {
|
|
61
|
-
const result =
|
|
62
|
-
shellExec(`kubectl exec ${path} -- test -f ${checkPath} && echo "true" || echo "false"`, {
|
|
63
|
-
stdout: true,
|
|
64
|
-
disableLog: true,
|
|
65
|
-
silent: true,
|
|
66
|
-
}).trim(),
|
|
67
|
-
);
|
|
77
|
+
const result = UnderpostDeploy.API.existsContainerFile({ podName: path, path: checkPath });
|
|
68
78
|
logger.info('monitor', result);
|
|
69
79
|
if (result === true) {
|
|
70
80
|
switch (path) {
|
|
@@ -74,21 +84,21 @@ class UnderpostRun {
|
|
|
74
84
|
const podName = path;
|
|
75
85
|
const basePath = '/home/dd';
|
|
76
86
|
const scriptPath = '/site/en/tutorials/generative/cvae.py';
|
|
77
|
-
shellExec(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
82
|
-
const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
|
|
83
|
-
fs.writeFileSync(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
print('=== SCRIPT UPDATE TEST ===')`,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
);
|
|
87
|
+
// shellExec(
|
|
88
|
+
// `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
|
|
89
|
+
// .split('/')
|
|
90
|
+
// .pop()}`,
|
|
91
|
+
// );
|
|
92
|
+
// const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
|
|
93
|
+
// fs.writeFileSync(
|
|
94
|
+
// `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
|
|
95
|
+
// file.replace(
|
|
96
|
+
// `import time`,
|
|
97
|
+
// `import time
|
|
98
|
+
// print('=== SCRIPT UPDATE TEST ===')`,
|
|
99
|
+
// ),
|
|
100
|
+
// 'utf8',
|
|
101
|
+
// );
|
|
92
102
|
shellExec(
|
|
93
103
|
`sudo kubectl cp ${basePath}/lab/src/${scriptPath
|
|
94
104
|
.split('/')
|
|
@@ -96,6 +106,28 @@ print('=== SCRIPT UPDATE TEST ===')`,
|
|
|
96
106
|
);
|
|
97
107
|
// shellExec(`sudo kubectl exec -i ${podName} -- sh -c "ipython ${basePath}/docs${scriptPath}"`);
|
|
98
108
|
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkPath}"`);
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
const checkPath = `/latent_space_plot.png`;
|
|
112
|
+
const outsPaths = [];
|
|
113
|
+
logger.info('monitor', checkPath);
|
|
114
|
+
while (!UnderpostDeploy.API.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
|
|
115
|
+
await timer(1000);
|
|
116
|
+
|
|
117
|
+
{
|
|
118
|
+
const toPath = `${basePath}/lab${checkPath}`;
|
|
119
|
+
outsPaths.push(toPath);
|
|
120
|
+
shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (let i of range(1, 10)) {
|
|
124
|
+
i = `/image_at_epoch_${setPad(i, '0', 4)}.png`;
|
|
125
|
+
const toPath = `${basePath}/lab/${i}`;
|
|
126
|
+
outsPaths.push(toPath);
|
|
127
|
+
shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${i} ${toPath}`);
|
|
128
|
+
}
|
|
129
|
+
openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
|
|
130
|
+
}
|
|
99
131
|
shellExec(`sudo kill -9 ${pid}`);
|
|
100
132
|
}
|
|
101
133
|
break;
|
|
@@ -115,6 +147,8 @@ print('=== SCRIPT UPDATE TEST ===')`,
|
|
|
115
147
|
const podName = 'tf-vae-test';
|
|
116
148
|
await UnderpostRun.RUNNERS['deploy-job']('', {
|
|
117
149
|
podName,
|
|
150
|
+
// volumeMountPath: '/custom_images',
|
|
151
|
+
// volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
|
|
118
152
|
on: {
|
|
119
153
|
init: async () => {
|
|
120
154
|
openTerminal(`node bin run --dev monitor ${podName}`);
|
|
@@ -136,20 +170,29 @@ print('=== SCRIPT UPDATE TEST ===')`,
|
|
|
136
170
|
`echo '' > /await`,
|
|
137
171
|
`echo '=== WAITING SCRIPT LAUNCH ==='`,
|
|
138
172
|
`while [ -f /await ]; do sleep 1; done`,
|
|
139
|
-
`ipython site/en/tutorials/generative/cvae.py`,
|
|
140
173
|
`echo '=== FINISHED ==='`,
|
|
174
|
+
daemonProcess(`ipython site/en/tutorials/generative/cvae.py`),
|
|
141
175
|
],
|
|
142
176
|
});
|
|
143
177
|
},
|
|
144
178
|
'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
145
179
|
const podName = options.podName || 'deploy-job';
|
|
146
|
-
const volumeName =
|
|
180
|
+
const volumeName = `${podName}-volume`;
|
|
147
181
|
const args = (options.args ? options.args : path ? [`python ${path}`] : []).filter((c) => c.trim());
|
|
148
182
|
const imageName = options.imageName || 'nvcr.io/nvidia/tensorflow:24.04-tf2-py3';
|
|
149
183
|
const containerName = options.containerName || `${podName}-container`;
|
|
150
184
|
const gpuEnable = imageName.match('nvidia');
|
|
151
185
|
const runtimeClassName = gpuEnable ? 'nvidia' : '';
|
|
152
186
|
const namespace = options.namespace || 'default';
|
|
187
|
+
const volumeMountPath = options.volumeMountPath || path;
|
|
188
|
+
const volumeHostPath = options.volumeHostPath || path;
|
|
189
|
+
const enableVolumeMount = volumeHostPath && volumeMountPath;
|
|
190
|
+
|
|
191
|
+
if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
|
|
192
|
+
const volumeType =
|
|
193
|
+
options.volumeType || (enableVolumeMount && fs.statSync(volumeHostPath).isDirectory()) ? 'Directory' : 'File';
|
|
194
|
+
|
|
195
|
+
const envs = UnderpostRootEnv.API.list();
|
|
153
196
|
|
|
154
197
|
const cmd = `kubectl apply -f - <<EOF
|
|
155
198
|
apiVersion: v1
|
|
@@ -174,27 +217,30 @@ ${
|
|
|
174
217
|
${args.map((arg) => ` ${arg}`).join('\n')}`
|
|
175
218
|
: ''
|
|
176
219
|
}
|
|
177
|
-
${
|
|
220
|
+
${`${
|
|
178
221
|
gpuEnable
|
|
179
222
|
? ` resources:
|
|
180
223
|
limits:
|
|
181
224
|
nvidia.com/gpu: '1'
|
|
182
|
-
|
|
183
|
-
- name: NVIDIA_VISIBLE_DEVICES
|
|
184
|
-
value: all`
|
|
225
|
+
`
|
|
185
226
|
: ''
|
|
186
|
-
}
|
|
227
|
+
} env:
|
|
228
|
+
${Object.keys(envs)
|
|
229
|
+
.map((key) => ({ key, value: typeof envs[key] === 'number' ? envs[key] : `"${envs[key]}"` }))
|
|
230
|
+
.concat(gpuEnable ? [{ key: 'NVIDIA_VISIBLE_DEVICES', value: 'all' }] : [])
|
|
231
|
+
.map((env) => ` - name: ${env.key}\n value: ${env.value}`)
|
|
232
|
+
.join('\n')}`}
|
|
187
233
|
${
|
|
188
|
-
|
|
234
|
+
enableVolumeMount
|
|
189
235
|
? `
|
|
190
236
|
volumeMounts:
|
|
191
237
|
- name: ${volumeName}
|
|
192
|
-
mountPath: ${
|
|
238
|
+
mountPath: ${volumeMountPath}
|
|
193
239
|
volumes:
|
|
194
240
|
- name: ${volumeName}
|
|
195
241
|
hostPath:
|
|
196
|
-
path: ${
|
|
197
|
-
type: ${
|
|
242
|
+
path: ${volumeHostPath}
|
|
243
|
+
type: ${volumeType}`
|
|
198
244
|
: ''
|
|
199
245
|
}
|
|
200
246
|
EOF`;
|
package/src/index.js
CHANGED
|
@@ -1,43 +1,35 @@
|
|
|
1
1
|
FROM rockylinux:9
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
RUN sed -i.bak 's/display_errors=Off/display_errors=On/g' /opt/lampp/etc/php.ini
|
|
34
|
-
# Enable includes of several configuration files for Apache
|
|
35
|
-
RUN mkdir -p /opt/lampp/apache2/conf.d
|
|
36
|
-
RUN echo "IncludeOptional /opt/lampp/apache2/conf.d/*.conf" >>/opt/lampp/etc/httpd.conf
|
|
37
|
-
# Create a /www folder and a symbolic link to it in /opt/lampp/htdocs
|
|
38
|
-
# This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools
|
|
39
|
-
RUN mkdir /www
|
|
40
|
-
RUN ln -s /www /opt/lampp/htdocs
|
|
3
|
+
# --- Update and install required packages
|
|
4
|
+
RUN dnf -y update && \
|
|
5
|
+
dnf -y install epel-release && \
|
|
6
|
+
dnf -y install --allowerasing \
|
|
7
|
+
bzip2 \
|
|
8
|
+
sudo \
|
|
9
|
+
curl \
|
|
10
|
+
net-tools \
|
|
11
|
+
openssh-server \
|
|
12
|
+
nano \
|
|
13
|
+
vim-enhanced \
|
|
14
|
+
less \
|
|
15
|
+
openssl-devel \
|
|
16
|
+
wget \
|
|
17
|
+
git \
|
|
18
|
+
gnupg2 \
|
|
19
|
+
libnsl \
|
|
20
|
+
perl && \
|
|
21
|
+
dnf clean all
|
|
22
|
+
|
|
23
|
+
# --- Download and install XAMPP
|
|
24
|
+
RUN curl -L -o /tmp/xampp-linux-installer.run "https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run" && \
|
|
25
|
+
chmod +x /tmp/xampp-linux-installer.run && \
|
|
26
|
+
bash -c "/tmp/xampp-linux-installer.run --mode unattended" && \
|
|
27
|
+
ln -sf /opt/lampp/lampp /usr/bin/lampp
|
|
28
|
+
|
|
29
|
+
# --- Create /xampp/htdocs (static root) and set permissions
|
|
30
|
+
RUN mkdir -p /opt/lampp/htdocs && \
|
|
31
|
+
chown -R root:root /opt/lampp/htdocs && \
|
|
32
|
+
chmod -R a+rX /opt/lampp/htdocs
|
|
41
33
|
|
|
42
34
|
# Install Node.js
|
|
43
35
|
RUN curl -fsSL https://rpm.nodesource.com/setup_23.x | bash -
|
|
@@ -51,7 +43,6 @@ RUN npm --version
|
|
|
51
43
|
# Set working directory
|
|
52
44
|
WORKDIR /home/dd
|
|
53
45
|
|
|
54
|
-
# Expose necessary ports
|
|
55
46
|
EXPOSE 22
|
|
56
47
|
EXPOSE 80
|
|
57
48
|
EXPOSE 443
|
|
@@ -10,7 +10,16 @@ const Lampp = {
|
|
|
10
10
|
initService: async function (options = { daemon: false }) {
|
|
11
11
|
let cmd;
|
|
12
12
|
// linux
|
|
13
|
-
|
|
13
|
+
// /opt/lampp/apache2/conf/httpd.conf
|
|
14
|
+
fs.writeFileSync(`/opt/lampp/etc/extra/httpd-vhosts.conf`, this.router || '', 'utf8');
|
|
15
|
+
fs.writeFileSync(
|
|
16
|
+
`/opt/lampp/etc/httpd.conf`,
|
|
17
|
+
fs
|
|
18
|
+
.readFileSync(`/opt/lampp/etc/httpd.conf`, 'utf8')
|
|
19
|
+
.replace(`#Include etc/extra/httpd-vhosts.conf`, `Include etc/extra/httpd-vhosts.conf`),
|
|
20
|
+
'utf8',
|
|
21
|
+
);
|
|
22
|
+
|
|
14
23
|
cmd = `sudo /opt/lampp/lampp stop`;
|
|
15
24
|
if (!fs.readFileSync(`/opt/lampp/etc/httpd.conf`, 'utf8').match(`# Listen 80`))
|
|
16
25
|
fs.writeFileSync(
|
|
@@ -42,7 +51,7 @@ const Lampp = {
|
|
|
42
51
|
if (this.router) fs.writeFileSync(`./tmp/lampp-router.conf`, this.router, 'utf-8');
|
|
43
52
|
shellExec(cmd);
|
|
44
53
|
},
|
|
45
|
-
enabled: () => fs.existsSync(`/opt/lampp/
|
|
54
|
+
enabled: () => fs.existsSync(`/opt/lampp/etc/httpd.conf`),
|
|
46
55
|
appendRouter: function (render) {
|
|
47
56
|
if (!this.router) {
|
|
48
57
|
if (fs.existsSync(`./tmp/lampp-router.conf`))
|
package/src/server/process.js
CHANGED
|
@@ -61,11 +61,18 @@ const shellCd = (cd, options = { disableLog: false }) => {
|
|
|
61
61
|
return shell.cd(cd);
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
const openTerminal = (cmd) =>
|
|
64
|
+
const openTerminal = (cmd, options = { single: false }) => {
|
|
65
|
+
if (options.single === true) {
|
|
66
|
+
shellExec(`setsid gnome-terminal -- bash -ic "${cmd}; exec bash" >/dev/null 2>&1 &`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
65
69
|
shellExec(`gnome-terminal -- bash -c "${cmd}; exec bash" & disown`, {
|
|
66
70
|
async: true,
|
|
67
71
|
stdout: true,
|
|
68
72
|
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const daemonProcess = (cmd) => `exec bash -c '${cmd}; exec tail -f /dev/null'`;
|
|
69
76
|
|
|
70
77
|
// list all terminals: pgrep gnome-terminal
|
|
71
78
|
// list last terminal: pgrep -n gnome-terminal
|
|
@@ -76,4 +83,4 @@ function pbcopy(data) {
|
|
|
76
83
|
logger.info(`copied to clipboard`, clipboard.readSync());
|
|
77
84
|
}
|
|
78
85
|
|
|
79
|
-
export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, openTerminal, getTerminalPid };
|
|
86
|
+
export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, openTerminal, getTerminalPid, daemonProcess };
|