@milaboratories/pl-deployments 2.15.7 → 2.15.9
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 +18 -5
- package/dist/common/os_and_arch.cjs +19 -19
- package/dist/common/os_and_arch.cjs.map +1 -1
- package/dist/common/os_and_arch.js +19 -19
- package/dist/common/os_and_arch.js.map +1 -1
- package/dist/common/pl_binary.cjs +9 -9
- package/dist/common/pl_binary.cjs.map +1 -1
- package/dist/common/pl_binary.d.ts +6 -6
- package/dist/common/pl_binary.d.ts.map +1 -1
- package/dist/common/pl_binary.js +9 -9
- package/dist/common/pl_binary.js.map +1 -1
- package/dist/common/pl_binary_download.cjs +16 -16
- package/dist/common/pl_binary_download.cjs.map +1 -1
- package/dist/common/pl_binary_download.d.ts +6 -6
- package/dist/common/pl_binary_download.d.ts.map +1 -1
- package/dist/common/pl_binary_download.js +16 -16
- package/dist/common/pl_binary_download.js.map +1 -1
- package/dist/common/pl_version.cjs +1 -1
- package/dist/common/pl_version.cjs.map +1 -1
- package/dist/common/pl_version.js +1 -1
- package/dist/common/pl_version.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/local/options.d.ts +4 -4
- package/dist/local/pid.cjs +1 -1
- package/dist/local/pid.cjs.map +1 -1
- package/dist/local/pid.js +1 -1
- package/dist/local/pid.js.map +1 -1
- package/dist/local/pl.cjs +26 -26
- package/dist/local/pl.cjs.map +1 -1
- package/dist/local/pl.d.ts +8 -8
- package/dist/local/pl.d.ts.map +1 -1
- package/dist/local/pl.js +26 -26
- package/dist/local/pl.js.map +1 -1
- package/dist/local/process.cjs +16 -16
- package/dist/local/process.cjs.map +1 -1
- package/dist/local/process.d.ts +2 -2
- package/dist/local/process.js +16 -16
- package/dist/local/process.js.map +1 -1
- package/dist/local/trace.cjs.map +1 -1
- package/dist/local/trace.d.ts +1 -1
- package/dist/local/trace.js.map +1 -1
- package/dist/package.json.cjs +2 -1
- package/dist/package.json.cjs.map +1 -1
- package/dist/package.json.js +2 -1
- package/dist/package.json.js.map +1 -1
- package/dist/ssh/__tests__/common-utils.d.ts +2 -2
- package/dist/ssh/__tests__/common-utils.d.ts.map +1 -1
- package/dist/ssh/connection_info.cjs +13 -7
- package/dist/ssh/connection_info.cjs.map +1 -1
- package/dist/ssh/connection_info.d.ts +1 -1
- package/dist/ssh/connection_info.d.ts.map +1 -1
- package/dist/ssh/connection_info.js +13 -7
- package/dist/ssh/connection_info.js.map +1 -1
- package/dist/ssh/pl.cjs +79 -76
- package/dist/ssh/pl.cjs.map +1 -1
- package/dist/ssh/pl.d.ts +18 -18
- package/dist/ssh/pl.d.ts.map +1 -1
- package/dist/ssh/pl.js +79 -76
- package/dist/ssh/pl.js.map +1 -1
- package/dist/ssh/pl_paths.cjs +13 -13
- package/dist/ssh/pl_paths.cjs.map +1 -1
- package/dist/ssh/pl_paths.d.ts.map +1 -1
- package/dist/ssh/pl_paths.js +13 -13
- package/dist/ssh/pl_paths.js.map +1 -1
- package/dist/ssh/ssh.cjs +43 -40
- package/dist/ssh/ssh.cjs.map +1 -1
- package/dist/ssh/ssh.d.ts +9 -9
- package/dist/ssh/ssh.d.ts.map +1 -1
- package/dist/ssh/ssh.js +43 -40
- package/dist/ssh/ssh.js.map +1 -1
- package/dist/ssh/ssh_errors.cjs +7 -5
- package/dist/ssh/ssh_errors.cjs.map +1 -1
- package/dist/ssh/ssh_errors.d.ts.map +1 -1
- package/dist/ssh/ssh_errors.js +7 -5
- package/dist/ssh/ssh_errors.js.map +1 -1
- package/dist/ssh/supervisord.cjs +15 -13
- package/dist/ssh/supervisord.cjs.map +1 -1
- package/dist/ssh/supervisord.d.ts +2 -2
- package/dist/ssh/supervisord.d.ts.map +1 -1
- package/dist/ssh/supervisord.js +15 -13
- package/dist/ssh/supervisord.js.map +1 -1
- package/package.json +38 -37
- package/src/common/os_and_arch.ts +19 -19
- package/src/common/pl_binary.ts +30 -27
- package/src/common/pl_binary_download.ts +80 -59
- package/src/common/pl_version.ts +2 -2
- package/src/index.ts +5 -5
- package/src/local/config.test.yaml +19 -19
- package/src/local/options.ts +4 -4
- package/src/local/pid.ts +4 -4
- package/src/local/pl.test.ts +245 -253
- package/src/local/pl.ts +45 -50
- package/src/local/process.ts +21 -21
- package/src/local/trace.ts +1 -1
- package/src/ssh/__tests__/common-utils.ts +21 -19
- package/src/ssh/__tests__/pl-docker.test.ts +68 -59
- package/src/ssh/__tests__/ssh-docker.test.ts +152 -90
- package/src/ssh/__tests__/ssh-upload.test.ts +42 -31
- package/src/ssh/connection_info.ts +33 -27
- package/src/ssh/pl.test.ts +15 -13
- package/src/ssh/pl.ts +228 -143
- package/src/ssh/pl_paths.ts +22 -18
- package/src/ssh/ssh.ts +151 -74
- package/src/ssh/ssh_errors.test.ts +39 -39
- package/src/ssh/ssh_errors.ts +8 -6
- package/src/ssh/supervisord.ts +28 -28
package/dist/ssh/pl.js
CHANGED
|
@@ -15,7 +15,7 @@ class SshPl {
|
|
|
15
15
|
logger;
|
|
16
16
|
sshClient;
|
|
17
17
|
username;
|
|
18
|
-
initState = { step:
|
|
18
|
+
initState = { step: "init" };
|
|
19
19
|
constructor(logger, sshClient, username) {
|
|
20
20
|
this.logger = logger;
|
|
21
21
|
this.sshClient = sshClient;
|
|
@@ -47,7 +47,7 @@ class SshPl {
|
|
|
47
47
|
return await supervisorStatus(this.logger, this.sshClient, remoteHome, arch.arch);
|
|
48
48
|
}
|
|
49
49
|
/** Starts all the services on the server.
|
|
50
|
-
|
|
50
|
+
* Idempotent semantic: we could call it several times. */
|
|
51
51
|
async start(shouldUseMinio) {
|
|
52
52
|
const arch = await this.getArch();
|
|
53
53
|
const remoteHome = await this.getUserHomeDirectory();
|
|
@@ -60,7 +60,7 @@ class SshPl {
|
|
|
60
60
|
}
|
|
61
61
|
catch (e) {
|
|
62
62
|
let msg = `SshPl.start: ${e}`;
|
|
63
|
-
let logs =
|
|
63
|
+
let logs = "";
|
|
64
64
|
try {
|
|
65
65
|
logs = await this.sshClient.readFile(platformaCliLogs(remoteHome));
|
|
66
66
|
msg += `, platforma cli logs: ${logs}`;
|
|
@@ -73,7 +73,7 @@ class SshPl {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
/** Stops all the services on the server.
|
|
76
|
-
|
|
76
|
+
* Idempotent semantic: we could call it several times. */
|
|
77
77
|
async stop() {
|
|
78
78
|
const arch = await this.getArch();
|
|
79
79
|
const remoteHome = await this.getUserHomeDirectory();
|
|
@@ -110,7 +110,7 @@ class SshPl {
|
|
|
110
110
|
* generates all the configs, creates necessary dirs,
|
|
111
111
|
* and finally starts all the services. */
|
|
112
112
|
async platformaInit(options) {
|
|
113
|
-
const state = { localWorkdir: options.localWorkdir, step:
|
|
113
|
+
const state = { localWorkdir: options.localWorkdir, step: "init" };
|
|
114
114
|
const { onProgress } = options;
|
|
115
115
|
// merge options with default ops.
|
|
116
116
|
const ops = {
|
|
@@ -123,12 +123,12 @@ class SshPl {
|
|
|
123
123
|
await this.doStepDetectHome(state, onProgress);
|
|
124
124
|
const needRestartPlatforma = await this.doStepReadExistedConfig(state, ops, onProgress);
|
|
125
125
|
if (!needRestartPlatforma) {
|
|
126
|
-
await onProgress?.(
|
|
126
|
+
await onProgress?.("Platforma is already running. Skipping initialization.");
|
|
127
127
|
return state.existedSettings;
|
|
128
128
|
}
|
|
129
129
|
await this.doStepStopExistedPlatforma(state, onProgress);
|
|
130
130
|
await this.doStepCheckDbLock(state, onProgress);
|
|
131
|
-
await onProgress?.(
|
|
131
|
+
await onProgress?.("Installation platforma...");
|
|
132
132
|
await this.doStepDownloadBinaries(state, onProgress, ops);
|
|
133
133
|
await this.doStepFetchPorts(state);
|
|
134
134
|
await this.doStepGenerateNewConfig(state, onProgress, ops);
|
|
@@ -145,33 +145,36 @@ class SshPl {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
async doStepStopExistedPlatforma(state, onProgress) {
|
|
148
|
-
state.step =
|
|
148
|
+
state.step = "stopExistedPlatforma";
|
|
149
149
|
if (!isAllAlive(state.alive, state.shouldUseMinio ?? false)) {
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
|
-
await onProgress?.(
|
|
152
|
+
await onProgress?.("Stopping services...");
|
|
153
153
|
await this.stop();
|
|
154
154
|
}
|
|
155
155
|
removeSensitiveData(state) {
|
|
156
156
|
const stateCopy = { ...state };
|
|
157
|
-
stateCopy.generatedConfig = {
|
|
157
|
+
stateCopy.generatedConfig = {
|
|
158
|
+
...stateCopy.generatedConfig,
|
|
159
|
+
filesToCreate: { skipped: "sanitized" },
|
|
160
|
+
};
|
|
158
161
|
return stateCopy;
|
|
159
162
|
}
|
|
160
163
|
async doStepStartPlatforma(state, onProgress) {
|
|
161
|
-
state.step =
|
|
162
|
-
await onProgress?.(
|
|
164
|
+
state.step = "startPlatforma";
|
|
165
|
+
await onProgress?.("Starting Platforma on the server...");
|
|
163
166
|
await this.start(state.shouldUseMinio ?? false);
|
|
164
167
|
state.started = true;
|
|
165
168
|
this.initState = state;
|
|
166
|
-
await onProgress?.(
|
|
169
|
+
await onProgress?.("Platforma has been started successfully.");
|
|
167
170
|
}
|
|
168
171
|
async doStepSaveNewConnectionInfo(state, onProgress, ops) {
|
|
169
|
-
state.step =
|
|
172
|
+
state.step = "saveNewConnectionInfo";
|
|
170
173
|
const config = state.generatedConfig;
|
|
171
|
-
await onProgress?.(
|
|
174
|
+
await onProgress?.("Saving connection information...");
|
|
172
175
|
state.connectionInfo = newConnectionInfo(config.plUser, config.plPassword, state.ports, notEmpty(ops.useGlobalAccess), ops.plBinary.version, state.shouldUseMinio ?? false);
|
|
173
176
|
await this.sshClient.writeFileOnTheServer(connectionInfo(state.remoteHome), stringifyConnectionInfo(state.connectionInfo));
|
|
174
|
-
await onProgress?.(
|
|
177
|
+
await onProgress?.("Connection information saved.");
|
|
175
178
|
}
|
|
176
179
|
async doStepCheckDbLock(state, onProgress) {
|
|
177
180
|
const removeLockFile = async (lockFilePath) => {
|
|
@@ -185,32 +188,32 @@ class SshPl {
|
|
|
185
188
|
throw new Error(msg);
|
|
186
189
|
}
|
|
187
190
|
};
|
|
188
|
-
state.step =
|
|
189
|
-
await onProgress?.(
|
|
191
|
+
state.step = "checkDbLock";
|
|
192
|
+
await onProgress?.("Checking for DB lock...");
|
|
190
193
|
const lockFilePath = platformaDbLock(state.remoteHome);
|
|
191
194
|
const lockFileExists = await this.sshClient.checkFileExists(lockFilePath);
|
|
192
195
|
if (!lockFileExists) {
|
|
193
|
-
await onProgress?.(
|
|
196
|
+
await onProgress?.("No DB lock found. Proceeding...");
|
|
194
197
|
return;
|
|
195
198
|
}
|
|
196
199
|
this.logger.info(`DB lock file found at ${lockFilePath}. Checking which process holds it...`);
|
|
197
200
|
const lockProcessInfo = await this.findLockHolder(lockFilePath);
|
|
198
201
|
if (!lockProcessInfo) {
|
|
199
|
-
this.logger.warn(
|
|
202
|
+
this.logger.warn("Lock file exists but no process is holding it. Removing stale lock file...");
|
|
200
203
|
await removeLockFile(lockFilePath);
|
|
201
204
|
return;
|
|
202
205
|
}
|
|
203
206
|
this.logger.info(`Found process ${lockProcessInfo.pid} (user: ${lockProcessInfo.user}) holding DB lock`);
|
|
204
207
|
if (lockProcessInfo.user !== this.username) {
|
|
205
|
-
const msg = `DB lock is held by process ${lockProcessInfo.pid} `
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
const msg = `DB lock is held by process ${lockProcessInfo.pid} ` +
|
|
209
|
+
`owned by user '${lockProcessInfo.user}', but current user is '${this.username}'. ` +
|
|
210
|
+
"Cannot kill process owned by different user.";
|
|
208
211
|
this.logger.error(msg);
|
|
209
212
|
throw new Error(msg);
|
|
210
213
|
}
|
|
211
214
|
this.logger.info(`Process ${lockProcessInfo.pid} belongs to current user ${this.username}. Killing it...`);
|
|
212
215
|
await this.killRemoteProcess(lockProcessInfo.pid);
|
|
213
|
-
this.logger.info(
|
|
216
|
+
this.logger.info("Process holding DB lock has been terminated.");
|
|
214
217
|
// Verify lock file is gone or can be removed
|
|
215
218
|
const lockStillExists = await this.sshClient.checkFileExists(lockFilePath);
|
|
216
219
|
if (lockStillExists) {
|
|
@@ -218,8 +221,8 @@ class SshPl {
|
|
|
218
221
|
}
|
|
219
222
|
}
|
|
220
223
|
async doStepConfigureSupervisord(state, onProgress) {
|
|
221
|
-
await onProgress?.(
|
|
222
|
-
state.step =
|
|
224
|
+
await onProgress?.("Writing supervisord configuration...");
|
|
225
|
+
state.step = "configureSupervisord";
|
|
223
226
|
const config = state.generatedConfig;
|
|
224
227
|
let supervisorConfig;
|
|
225
228
|
if (state.shouldUseMinio) {
|
|
@@ -232,12 +235,12 @@ class SshPl {
|
|
|
232
235
|
if (!writeResult) {
|
|
233
236
|
throw new Error(`Can not write supervisord config on the server ${workDir(state.remoteHome)}`);
|
|
234
237
|
}
|
|
235
|
-
await onProgress?.(
|
|
238
|
+
await onProgress?.("Supervisord configuration written.");
|
|
236
239
|
}
|
|
237
240
|
async doStepCreateFoldersAndSaveFiles(state, onProgress) {
|
|
238
|
-
state.step =
|
|
241
|
+
state.step = "createFoldersAndSaveFiles";
|
|
239
242
|
const config = state.generatedConfig;
|
|
240
|
-
await onProgress?.(
|
|
243
|
+
await onProgress?.("Generating folder structure...");
|
|
241
244
|
for (const [filePath, content] of Object.entries(config.filesToCreate)) {
|
|
242
245
|
await this.sshClient.writeFileOnTheServer(filePath, content);
|
|
243
246
|
this.logger.info(`Created file ${filePath}`);
|
|
@@ -246,16 +249,16 @@ class SshPl {
|
|
|
246
249
|
await this.sshClient.ensureRemoteDirCreated(dir);
|
|
247
250
|
this.logger.info(`Created directory ${dir}`);
|
|
248
251
|
}
|
|
249
|
-
await onProgress?.(
|
|
252
|
+
await onProgress?.("Folder structure created.");
|
|
250
253
|
}
|
|
251
254
|
async doStepGenerateNewConfig(state, onProgress, ops) {
|
|
252
|
-
state.step =
|
|
253
|
-
await onProgress?.(
|
|
255
|
+
state.step = "generateNewConfig";
|
|
256
|
+
await onProgress?.("Generating new config...");
|
|
254
257
|
const config = await generateSshPlConfigs({
|
|
255
258
|
logger: this.logger,
|
|
256
259
|
workingDir: workDir(state.remoteHome),
|
|
257
260
|
portsMode: {
|
|
258
|
-
type:
|
|
261
|
+
type: "customWithMinio",
|
|
259
262
|
ports: {
|
|
260
263
|
debug: state.ports.debug.remote,
|
|
261
264
|
grpc: state.ports.grpc.remote,
|
|
@@ -274,51 +277,51 @@ class SshPl {
|
|
|
274
277
|
useMinio: state.shouldUseMinio ?? false,
|
|
275
278
|
});
|
|
276
279
|
state.generatedConfig = { ...config };
|
|
277
|
-
await onProgress?.(
|
|
280
|
+
await onProgress?.("New config generated");
|
|
278
281
|
}
|
|
279
282
|
async doStepFetchPorts(state) {
|
|
280
|
-
state.step =
|
|
283
|
+
state.step = "fetchPorts";
|
|
281
284
|
state.ports = await this.fetchPorts(state.remoteHome, state.arch);
|
|
282
|
-
if (!state.ports.debug.remote
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
285
|
+
if (!state.ports.debug.remote ||
|
|
286
|
+
!state.ports.grpc.remote ||
|
|
287
|
+
!state.ports.minioPort.remote ||
|
|
288
|
+
!state.ports.minioConsolePort.remote ||
|
|
289
|
+
!state.ports.monitoring.remote ||
|
|
290
|
+
!state.ports.http?.remote) {
|
|
288
291
|
throw new Error(`SshPl.platformaInit: remote ports are not defined`);
|
|
289
292
|
}
|
|
290
293
|
}
|
|
291
294
|
async doStepDownloadBinaries(state, onProgress, ops) {
|
|
292
|
-
state.step =
|
|
293
|
-
await onProgress?.(
|
|
295
|
+
state.step = "downloadBinaries";
|
|
296
|
+
await onProgress?.("Downloading and uploading required binaries...");
|
|
294
297
|
const glibcVersion = await getGlibcVersion(this.logger, this.sshClient);
|
|
295
298
|
if (glibcVersion < minRequiredGlibcVersion)
|
|
296
299
|
throw new Error(`glibc version ${glibcVersion} is too old. Version ${minRequiredGlibcVersion} or higher is required for Platforma.`);
|
|
297
300
|
const downloadRes = await this.downloadBinariesAndUploadToTheServer(ops.localWorkdir, ops.plBinary, state.remoteHome, state.arch, state.shouldUseMinio ?? false, ops.proxy);
|
|
298
|
-
await onProgress?.(
|
|
301
|
+
await onProgress?.("All required binaries have been downloaded and uploaded.");
|
|
299
302
|
state.binPaths = { ...downloadRes, history: undefined };
|
|
300
303
|
state.downloadedBinaries = downloadRes.history;
|
|
301
304
|
}
|
|
302
305
|
async doStepDetectArch(state, onProgress) {
|
|
303
|
-
state.step =
|
|
304
|
-
await onProgress?.(
|
|
306
|
+
state.step = "detectArch";
|
|
307
|
+
await onProgress?.("Detecting server architecture...");
|
|
305
308
|
state.arch = await this.getArch();
|
|
306
|
-
await onProgress?.(
|
|
309
|
+
await onProgress?.("Server architecture detected.");
|
|
307
310
|
}
|
|
308
311
|
async doStepDetectHome(state, onProgress) {
|
|
309
|
-
state.step =
|
|
310
|
-
await onProgress?.(
|
|
312
|
+
state.step = "detectHome";
|
|
313
|
+
await onProgress?.("Fetching user home directory...");
|
|
311
314
|
state.remoteHome = await this.getUserHomeDirectory();
|
|
312
|
-
await onProgress?.(
|
|
315
|
+
await onProgress?.("User home directory retrieved.");
|
|
313
316
|
}
|
|
314
317
|
async doStepReadExistedConfig(state, ops, onProgress) {
|
|
315
|
-
state.step =
|
|
316
|
-
await onProgress?.(
|
|
318
|
+
state.step = "checkAlive";
|
|
319
|
+
await onProgress?.("Checking platform status...");
|
|
317
320
|
state.alive = await this.isAlive();
|
|
318
321
|
if (!state.alive?.platforma) {
|
|
319
322
|
return true;
|
|
320
323
|
}
|
|
321
|
-
await onProgress?.(
|
|
324
|
+
await onProgress?.("All required services are running.");
|
|
322
325
|
state.existedSettings = await this.readExistedConfig(state.remoteHome);
|
|
323
326
|
if (!state.existedSettings) {
|
|
324
327
|
throw new Error(`SshPl.platformaInit: platforma is alive but existed settings are not found`);
|
|
@@ -335,10 +338,10 @@ class SshPl {
|
|
|
335
338
|
this.logger.info(`SshPl.platformaInit: minio is not used`);
|
|
336
339
|
}
|
|
337
340
|
if (!state.needRestart) {
|
|
338
|
-
await onProgress?.(
|
|
341
|
+
await onProgress?.("Server setup completed.");
|
|
339
342
|
return false;
|
|
340
343
|
}
|
|
341
|
-
await onProgress?.(
|
|
344
|
+
await onProgress?.("Stopping services...");
|
|
342
345
|
await this.stop();
|
|
343
346
|
return true;
|
|
344
347
|
}
|
|
@@ -346,13 +349,13 @@ class SshPl {
|
|
|
346
349
|
const state = [];
|
|
347
350
|
const dispatcher = defaultHttpDispatcher(proxy);
|
|
348
351
|
try {
|
|
349
|
-
const pl = await this.downloadAndUntar(localWorkdir, remoteHome, arch,
|
|
352
|
+
const pl = await this.downloadAndUntar(localWorkdir, remoteHome, arch, "pl", `pl-${plBinary.version}`, dispatcher);
|
|
350
353
|
state.push(pl);
|
|
351
|
-
const supervisor = await this.downloadAndUntar(localWorkdir, remoteHome, arch,
|
|
354
|
+
const supervisor = await this.downloadAndUntar(localWorkdir, remoteHome, arch, "supervisord", supervisordDirName, dispatcher);
|
|
352
355
|
state.push(supervisor);
|
|
353
356
|
const minioPath = minioBin(remoteHome, arch.arch);
|
|
354
357
|
if (shouldUseMinio) {
|
|
355
|
-
const minio = await this.downloadAndUntar(localWorkdir, remoteHome, arch,
|
|
358
|
+
const minio = await this.downloadAndUntar(localWorkdir, remoteHome, arch, "minio", minioDirName, dispatcher);
|
|
356
359
|
state.push(minio);
|
|
357
360
|
await this.sshClient.chmod(minioPath, 0o750);
|
|
358
361
|
}
|
|
@@ -381,7 +384,7 @@ class SshPl {
|
|
|
381
384
|
// Example:
|
|
382
385
|
// COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
|
383
386
|
// platforma 11628 rfiskov 10u REG 1,16 0 66670038 ./LOCK
|
|
384
|
-
const lines = output.split(
|
|
387
|
+
const lines = output.split("\n");
|
|
385
388
|
if (lines.length <= 1) {
|
|
386
389
|
return null;
|
|
387
390
|
}
|
|
@@ -461,11 +464,11 @@ class SshPl {
|
|
|
461
464
|
}
|
|
462
465
|
}
|
|
463
466
|
/** We have to extract pl in the remote server,
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
467
|
+
* because Windows doesn't support symlinks
|
|
468
|
+
* that are found in Linux pl binaries tgz archive.
|
|
469
|
+
* For this reason, we extract all to the remote server.
|
|
470
|
+
* It requires `tar` to be installed on the server
|
|
471
|
+
* (it's not installed for Rocky Linux for example). */
|
|
469
472
|
async downloadAndUntar(localWorkdir, remoteHome, arch, softwareName, tgzName, dispatcher) {
|
|
470
473
|
const state = {};
|
|
471
474
|
state.binBasePath = binariesDir(remoteHome);
|
|
@@ -496,14 +499,14 @@ class SshPl {
|
|
|
496
499
|
state.downloadResult = notEmpty(downloadBinaryResult);
|
|
497
500
|
state.localArchivePath = upath.resolve(state.downloadResult.archivePath);
|
|
498
501
|
state.remoteDir = upath.join(state.binBasePath, state.downloadResult.baseName);
|
|
499
|
-
state.remoteArchivePath = state.remoteDir +
|
|
502
|
+
state.remoteArchivePath = state.remoteDir + ".tgz";
|
|
500
503
|
await this.sshClient.ensureRemoteDirCreated(state.remoteDir);
|
|
501
504
|
await this.sshClient.uploadFile(state.localArchivePath, state.remoteArchivePath);
|
|
502
505
|
state.uploadDone = true;
|
|
503
506
|
try {
|
|
504
|
-
await this.sshClient.exec(
|
|
507
|
+
await this.sshClient.exec("hash tar");
|
|
505
508
|
}
|
|
506
|
-
catch
|
|
509
|
+
catch {
|
|
507
510
|
throw new Error(`tar is not installed on the server. Please install it before running Platforma.`);
|
|
508
511
|
}
|
|
509
512
|
// TODO: Create a proper archive to avoid xattr warnings
|
|
@@ -517,9 +520,9 @@ class SshPl {
|
|
|
517
520
|
const checkPathSupervisor = supervisorBin(remoteHome, arch.arch);
|
|
518
521
|
const checkPathMinio = minioDir(remoteHome, arch.arch);
|
|
519
522
|
const checkPathPlatforma = platformaBin(remoteHome, arch.arch);
|
|
520
|
-
if (!await this.sshClient.checkFileExists(checkPathPlatforma)
|
|
521
|
-
|
|
522
|
-
|
|
523
|
+
if (!(await this.sshClient.checkFileExists(checkPathPlatforma)) ||
|
|
524
|
+
!(await this.sshClient.checkFileExists(checkPathMinio)) ||
|
|
525
|
+
!(await this.sshClient.checkFileExists(checkPathSupervisor))) {
|
|
523
526
|
return true;
|
|
524
527
|
}
|
|
525
528
|
return false;
|
|
@@ -532,7 +535,7 @@ class SshPl {
|
|
|
532
535
|
await sleep(interval);
|
|
533
536
|
total += interval;
|
|
534
537
|
if (total > maxMs) {
|
|
535
|
-
throw new Error(`isAliveWithInterval: The process did not ${shouldStart ?
|
|
538
|
+
throw new Error(`isAliveWithInterval: The process did not ${shouldStart ? "started" : "stopped"} after ${maxMs} ms. Live status: ${JSON.stringify(alive)}`);
|
|
536
539
|
}
|
|
537
540
|
alive = await this.isAlive();
|
|
538
541
|
}
|
|
@@ -588,17 +591,17 @@ class SshPl {
|
|
|
588
591
|
return +stdout;
|
|
589
592
|
}
|
|
590
593
|
async getArch() {
|
|
591
|
-
const { stdout, stderr } = await this.sshClient.exec(
|
|
594
|
+
const { stdout, stderr } = await this.sshClient.exec("uname -s && uname -m");
|
|
592
595
|
if (stderr)
|
|
593
596
|
throw new Error(`getArch: stderr is not empty: ${stderr}, stdout: ${stdout}`);
|
|
594
|
-
const arr = stdout.split(
|
|
597
|
+
const arr = stdout.split("\n");
|
|
595
598
|
return {
|
|
596
599
|
platform: arr[0],
|
|
597
600
|
arch: arr[1],
|
|
598
601
|
};
|
|
599
602
|
}
|
|
600
603
|
async getUserHomeDirectory() {
|
|
601
|
-
const { stdout, stderr } = await this.sshClient.exec(
|
|
604
|
+
const { stdout, stderr } = await this.sshClient.exec("echo $HOME");
|
|
602
605
|
if (stderr) {
|
|
603
606
|
const home = `/home/${this.username}`;
|
|
604
607
|
console.warn(`getUserHomeDirectory: stderr is not empty: ${stderr}, stdout: ${stdout}, will get a default home: ${home}`);
|
|
@@ -610,7 +613,7 @@ class SshPl {
|
|
|
610
613
|
const defaultSshPlConfig = {
|
|
611
614
|
useGlobalAccess: false,
|
|
612
615
|
plBinary: {
|
|
613
|
-
type:
|
|
616
|
+
type: "Download",
|
|
614
617
|
version: getDefaultPlVersion(),
|
|
615
618
|
},
|
|
616
619
|
};
|
|
@@ -621,7 +624,7 @@ const defaultSshPlConfig = {
|
|
|
621
624
|
*/
|
|
622
625
|
async function getGlibcVersion(logger, sshClient) {
|
|
623
626
|
try {
|
|
624
|
-
const { stdout, stderr } = await sshClient.exec(
|
|
627
|
+
const { stdout, stderr } = await sshClient.exec("ldd --version | head -n 1");
|
|
625
628
|
if (stderr) {
|
|
626
629
|
throw new Error(`Failed to check glibc version: ${stderr}`);
|
|
627
630
|
}
|