From 457e58e73030328a250b04ad7fc73abcccd21a41 Mon Sep 17 00:00:00 2001 From: Rui Gao Date: Thu, 23 Jul 2026 08:29:53 +0000 Subject: [PATCH 1/4] chore: upgrade Python 3.10 to 3.12 in Dockerfiles Python 3.10 reaches EOL October 2026. Upgrade to 3.12 (EOL October 2028) for openpai-runtime, postgresql-sdk, cluster-utilization, and cert-expiration-checker. Co-Authored-By: Claude --- .../build/cert-expiration-checker.common.dockerfile | 2 +- src/alert-manager/build/cluster-utilization.common.dockerfile | 2 +- src/openpai-runtime/build/openpai-runtime.common.dockerfile | 2 +- src/postgresql-sdk/build/postgresql-sdk.k8s.dockerfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/alert-manager/build/cert-expiration-checker.common.dockerfile b/src/alert-manager/build/cert-expiration-checker.common.dockerfile index 4c2ca3ef..3ec6f9c8 100644 --- a/src/alert-manager/build/cert-expiration-checker.common.dockerfile +++ b/src/alert-manager/build/cert-expiration-checker.common.dockerfile @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -FROM python:3.10-slim +FROM python:3.12-slim RUN apt-get update && apt-get upgrade -y && \ apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/src/alert-manager/build/cluster-utilization.common.dockerfile b/src/alert-manager/build/cluster-utilization.common.dockerfile index 76634926..b95013db 100644 --- a/src/alert-manager/build/cluster-utilization.common.dockerfile +++ b/src/alert-manager/build/cluster-utilization.common.dockerfile @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -FROM python:3.10-slim +FROM python:3.12-slim RUN apt-get update && apt-get upgrade -y && \ apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/src/openpai-runtime/build/openpai-runtime.common.dockerfile b/src/openpai-runtime/build/openpai-runtime.common.dockerfile index 32c7d355..dd9b5578 100644 --- a/src/openpai-runtime/build/openpai-runtime.common.dockerfile +++ b/src/openpai-runtime/build/openpai-runtime.common.dockerfile @@ -67,7 +67,7 @@ COPY src/frameworkcontroller ${PROJECT_DIR} RUN ${PROJECT_DIR}/build/frameworkbarrier/go-build.sh && \ mv ${PROJECT_DIR}/dist/frameworkbarrier/* ${INSTALL_DIR} -FROM python:3.10-alpine +FROM python:3.12-alpine RUN mkdir -p /opt/package_cache COPY --from=ubuntu_20_04_cache /package_cache /opt/package_cache/ diff --git a/src/postgresql-sdk/build/postgresql-sdk.k8s.dockerfile b/src/postgresql-sdk/build/postgresql-sdk.k8s.dockerfile index 878e10c3..85c4a6f5 100644 --- a/src/postgresql-sdk/build/postgresql-sdk.k8s.dockerfile +++ b/src/postgresql-sdk/build/postgresql-sdk.k8s.dockerfile @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -FROM python:3.10-slim +FROM python:3.12-slim # Install system dependencies RUN apt-get update && \ From 7bcd8429deb0eb6582cb0910dc7821d83e04b7f6 Mon Sep 17 00:00:00 2001 From: Rui Gao Date: Fri, 24 Jul 2026 01:11:43 +0000 Subject: [PATCH 2/4] chore: upgrade Node.js 20 to 24 across all services Node.js 20 reached EOL March 2026. Upgrade to Node 24 (current LTS) for rest-server, database-controller, alert-handler, job-status-change-notification, and grafana. - Replace native `diskusage` package with built-in `fs.statfs()` in database-controller to eliminate unmaintained native addon dependency - Restore `npm install -g npm@latest` (Node 24 supports npm 12+) - Update engines field to ^24 in package.json files - Regenerate yarn.lock files under Node 24 - Add `corepack enable` for grafana plugin build Co-Authored-By: Claude --- .../build/alert-handler.common.dockerfile | 6 +++--- ...tatus-change-notification.common.dockerfile | 6 +++--- .../src/alert-handler/package.json | 2 +- .../package.json | 2 +- .../database-controller.common.dockerfile | 6 +++--- src/database-controller/src/package.json | 1 - .../src/watcher/cluster-event/index.js | 6 ++++-- src/database-controller/src/yarn.lock | 18 ------------------ src/grafana/build/grafana.common.dockerfile | 4 ++-- .../build/rest-server.common.dockerfile | 6 +++--- src/rest-server/package.json | 2 +- src/rest-server/yarn.lock | 4 ++-- 12 files changed, 23 insertions(+), 40 deletions(-) diff --git a/src/alert-manager/build/alert-handler.common.dockerfile b/src/alert-manager/build/alert-handler.common.dockerfile index 20e316b9..3fed5900 100755 --- a/src/alert-manager/build/alert-handler.common.dockerfile +++ b/src/alert-manager/build/alert-handler.common.dockerfile @@ -2,9 +2,9 @@ # Licensed under the MIT License. # Build stage -FROM node:20 AS builder +FROM node:24 AS builder -RUN npm install -g npm@11 +RUN npm install -g npm@latest WORKDIR /usr/src/app @@ -19,7 +19,7 @@ RUN for dep in $(node -pe "Object.keys(require('./package.json').devDependencies COPY ./src/alert-handler . # Production stage - use slim image -FROM node:20-slim +FROM node:24-slim WORKDIR /usr/src/app diff --git a/src/alert-manager/build/job-status-change-notification.common.dockerfile b/src/alert-manager/build/job-status-change-notification.common.dockerfile index a8b268ce..33239507 100644 --- a/src/alert-manager/build/job-status-change-notification.common.dockerfile +++ b/src/alert-manager/build/job-status-change-notification.common.dockerfile @@ -2,9 +2,9 @@ # Licensed under the MIT License. # Build stage -FROM node:20 AS builder +FROM node:24 AS builder -RUN npm install -g npm@11 +RUN npm install -g npm@latest WORKDIR /usr/src/app @@ -25,7 +25,7 @@ COPY ./src/job-status-change-notification . RUN rm -rf openpaidbsdk/node_modules # Production stage - use slim image -FROM node:20-slim +FROM node:24-slim WORKDIR /usr/src/app diff --git a/src/alert-manager/src/alert-handler/package.json b/src/alert-manager/src/alert-handler/package.json index 5b734edc..4daeb9ab 100644 --- a/src/alert-manager/src/alert-handler/package.json +++ b/src/alert-manager/src/alert-handler/package.json @@ -17,7 +17,7 @@ "url": "https://github.com/Microsoft/pai/issues" }, "engines": { - "node": "^20" + "node": "^24" }, "_moduleAliases": { "@alert-handler": "." diff --git a/src/alert-manager/src/job-status-change-notification/package.json b/src/alert-manager/src/job-status-change-notification/package.json index 63f5b1e1..e5054702 100644 --- a/src/alert-manager/src/job-status-change-notification/package.json +++ b/src/alert-manager/src/job-status-change-notification/package.json @@ -17,7 +17,7 @@ "url": "https://github.com/Microsoft/pai/issues" }, "engines": { - "node": "^20" + "node": "^24" }, "_moduleAliases": { "@job-status-change-notification": "." diff --git a/src/database-controller/build/database-controller.common.dockerfile b/src/database-controller/build/database-controller.common.dockerfile index dcee9d5b..85576707 100644 --- a/src/database-controller/build/database-controller.common.dockerfile +++ b/src/database-controller/build/database-controller.common.dockerfile @@ -2,9 +2,9 @@ # Licensed under the MIT License. # Build stage -FROM node:20 AS builder +FROM node:24 AS builder -RUN npm install -g npm@11 +RUN npm install -g npm@latest WORKDIR /database-controller @@ -23,7 +23,7 @@ RUN json -I -f package.json -e "this.paiVersion=\"`cat ../version/PAI.VERSION`\" RUN json -I -f package.json -e "this.paiCommitVersion=\"`cat ../version/COMMIT.VERSION`\"" # Production stage - use slim image -FROM node:20-slim +FROM node:24-slim WORKDIR /database-controller/src diff --git a/src/database-controller/src/package.json b/src/database-controller/src/package.json index 01081ebf..07f39edc 100644 --- a/src/database-controller/src/package.json +++ b/src/database-controller/src/package.json @@ -15,7 +15,6 @@ "body-parser": "^2.2.1", "compression": "^1.8.0", "cors": "^2.8.5", - "diskusage": "^1.2.0", "dotenv": "^16.5.0", "express": "^5.2.0", "http-errors": "^2.0.0", diff --git a/src/database-controller/src/watcher/cluster-event/index.js b/src/database-controller/src/watcher/cluster-event/index.js index 361281d5..67b374f5 100644 --- a/src/database-controller/src/watcher/cluster-event/index.js +++ b/src/database-controller/src/watcher/cluster-event/index.js @@ -12,7 +12,7 @@ require('@dbc/common/init'); const logger = require('@dbc/common/logger'); const { getEventInformer } = require('@dbc/common/k8s'); const { alwaysRetryDecorator } = require('@dbc/common/util'); -const disk = require('diskusage'); +const { statfs } = require('fs/promises'); const config = require('@dbc/watcher/cluster-event/config'); // Here, we use AsyncLock to control the concurrency of events with the same uid; @@ -85,7 +85,9 @@ const eventHandler = (eventType, apiObject) => { async function assertDiskUsageHealthy() { try { - const { available, total } = await disk.check(config.diskPath); + const stats = await statfs(config.diskPath); + const available = stats.bavail * stats.bsize; + const total = stats.blocks * stats.bsize; const currentUsage = ((total - available) / total) * 100; logger.info(`Current internal storage usage is ${currentUsage}% .`); if (currentUsage > config.maxDiskUsagePercent) { diff --git a/src/database-controller/src/yarn.lock b/src/database-controller/src/yarn.lock index 3a3b6c10..1d2e9d85 100644 --- a/src/database-controller/src/yarn.lock +++ b/src/database-controller/src/yarn.lock @@ -730,14 +730,6 @@ depd@^2.0.0, depd@~2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -diskusage@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/diskusage/-/diskusage-1.2.0.tgz#3e8ae42333d5d7e0c7d93e055d7fea9ea841bc88" - integrity sha512-2u3OG3xuf5MFyzc4MctNRUKjjwK+UkovRYdD2ed/NZNZPrt0lqHnLKxGhlFVvAb4/oufIgQG3nWgwmeTbHOvXA== - dependencies: - es6-promise "^4.2.8" - nan "^2.18.0" - doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -897,11 +889,6 @@ es-to-primitive@^1.3.0: is-date-object "^1.1.0" is-symbol "^1.1.1" -es6-promise@^4.2.8: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - escape-html@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -1861,11 +1848,6 @@ ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nan@^2.18.0: - version "2.28.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.28.0.tgz#126717fd359d5a03d3edf7c44e6ce9b707fb57f5" - integrity sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" diff --git a/src/grafana/build/grafana.common.dockerfile b/src/grafana/build/grafana.common.dockerfile index fdff7121..82ab4238 100644 --- a/src/grafana/build/grafana.common.dockerfile +++ b/src/grafana/build/grafana.common.dockerfile @@ -14,7 +14,7 @@ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -FROM node:20 AS build +FROM node:24 AS build ARG TARGETOS ARG TARGETARCH @@ -35,7 +35,7 @@ RUN git clone --branch ${PLUGINVERSION} --depth 1 https://github.com/grafana/gra RUN go install github.com/magefile/mage@latest -RUN yarn && yarn build +RUN corepack enable && yarn && yarn build RUN if [ "$TARGETARCH" = "amd64" ]; then \ mage build:linux; \ diff --git a/src/rest-server/build/rest-server.common.dockerfile b/src/rest-server/build/rest-server.common.dockerfile index 1d27126a..0c1de38d 100644 --- a/src/rest-server/build/rest-server.common.dockerfile +++ b/src/rest-server/build/rest-server.common.dockerfile @@ -16,9 +16,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Build stage -FROM node:20 AS builder +FROM node:24 AS builder -RUN npm install -g npm@11 +RUN npm install -g npm@latest WORKDIR /usr/src/app @@ -38,7 +38,7 @@ RUN for dep in $(node -pe "Object.keys(require('./package.json').devDependencies done # Production stage - use slim image -FROM node:20-slim +FROM node:24-slim WORKDIR /usr/src/app diff --git a/src/rest-server/package.json b/src/rest-server/package.json index c33be33e..239f5f06 100644 --- a/src/rest-server/package.json +++ b/src/rest-server/package.json @@ -22,7 +22,7 @@ "url": "https://github.com/Microsoft/pai/issues" }, "engines": { - "node": "^20" + "node": "^24" }, "dependencies": { "@azure/storage-blob": "^12.27.0", diff --git a/src/rest-server/yarn.lock b/src/rest-server/yarn.lock index 948fd324..3c7ebad8 100644 --- a/src/rest-server/yarn.lock +++ b/src/rest-server/yarn.lock @@ -4302,11 +4302,11 @@ __metadata: "openpaidbsdk@file:./openpaidbsdk::locator=pai-rest-server%40workspace%3A.": version: 1.0.2 - resolution: "openpaidbsdk@file:./openpaidbsdk#./openpaidbsdk::hash=9a36d0&locator=pai-rest-server%40workspace%3A." + resolution: "openpaidbsdk@file:./openpaidbsdk#./openpaidbsdk::hash=e146c8&locator=pai-rest-server%40workspace%3A." dependencies: pg: "npm:^8.15.6" sequelize: "npm:6.37.8" - checksum: 10c0/59e6c0f200a02f4e312e220d845b1daeaa2fa96cf089876c6a76f10375a20650ac4b66c60c1b9317ae61b0d62e7b9a1dd21cbb0016df11549d9cc8a276997a07 + checksum: 10c0/e40aa120c1c2bcf0236ffe40fad7f5a0d7ce0d4e6dadd5c968b390d4e143cddae6b4db029080cbb6ff7c8075781ffe7c9c6b97b0161ffe2b97284aac96619887 languageName: node linkType: hard From fb9e21e7a23436f2fead2ecbb2e8bf9fd61e215d Mon Sep 17 00:00:00 2001 From: Rui Gao Date: Fri, 24 Jul 2026 01:24:52 +0000 Subject: [PATCH 3/4] chore: replace Ubuntu 20.04 with 24.04 in openpai-runtime package cache Ubuntu 20.04 reached EOL April 2025. Replace with 24.04 while keeping 22.04 for existing user jobs. Co-Authored-By: Claude --- .../build/openpai-runtime.common.dockerfile | 10 +++++----- .../src/src/package_cache/package_cache_info | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/openpai-runtime/build/openpai-runtime.common.dockerfile b/src/openpai-runtime/build/openpai-runtime.common.dockerfile index dd9b5578..e6ae2e02 100644 --- a/src/openpai-runtime/build/openpai-runtime.common.dockerfile +++ b/src/openpai-runtime/build/openpai-runtime.common.dockerfile @@ -17,20 +17,20 @@ # Package Cache Data Layer Starts -FROM ubuntu:20.04 AS ubuntu_20_04_cache +FROM ubuntu:22.04 AS ubuntu_22_04_cache WORKDIR /src COPY src/src/package_cache ./ RUN chmod -R +x ./ -RUN /bin/bash ubuntu_build.sh package_cache_info ubuntu20.04 +RUN /bin/bash ubuntu_build.sh package_cache_info ubuntu22.04 -FROM ubuntu:22.04 AS ubuntu_22_04_cache +FROM ubuntu:24.04 AS ubuntu_24_04_cache WORKDIR /src COPY src/src/package_cache ./ RUN chmod -R +x ./ -RUN /bin/bash ubuntu_build.sh package_cache_info ubuntu22.04 +RUN /bin/bash ubuntu_build.sh package_cache_info ubuntu24.04 # Package Cache Data Layer Ends @@ -70,8 +70,8 @@ RUN ${PROJECT_DIR}/build/frameworkbarrier/go-build.sh && \ FROM python:3.12-alpine RUN mkdir -p /opt/package_cache -COPY --from=ubuntu_20_04_cache /package_cache /opt/package_cache/ COPY --from=ubuntu_22_04_cache /package_cache /opt/package_cache/ +COPY --from=ubuntu_24_04_cache /package_cache /opt/package_cache/ ENV INSTALL_DIR=/opt/kube-runtime ARG BARRIER_DIR=/opt/frameworkcontroller/frameworkbarrier diff --git a/src/openpai-runtime/src/src/package_cache/package_cache_info b/src/openpai-runtime/src/src/package_cache/package_cache_info index 53105eb5..dfe665a4 100644 --- a/src/openpai-runtime/src/src/package_cache/package_cache_info +++ b/src/openpai-runtime/src/src/package_cache/package_cache_info @@ -1,10 +1,10 @@ # group_name, os, packages(space-gapped) # "#" can be used for comments -ssh,ubuntu20.04,openssh-client openssh-server ssh,ubuntu22.04,openssh-client openssh-server -nfs,ubuntu20.04,nfs-common +ssh,ubuntu24.04,openssh-client openssh-server nfs,ubuntu22.04,nfs-common -samba,ubuntu20.04,cifs-utils +nfs,ubuntu24.04,nfs-common samba,ubuntu22.04,cifs-utils -azurefile,ubuntu20.04,cifs-utils sshpass +samba,ubuntu24.04,cifs-utils azurefile,ubuntu22.04,cifs-utils sshpass +azurefile,ubuntu24.04,cifs-utils sshpass From dd549c53ae142c1455047a831fcd7847c81620c2 Mon Sep 17 00:00:00 2001 From: Rui Gao Date: Fri, 24 Jul 2026 03:20:45 +0000 Subject: [PATCH 4/4] fix: use frsize instead of bsize for statfs block size calculation POSIX defines blocks/bavail in units of frsize (fundamental block size), not bsize (optimal transfer size). They differ on some filesystems. Co-Authored-By: Claude --- src/database-controller/src/watcher/cluster-event/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/database-controller/src/watcher/cluster-event/index.js b/src/database-controller/src/watcher/cluster-event/index.js index 67b374f5..473aeac8 100644 --- a/src/database-controller/src/watcher/cluster-event/index.js +++ b/src/database-controller/src/watcher/cluster-event/index.js @@ -86,8 +86,9 @@ const eventHandler = (eventType, apiObject) => { async function assertDiskUsageHealthy() { try { const stats = await statfs(config.diskPath); - const available = stats.bavail * stats.bsize; - const total = stats.blocks * stats.bsize; + const blockSize = stats.frsize ?? stats.bsize; + const available = stats.bavail * blockSize; + const total = stats.blocks * blockSize; const currentUsage = ((total - available) / total) * 100; logger.info(`Current internal storage usage is ${currentUsage}% .`); if (currentUsage > config.maxDiskUsagePercent) {