@milaboratories/pl-deployments 2.12.4 → 2.12.6

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/dist/ssh/pl.cjs CHANGED
@@ -128,6 +128,7 @@ class SshPl {
128
128
  return state.existedSettings;
129
129
  }
130
130
  await this.doStepStopExistedPlatforma(state, onProgress);
131
+ await this.doStepCheckDbLock(state, onProgress);
131
132
  await onProgress?.('Installation platforma...');
132
133
  await this.doStepDownloadBinaries(state, onProgress, ops);
133
134
  await this.doStepFetchPorts(state);
@@ -173,6 +174,50 @@ class SshPl {
173
174
  await this.sshClient.writeFileOnTheServer(pl_paths.connectionInfo(state.remoteHome), connection_info.stringifyConnectionInfo(state.connectionInfo));
174
175
  await onProgress?.('Connection information saved.');
175
176
  }
177
+ async doStepCheckDbLock(state, onProgress) {
178
+ const removeLockFile = async (lockFilePath) => {
179
+ try {
180
+ await this.sshClient.exec(`rm -f ${lockFilePath}`);
181
+ this.logger.info(`Removed stale lock file ${lockFilePath}`);
182
+ }
183
+ catch (e) {
184
+ const msg = `Failed to remove stale lock file ${lockFilePath}: ${e}`;
185
+ this.logger.error(msg);
186
+ throw new Error(msg);
187
+ }
188
+ };
189
+ state.step = 'checkDbLock';
190
+ await onProgress?.('Checking for DB lock...');
191
+ const lockFilePath = pl_paths.platformaDbLock(state.remoteHome);
192
+ const lockFileExists = await this.sshClient.checkFileExists(lockFilePath);
193
+ if (!lockFileExists) {
194
+ await onProgress?.('No DB lock found. Proceeding...');
195
+ return;
196
+ }
197
+ this.logger.info(`DB lock file found at ${lockFilePath}. Checking which process holds it...`);
198
+ const lockProcessInfo = await this.findLockHolder(lockFilePath);
199
+ if (!lockProcessInfo) {
200
+ this.logger.warn('Lock file exists but no process is holding it. Removing stale lock file...');
201
+ await removeLockFile(lockFilePath);
202
+ return;
203
+ }
204
+ this.logger.info(`Found process ${lockProcessInfo.pid} (user: ${lockProcessInfo.user}) holding DB lock`);
205
+ if (lockProcessInfo.user !== this.username) {
206
+ const msg = `DB lock is held by process ${lockProcessInfo.pid} `
207
+ + `owned by user '${lockProcessInfo.user}', but current user is '${this.username}'. `
208
+ + 'Cannot kill process owned by different user.';
209
+ this.logger.error(msg);
210
+ throw new Error(msg);
211
+ }
212
+ this.logger.info(`Process ${lockProcessInfo.pid} belongs to current user ${this.username}. Killing it...`);
213
+ await this.killRemoteProcess(lockProcessInfo.pid);
214
+ this.logger.info('Process holding DB lock has been terminated.');
215
+ // Verify lock file is gone or can be removed
216
+ const lockStillExists = await this.sshClient.checkFileExists(lockFilePath);
217
+ if (lockStillExists) {
218
+ await removeLockFile(lockFilePath);
219
+ }
220
+ }
176
221
  async doStepConfigureSupervisord(state, onProgress) {
177
222
  await onProgress?.('Writing supervisord configuration...');
178
223
  state.step = 'configureSupervisord';
@@ -323,6 +368,95 @@ class SshPl {
323
368
  throw e;
324
369
  }
325
370
  }
371
+ async findLockHolderWithLsof(lockFilePath) {
372
+ try {
373
+ const { stdout } = await this.sshClient.exec(`lsof ${lockFilePath} 2>/dev/null || true`);
374
+ const output = stdout.trim();
375
+ if (!output) {
376
+ return null;
377
+ }
378
+ // Example:
379
+ // COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
380
+ // platforma 11628 rfiskov 10u REG 1,16 0 66670038 ./LOCK
381
+ const lines = output.split('\n');
382
+ if (lines.length <= 1) {
383
+ return null;
384
+ }
385
+ const parts = lines[1].trim().split(/\s+/);
386
+ if (parts.length < 3) {
387
+ return null;
388
+ }
389
+ const pid = Number.parseInt(parts[1], 10);
390
+ const user = parts[2];
391
+ return Number.isNaN(pid) || !user ? null : { pid, user };
392
+ }
393
+ catch (e) {
394
+ this.logger.warn(`Failed to use lsof to check lock: ${e}`);
395
+ return null;
396
+ }
397
+ }
398
+ async findLockHolderWithFuser(lockFilePath) {
399
+ try {
400
+ const { stdout } = await this.sshClient.exec(`fuser ${lockFilePath} 2>/dev/null || true`);
401
+ const output = stdout.trim();
402
+ if (!output) {
403
+ return null;
404
+ }
405
+ // Example: ./LOCK: 11628
406
+ const match = output.match(/: (\d+)/);
407
+ if (!match) {
408
+ return null;
409
+ }
410
+ const pid = Number.parseInt(match[1], 10);
411
+ if (Number.isNaN(pid)) {
412
+ return null;
413
+ }
414
+ try {
415
+ const psResult = await this.sshClient.exec(`ps -o user= -p ${pid} 2>/dev/null || true`);
416
+ const user = psResult.stdout.trim();
417
+ return user ? { pid, user } : null;
418
+ }
419
+ catch (e) {
420
+ this.logger.warn(`Failed to get user for PID ${pid}: ${e}`);
421
+ return null;
422
+ }
423
+ }
424
+ catch (e) {
425
+ this.logger.warn(`Failed to use fuser to check lock: ${e}`);
426
+ return null;
427
+ }
428
+ }
429
+ async findLockHolder(lockFilePath) {
430
+ const viaLsof = await this.findLockHolderWithLsof(lockFilePath);
431
+ if (viaLsof) {
432
+ return viaLsof;
433
+ }
434
+ return this.findLockHolderWithFuser(lockFilePath);
435
+ }
436
+ async killRemoteProcess(pid) {
437
+ this.logger.info(`Killing process ${pid}...`);
438
+ try {
439
+ // Try graceful termination first
440
+ await this.sshClient.exec(`kill ${pid} 2>/dev/null || true`);
441
+ await tsHelpers.sleep(1000);
442
+ // Check if process still exists
443
+ try {
444
+ await this.sshClient.exec(`kill -0 ${pid} 2>/dev/null`);
445
+ // Process still exists, force kill
446
+ this.logger.warn(`Process ${pid} still alive after SIGTERM, forcing kill...`);
447
+ await this.sshClient.exec(`kill -9 ${pid} 2>/dev/null || true`);
448
+ await tsHelpers.sleep(500);
449
+ }
450
+ catch {
451
+ // Process is dead, nothing to do
452
+ }
453
+ }
454
+ catch (e) {
455
+ const msg = `Failed to kill process ${pid}: ${e}`;
456
+ this.logger.error(msg);
457
+ throw new Error(msg);
458
+ }
459
+ }
326
460
  /** We have to extract pl in the remote server,
327
461
  * because Windows doesn't support symlinks
328
462
  * that are found in Linux pl binaries tgz archive.
@@ -1 +1 @@
1
- {"version":3,"file":"pl.cjs","sources":["../../src/ssh/pl.ts"],"sourcesContent":["import type * as ssh from 'ssh2';\nimport { SshClient } from './ssh';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { sleep, notEmpty } from '@milaboratories/ts-helpers';\nimport type { DownloadBinaryResult } from '../common/pl_binary_download';\nimport { downloadBinaryNoExtract } from '../common/pl_binary_download';\nimport upath from 'upath';\nimport * as plpath from './pl_paths';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nimport net from 'node:net';\nimport type { PlConfig, PlLicenseMode, SshPlConfigGenerationResult } from '@milaboratories/pl-config';\nimport { getFreePort, generateSshPlConfigs } from '@milaboratories/pl-config';\nimport type { SupervisorStatus } from './supervisord';\nimport { supervisorStatus, supervisorStop as supervisorCtlShutdown, generateSupervisordConfigWithMinio, supervisorCtlStart, isSupervisordRunning, generateSupervisordConfig, isAllAlive } from './supervisord';\nimport type { ConnectionInfo, SshPlPorts } from './connection_info';\nimport { newConnectionInfo, parseConnectionInfo, stringifyConnectionInfo } from './connection_info';\nimport type { PlBinarySourceDownload } from '../common/pl_binary';\n\nconst minRequiredGlibcVersion = 2.28;\n\nexport class SshPl {\n private initState: PlatformaInitState = { step: 'init' };\n constructor(\n public readonly logger: MiLogger,\n public readonly sshClient: SshClient,\n private readonly username: string,\n ) { }\n\n public info() {\n return {\n username: this.username,\n initState: this.initState,\n };\n }\n\n public static async init(logger: MiLogger, config: ssh.ConnectConfig): Promise<SshPl> {\n try {\n const sshClient = await SshClient.init(logger, config);\n return new SshPl(logger, sshClient, notEmpty(config.username));\n } catch (e: unknown) {\n logger.error(`Connection error in SshClient.init: ${e}`);\n throw e;\n }\n }\n\n public cleanUp() {\n this.sshClient.close();\n }\n\n /** Provides an info if the platforma and minio are running along with the debug info. */\n public async isAlive(): Promise<SupervisorStatus> {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n return await supervisorStatus(this.logger, this.sshClient, remoteHome, arch.arch);\n }\n\n /** Starts all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async start(shouldUseMinio: boolean) {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n if (!isAllAlive(await this.isAlive(), shouldUseMinio)) {\n await supervisorCtlStart(this.sshClient, remoteHome, arch.arch);\n\n // We are waiting for Platforma to run to ensure that it has started.\n return await this.checkIsAliveWithInterval(shouldUseMinio);\n }\n } catch (e: unknown) {\n let msg = `SshPl.start: ${e}`;\n\n let logs = '';\n try {\n logs = await this.sshClient.readFile(plpath.platformaCliLogs(remoteHome));\n msg += `, platforma cli logs: ${logs}`;\n } catch (e: unknown) {\n msg += `, Can not read platforma cli logs: ${e}`;\n }\n\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async stop() {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n const alive = await this.isAlive();\n if (isSupervisordRunning(alive)) {\n await supervisorCtlShutdown(this.sshClient, remoteHome, arch.arch);\n // Check if Minio is running by looking at the alive status\n const shouldUseMinio = alive.minio === true;\n return await this.checkIsAliveWithInterval(shouldUseMinio, 1000, 15, false);\n }\n } catch (e: unknown) {\n const msg = `PlSsh.stop: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops the services, deletes a directory with the state and closes SSH connection. */\n public async reset(): Promise<boolean> {\n await this.stopAndClean();\n this.cleanUp();\n return true;\n }\n\n /** Stops platforma and deletes its state. */\n public async stopAndClean(): Promise<void> {\n const remoteHome = await this.getUserHomeDirectory();\n\n this.logger.info(`pl.reset: Stop Platforma on the server`);\n await this.stop();\n\n this.logger.info(`pl.reset: Deleting Platforma workDir ${plpath.workDir(remoteHome)} on the server`);\n await this.sshClient.deleteFolder(plpath.workDir(remoteHome));\n }\n\n /** Downloads binaries and untar them on the server,\n * generates all the configs, creates necessary dirs,\n * and finally starts all the services. */\n public async platformaInit(options: SshPlConfig): Promise<ConnectionInfo> {\n const state: PlatformaInitState = { localWorkdir: options.localWorkdir, step: 'init' };\n\n const { onProgress } = options;\n\n // merge options with default ops.\n const ops: SshPlConfig = {\n ...defaultSshPlConfig,\n ...options,\n };\n state.plBinaryOps = ops.plBinary;\n\n try {\n await this.doStepDetectArch(state, onProgress);\n await this.doStepDetectHome(state, onProgress);\n\n const needRestartPlatforma = await this.doStepReadExistedConfig(state, ops, onProgress);\n if (!needRestartPlatforma) {\n await onProgress?.('Platforma is already running. Skipping initialization.');\n return state.existedSettings!;\n }\n await this.doStepStopExistedPlatforma(state, onProgress);\n\n await onProgress?.('Installation platforma...');\n\n await this.doStepDownloadBinaries(state, onProgress, ops);\n await this.doStepFetchPorts(state);\n await this.doStepGenerateNewConfig(state, onProgress, ops);\n await this.doStepCreateFoldersAndSaveFiles(state, onProgress);\n await this.doStepConfigureSupervisord(state, onProgress);\n await this.doStepSaveNewConnectionInfo(state, onProgress, ops);\n await this.doStepStartPlatforma(state, onProgress);\n\n return state.connectionInfo!;\n } catch (e: unknown) {\n const msg = `SshPl.platformaInit: ${e}, state: ${JSON.stringify(this.removeSensitiveData(state))}`;\n this.logger.error(msg);\n\n throw new Error(msg);\n }\n }\n\n private async doStepStopExistedPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'stopExistedPlatforma';\n if (!isAllAlive(state.alive!, state.shouldUseMinio ?? false)) {\n return;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n }\n\n private removeSensitiveData(state: PlatformaInitState): PlatformaInitState {\n const stateCopy = { ...state };\n stateCopy.generatedConfig = { ...stateCopy.generatedConfig, filesToCreate: { skipped: 'sanitized' } } as SshPlConfigGenerationResult;\n return stateCopy;\n }\n\n private async doStepStartPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'startPlatforma';\n await onProgress?.('Starting Platforma on the server...');\n await this.start(state.shouldUseMinio ?? false);\n state.started = true;\n this.initState = state;\n\n await onProgress?.('Platforma has been started successfully.');\n }\n\n private async doStepSaveNewConnectionInfo(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'saveNewConnectionInfo';\n const config = state.generatedConfig!;\n await onProgress?.('Saving connection information...');\n state.connectionInfo = newConnectionInfo(\n config.plUser,\n config.plPassword,\n state.ports!,\n notEmpty(ops.useGlobalAccess),\n ops.plBinary!.version,\n state.shouldUseMinio ?? false,\n );\n await this.sshClient.writeFileOnTheServer(\n plpath.connectionInfo(state.remoteHome!),\n stringifyConnectionInfo(state.connectionInfo),\n );\n await onProgress?.('Connection information saved.');\n }\n\n private async doStepConfigureSupervisord(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n await onProgress?.('Writing supervisord configuration...');\n state.step = 'configureSupervisord';\n\n const config = state.generatedConfig!;\n\n let supervisorConfig: string;\n if (state.shouldUseMinio) {\n supervisorConfig = generateSupervisordConfigWithMinio(\n config.minioConfig.storageDir,\n config.minioConfig.envs,\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.minioRelPath!,\n state.binPaths!.downloadedPl,\n );\n } else {\n supervisorConfig = generateSupervisordConfig(\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.downloadedPl,\n );\n }\n\n const writeResult = await this.sshClient.writeFileOnTheServer(plpath.supervisorConf(state.remoteHome!), supervisorConfig);\n if (!writeResult) {\n throw new Error(`Can not write supervisord config on the server ${plpath.workDir(state.remoteHome!)}`);\n }\n await onProgress?.('Supervisord configuration written.');\n }\n\n private async doStepCreateFoldersAndSaveFiles(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'createFoldersAndSaveFiles';\n const config = state.generatedConfig!;\n await onProgress?.('Generating folder structure...');\n for (const [filePath, content] of Object.entries(config.filesToCreate)) {\n await this.sshClient.writeFileOnTheServer(filePath, content);\n this.logger.info(`Created file ${filePath}`);\n }\n\n for (const dir of config.dirsToCreate) {\n await this.sshClient.ensureRemoteDirCreated(dir);\n this.logger.info(`Created directory ${dir}`);\n }\n await onProgress?.('Folder structure created.');\n }\n\n private async doStepGenerateNewConfig(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'generateNewConfig';\n\n await onProgress?.('Generating new config...');\n const config = await generateSshPlConfigs({\n logger: this.logger,\n workingDir: plpath.workDir(state.remoteHome!),\n portsMode: {\n type: 'customWithMinio',\n ports: {\n debug: state.ports!.debug.remote,\n grpc: state.ports!.grpc.remote,\n http: state.ports!.http!.remote,\n minio: state.ports!.minioPort.remote,\n minioConsole: state.ports!.minioConsolePort.remote,\n monitoring: state.ports!.monitoring.remote,\n\n httpLocal: state.ports!.http!.local,\n grpcLocal: state.ports!.grpc.local,\n minioLocal: state.ports!.minioPort.local,\n },\n },\n licenseMode: ops.license,\n useGlobalAccess: notEmpty(ops.useGlobalAccess),\n plConfigPostprocessing: ops.plConfigPostprocessing,\n useMinio: state.shouldUseMinio ?? false,\n });\n state.generatedConfig = { ...config };\n await onProgress?.('New config generated');\n }\n\n private async doStepFetchPorts(state: PlatformaInitState) {\n state.step = 'fetchPorts';\n state.ports = await this.fetchPorts(state.remoteHome!, state.arch!);\n\n if (!state.ports.debug.remote\n || !state.ports.grpc.remote\n || !state.ports.minioPort.remote\n || !state.ports.minioConsolePort.remote\n || !state.ports.monitoring.remote\n || !state.ports.http?.remote) {\n throw new Error(`SshPl.platformaInit: remote ports are not defined`);\n }\n }\n\n private async doStepDownloadBinaries(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'downloadBinaries';\n await onProgress?.('Downloading and uploading required binaries...');\n\n const glibcVersion = await getGlibcVersion(this.logger, this.sshClient);\n if (glibcVersion < minRequiredGlibcVersion)\n throw new Error(`glibc version ${glibcVersion} is too old. Version ${minRequiredGlibcVersion} or higher is required for Platforma.`);\n\n const downloadRes = await this.downloadBinariesAndUploadToTheServer(\n ops.localWorkdir, ops.plBinary!, state.remoteHome!, state.arch!, state.shouldUseMinio ?? false,\n );\n await onProgress?.('All required binaries have been downloaded and uploaded.');\n\n state.binPaths = { ...downloadRes, history: undefined };\n state.downloadedBinaries = downloadRes.history;\n }\n\n private async doStepDetectArch(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectArch';\n await onProgress?.('Detecting server architecture...');\n state.arch = await this.getArch();\n await onProgress?.('Server architecture detected.');\n }\n\n private async doStepDetectHome(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectHome';\n await onProgress?.('Fetching user home directory...');\n state.remoteHome = await this.getUserHomeDirectory();\n await onProgress?.('User home directory retrieved.');\n }\n\n private async doStepReadExistedConfig(\n state: PlatformaInitState,\n ops: SshPlConfig,\n onProgress: ((...args: any) => Promise<any>) | undefined,\n ): Promise<boolean> {\n state.step = 'checkAlive';\n await onProgress?.('Checking platform status...');\n state.alive = await this.isAlive();\n\n if (!state.alive?.platforma) {\n return true;\n }\n\n await onProgress?.('All required services are running.');\n\n state.existedSettings = await this.readExistedConfig(state.remoteHome!);\n if (!state.existedSettings) {\n throw new Error(`SshPl.platformaInit: platforma is alive but existed settings are not found`);\n }\n\n const sameGA = state.existedSettings.useGlobalAccess == ops.useGlobalAccess;\n const samePlVersion = state.existedSettings.plVersion == ops.plBinary!.version;\n state.needRestart = !(sameGA && samePlVersion);\n this.logger.info(`SshPl.platformaInit: need restart? ${state.needRestart}`);\n\n state.shouldUseMinio = state.existedSettings.minioIsUsed;\n if (state.shouldUseMinio) {\n this.logger.info(`SshPl.platformaInit: minio is used`);\n } else {\n this.logger.info(`SshPl.platformaInit: minio is not used`);\n }\n\n if (!state.needRestart) {\n await onProgress?.('Server setup completed.');\n return false;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n\n return true;\n }\n\n public async downloadBinariesAndUploadToTheServer(\n localWorkdir: string,\n plBinary: PlBinarySourceDownload,\n remoteHome: string,\n arch: Arch,\n shouldUseMinio: boolean,\n ) {\n const state: DownloadAndUntarState[] = [];\n try {\n const pl = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'pl', `pl-${plBinary.version}`,\n );\n state.push(pl);\n\n const supervisor = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'supervisord', plpath.supervisordDirName,\n );\n state.push(supervisor);\n\n const minioPath = plpath.minioBin(remoteHome, arch.arch);\n if (shouldUseMinio) {\n const minio = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'minio', plpath.minioDirName,\n );\n state.push(minio);\n await this.sshClient.chmod(minioPath, 0o750);\n }\n\n return {\n history: state,\n minioRelPath: shouldUseMinio ? minioPath : undefined,\n downloadedPl: plpath.platformaBin(remoteHome, arch.arch),\n };\n } catch (e: unknown) {\n const msg = `SshPl.downloadBinariesAndUploadToServer: ${e}, state: ${JSON.stringify(state)}`;\n this.logger.error(msg);\n throw e;\n }\n }\n\n /** We have to extract pl in the remote server,\n * because Windows doesn't support symlinks\n * that are found in Linux pl binaries tgz archive.\n * For this reason, we extract all to the remote server.\n * It requires `tar` to be installed on the server\n * (it's not installed for Rocky Linux for example). */\n public async downloadAndUntar(\n localWorkdir: string,\n remoteHome: string,\n arch: Arch,\n softwareName: string,\n tgzName: string,\n ): Promise<DownloadAndUntarState> {\n const state: DownloadAndUntarState = {};\n state.binBasePath = plpath.binariesDir(remoteHome);\n await this.sshClient.ensureRemoteDirCreated(state.binBasePath);\n state.binBasePathCreated = true;\n\n let downloadBinaryResult: DownloadBinaryResult | null = null;\n const attempts = 5;\n for (let i = 1; i <= attempts; i++) {\n try {\n downloadBinaryResult = await downloadBinaryNoExtract({\n logger: this.logger,\n baseDir: localWorkdir,\n softwareName,\n tgzName,\n arch: arch.arch,\n platform: arch.platform,\n });\n break;\n } catch (e: unknown) {\n await sleep(300);\n if (i == attempts) {\n throw new Error(`downloadAndUntar: ${attempts} attempts, last error: ${e}`);\n }\n }\n }\n state.downloadResult = notEmpty(downloadBinaryResult);\n\n state.localArchivePath = upath.resolve(state.downloadResult.archivePath);\n state.remoteDir = upath.join(state.binBasePath, state.downloadResult.baseName);\n state.remoteArchivePath = state.remoteDir + '.tgz';\n\n await this.sshClient.ensureRemoteDirCreated(state.remoteDir);\n await this.sshClient.uploadFile(state.localArchivePath, state.remoteArchivePath);\n state.uploadDone = true;\n\n try {\n await this.sshClient.exec('hash tar');\n } catch (_) {\n throw new Error(`tar is not installed on the server. Please install it before running Platforma.`);\n }\n\n // TODO: Create a proper archive to avoid xattr warnings\n const untarResult = await this.sshClient.exec(\n `tar --warning=no-all -xvf ${state.remoteArchivePath} --directory=${state.remoteDir}`,\n );\n\n if (untarResult.stderr)\n throw new Error(`downloadAndUntar: untar: stderr occurred: ${untarResult.stderr}, stdout: ${untarResult.stdout}`);\n\n state.untarDone = true;\n\n return state;\n }\n\n public async needDownload(remoteHome: string, arch: Arch) {\n const checkPathSupervisor = plpath.supervisorBin(remoteHome, arch.arch);\n const checkPathMinio = plpath.minioDir(remoteHome, arch.arch);\n const checkPathPlatforma = plpath.platformaBin(remoteHome, arch.arch);\n\n if (!await this.sshClient.checkFileExists(checkPathPlatforma)\n || !await this.sshClient.checkFileExists(checkPathMinio)\n || !await this.sshClient.checkFileExists(checkPathSupervisor)) {\n return true;\n }\n\n return false;\n }\n\n public async checkIsAliveWithInterval(shouldUseMinio: boolean, interval: number = 1000, count = 15, shouldStart = true): Promise<void> {\n const maxMs = count * interval;\n\n let total = 0;\n let alive = await this.isAlive();\n while (shouldStart ? !isAllAlive(alive, shouldUseMinio) : isAllAlive(alive, shouldUseMinio)) {\n await sleep(interval);\n total += interval;\n if (total > maxMs) {\n throw new Error(`isAliveWithInterval: The process did not ${shouldStart ? 'started' : 'stopped'} after ${maxMs} ms. Live status: ${JSON.stringify(alive)}`);\n }\n alive = await this.isAlive();\n }\n }\n\n public async readExistedConfig(remoteHome: string): Promise<ConnectionInfo> {\n const connectionInfo = await this.sshClient.readFile(plpath.connectionInfo(remoteHome));\n return parseConnectionInfo(connectionInfo);\n }\n\n public async fetchPorts(remoteHome: string, arch: Arch): Promise<SshPlPorts> {\n const ports: SshPlPorts = {\n grpc: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n monitoring: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n debug: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n http: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioPort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioConsolePort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n };\n\n return ports;\n }\n\n public async getLocalFreePort(): Promise<number> {\n return new Promise((res) => {\n const srv = net.createServer();\n srv.listen(0, () => {\n const port = (srv.address() as net.AddressInfo).port;\n srv.close((_) => res(port));\n });\n });\n }\n\n public async getFreePortForPlatformaOnServer(remoteHome: string, arch: Arch): Promise<number> {\n const freePortBin = plpath.platformaFreePortBin(remoteHome, arch.arch);\n\n const { stdout, stderr } = await this.sshClient.exec(`${freePortBin}`);\n if (stderr) {\n throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n }\n\n return +stdout;\n }\n\n public async getArch(): Promise<Arch> {\n const { stdout, stderr } = await this.sshClient.exec('uname -s && uname -m');\n if (stderr)\n throw new Error(`getArch: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n\n const arr = stdout.split('\\n');\n\n return {\n platform: arr[0],\n arch: arr[1],\n };\n }\n\n public async getUserHomeDirectory() {\n const { stdout, stderr } = await this.sshClient.exec('echo $HOME');\n\n if (stderr) {\n const home = `/home/${this.username}`;\n console.warn(`getUserHomeDirectory: stderr is not empty: ${stderr}, stdout: ${stdout}, will get a default home: ${home}`);\n\n return home;\n }\n\n return stdout.trim();\n }\n}\n\ntype Arch = { platform: string; arch: string };\n\nexport type SshPlConfig = {\n localWorkdir: string;\n license: PlLicenseMode;\n useGlobalAccess?: boolean;\n plBinary?: PlBinarySourceDownload;\n\n onProgress?: (...args: any) => Promise<any>;\n plConfigPostprocessing?: (config: PlConfig) => PlConfig;\n};\n\nconst defaultSshPlConfig: Pick<\n SshPlConfig,\n | 'useGlobalAccess'\n | 'plBinary'\n> = {\n useGlobalAccess: false,\n plBinary: {\n type: 'Download',\n version: getDefaultPlVersion(),\n },\n};\n\ntype BinPaths = {\n history?: DownloadAndUntarState[];\n minioRelPath?: string;\n downloadedPl: string;\n};\n\ntype DownloadAndUntarState = {\n binBasePath?: string;\n binBasePathCreated?: boolean;\n downloadResult?: DownloadBinaryResult;\n attempts?: number;\n\n localArchivePath?: string;\n remoteDir?: string;\n remoteArchivePath?: string;\n uploadDone?: boolean;\n untarDone?: boolean;\n};\n\ntype PlatformaInitStep =\n 'init'\n | 'detectArch'\n | 'detectHome'\n | 'checkAlive'\n | 'stopExistedPlatforma'\n | 'downloadBinaries'\n | 'fetchPorts'\n | 'generateNewConfig'\n | 'createFoldersAndSaveFiles'\n | 'configureSupervisord'\n | 'saveNewConnectionInfo'\n | 'startPlatforma';\n\ntype PlatformaInitState = {\n step: PlatformaInitStep;\n localWorkdir?: string;\n plBinaryOps?: PlBinarySourceDownload;\n arch?: Arch;\n remoteHome?: string;\n alive?: SupervisorStatus;\n existedSettings?: ConnectionInfo;\n needRestart?: boolean;\n shouldUseMinio?: boolean;\n downloadedBinaries?: DownloadAndUntarState[];\n binPaths?: BinPaths;\n ports?: SshPlPorts;\n generatedConfig?: SshPlConfigGenerationResult;\n connectionInfo?: ConnectionInfo;\n started?: boolean;\n};\n\n/**\n * Gets the glibc version on the remote system\n * @returns The glibc version as a number\n * @throws Error if version cannot be determined\n */\nasync function getGlibcVersion(logger: MiLogger, sshClient: SshClient): Promise <number> {\n try {\n const { stdout, stderr } = await sshClient.exec('ldd --version | head -n 1');\n if (stderr) {\n throw new Error(`Failed to check glibc version: ${stderr}`);\n }\n return parseGlibcVersion(stdout);\n } catch (e: unknown) {\n logger.error(`glibc version check failed: ${e}`);\n throw e;\n }\n}\n\nexport function parseGlibcVersion(output: string): number {\n const versionMatch = output.match(/\\d+\\.\\d+/);\n if (!versionMatch) {\n throw new Error(`Could not parse glibc version from: ${output}`);\n }\n\n return parseFloat(versionMatch[0]);\n}\n"],"names":["SshClient","notEmpty","supervisorStatus","isAllAlive","supervisorCtlStart","plpath.platformaCliLogs","isSupervisordRunning","supervisorCtlShutdown","plpath.workDir","newConnectionInfo","plpath.connectionInfo","stringifyConnectionInfo","generateSupervisordConfigWithMinio","generateSupervisordConfig","plpath.supervisorConf","generateSshPlConfigs","plpath.supervisordDirName","plpath.minioBin","plpath.minioDirName","plpath.platformaBin","plpath.binariesDir","downloadBinaryNoExtract","sleep","plpath.supervisorBin","plpath.minioDir","parseConnectionInfo","getFreePort","plpath.platformaFreePortBin","getDefaultPlVersion"],"mappings":"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"}
1
+ {"version":3,"file":"pl.cjs","sources":["../../src/ssh/pl.ts"],"sourcesContent":["import type * as ssh from 'ssh2';\nimport { SshClient } from './ssh';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { sleep, notEmpty } from '@milaboratories/ts-helpers';\nimport type { DownloadBinaryResult } from '../common/pl_binary_download';\nimport { downloadBinaryNoExtract } from '../common/pl_binary_download';\nimport upath from 'upath';\nimport * as plpath from './pl_paths';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nimport net from 'node:net';\nimport type { PlConfig, PlLicenseMode, SshPlConfigGenerationResult } from '@milaboratories/pl-config';\nimport { getFreePort, generateSshPlConfigs } from '@milaboratories/pl-config';\nimport type { SupervisorStatus } from './supervisord';\nimport { supervisorStatus, supervisorStop as supervisorCtlShutdown, generateSupervisordConfigWithMinio, supervisorCtlStart, isSupervisordRunning, generateSupervisordConfig, isAllAlive } from './supervisord';\nimport type { ConnectionInfo, SshPlPorts } from './connection_info';\nimport { newConnectionInfo, parseConnectionInfo, stringifyConnectionInfo } from './connection_info';\nimport type { PlBinarySourceDownload } from '../common/pl_binary';\n\nconst minRequiredGlibcVersion = 2.28;\n\nexport class SshPl {\n private initState: PlatformaInitState = { step: 'init' };\n constructor(\n public readonly logger: MiLogger,\n public readonly sshClient: SshClient,\n private readonly username: string,\n ) { }\n\n public info() {\n return {\n username: this.username,\n initState: this.initState,\n };\n }\n\n public static async init(logger: MiLogger, config: ssh.ConnectConfig): Promise<SshPl> {\n try {\n const sshClient = await SshClient.init(logger, config);\n return new SshPl(logger, sshClient, notEmpty(config.username));\n } catch (e: unknown) {\n logger.error(`Connection error in SshClient.init: ${e}`);\n throw e;\n }\n }\n\n public cleanUp() {\n this.sshClient.close();\n }\n\n /** Provides an info if the platforma and minio are running along with the debug info. */\n public async isAlive(): Promise<SupervisorStatus> {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n return await supervisorStatus(this.logger, this.sshClient, remoteHome, arch.arch);\n }\n\n /** Starts all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async start(shouldUseMinio: boolean) {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n if (!isAllAlive(await this.isAlive(), shouldUseMinio)) {\n await supervisorCtlStart(this.sshClient, remoteHome, arch.arch);\n\n // We are waiting for Platforma to run to ensure that it has started.\n return await this.checkIsAliveWithInterval(shouldUseMinio);\n }\n } catch (e: unknown) {\n let msg = `SshPl.start: ${e}`;\n\n let logs = '';\n try {\n logs = await this.sshClient.readFile(plpath.platformaCliLogs(remoteHome));\n msg += `, platforma cli logs: ${logs}`;\n } catch (e: unknown) {\n msg += `, Can not read platforma cli logs: ${e}`;\n }\n\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async stop() {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n const alive = await this.isAlive();\n if (isSupervisordRunning(alive)) {\n await supervisorCtlShutdown(this.sshClient, remoteHome, arch.arch);\n // Check if Minio is running by looking at the alive status\n const shouldUseMinio = alive.minio === true;\n return await this.checkIsAliveWithInterval(shouldUseMinio, 1000, 15, false);\n }\n } catch (e: unknown) {\n const msg = `PlSsh.stop: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops the services, deletes a directory with the state and closes SSH connection. */\n public async reset(): Promise<boolean> {\n await this.stopAndClean();\n this.cleanUp();\n return true;\n }\n\n /** Stops platforma and deletes its state. */\n public async stopAndClean(): Promise<void> {\n const remoteHome = await this.getUserHomeDirectory();\n\n this.logger.info(`pl.reset: Stop Platforma on the server`);\n await this.stop();\n\n this.logger.info(`pl.reset: Deleting Platforma workDir ${plpath.workDir(remoteHome)} on the server`);\n await this.sshClient.deleteFolder(plpath.workDir(remoteHome));\n }\n\n /** Downloads binaries and untar them on the server,\n * generates all the configs, creates necessary dirs,\n * and finally starts all the services. */\n public async platformaInit(options: SshPlConfig): Promise<ConnectionInfo> {\n const state: PlatformaInitState = { localWorkdir: options.localWorkdir, step: 'init' };\n\n const { onProgress } = options;\n\n // merge options with default ops.\n const ops: SshPlConfig = {\n ...defaultSshPlConfig,\n ...options,\n };\n state.plBinaryOps = ops.plBinary;\n\n try {\n await this.doStepDetectArch(state, onProgress);\n await this.doStepDetectHome(state, onProgress);\n\n const needRestartPlatforma = await this.doStepReadExistedConfig(state, ops, onProgress);\n if (!needRestartPlatforma) {\n await onProgress?.('Platforma is already running. Skipping initialization.');\n return state.existedSettings!;\n }\n await this.doStepStopExistedPlatforma(state, onProgress);\n await this.doStepCheckDbLock(state, onProgress);\n\n await onProgress?.('Installation platforma...');\n\n await this.doStepDownloadBinaries(state, onProgress, ops);\n await this.doStepFetchPorts(state);\n await this.doStepGenerateNewConfig(state, onProgress, ops);\n await this.doStepCreateFoldersAndSaveFiles(state, onProgress);\n await this.doStepConfigureSupervisord(state, onProgress);\n await this.doStepSaveNewConnectionInfo(state, onProgress, ops);\n await this.doStepStartPlatforma(state, onProgress);\n\n return state.connectionInfo!;\n } catch (e: unknown) {\n const msg = `SshPl.platformaInit: ${e}, state: ${JSON.stringify(this.removeSensitiveData(state))}`;\n this.logger.error(msg);\n\n throw new Error(msg);\n }\n }\n\n private async doStepStopExistedPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'stopExistedPlatforma';\n if (!isAllAlive(state.alive!, state.shouldUseMinio ?? false)) {\n return;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n }\n\n private removeSensitiveData(state: PlatformaInitState): PlatformaInitState {\n const stateCopy = { ...state };\n stateCopy.generatedConfig = { ...stateCopy.generatedConfig, filesToCreate: { skipped: 'sanitized' } } as SshPlConfigGenerationResult;\n return stateCopy;\n }\n\n private async doStepStartPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'startPlatforma';\n await onProgress?.('Starting Platforma on the server...');\n await this.start(state.shouldUseMinio ?? false);\n state.started = true;\n this.initState = state;\n\n await onProgress?.('Platforma has been started successfully.');\n }\n\n private async doStepSaveNewConnectionInfo(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'saveNewConnectionInfo';\n const config = state.generatedConfig!;\n await onProgress?.('Saving connection information...');\n state.connectionInfo = newConnectionInfo(\n config.plUser,\n config.plPassword,\n state.ports!,\n notEmpty(ops.useGlobalAccess),\n ops.plBinary!.version,\n state.shouldUseMinio ?? false,\n );\n await this.sshClient.writeFileOnTheServer(\n plpath.connectionInfo(state.remoteHome!),\n stringifyConnectionInfo(state.connectionInfo),\n );\n await onProgress?.('Connection information saved.');\n }\n\n private async doStepCheckDbLock(\n state: PlatformaInitState,\n onProgress?: (...args: any[]) => Promise<any>,\n ) {\n const removeLockFile = async (lockFilePath: string) => {\n try {\n await this.sshClient.exec(`rm -f ${lockFilePath}`);\n this.logger.info(`Removed stale lock file ${lockFilePath}`);\n } catch (e: unknown) {\n const msg = `Failed to remove stale lock file ${lockFilePath}: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n };\n\n state.step = 'checkDbLock';\n await onProgress?.('Checking for DB lock...');\n\n const lockFilePath = plpath.platformaDbLock(state.remoteHome!);\n const lockFileExists = await this.sshClient.checkFileExists(lockFilePath);\n\n if (!lockFileExists) {\n await onProgress?.('No DB lock found. Proceeding...');\n return;\n }\n\n this.logger.info(`DB lock file found at ${lockFilePath}. Checking which process holds it...`);\n const lockProcessInfo = await this.findLockHolder(lockFilePath);\n\n if (!lockProcessInfo) {\n this.logger.warn('Lock file exists but no process is holding it. Removing stale lock file...');\n await removeLockFile(lockFilePath);\n return;\n }\n\n this.logger.info(\n `Found process ${lockProcessInfo.pid} (user: ${lockProcessInfo.user}) holding DB lock`,\n );\n\n if (lockProcessInfo.user !== this.username) {\n const msg\n = `DB lock is held by process ${lockProcessInfo.pid} `\n + `owned by user '${lockProcessInfo.user}', but current user is '${this.username}'. `\n + 'Cannot kill process owned by different user.';\n this.logger.error(msg);\n throw new Error(msg);\n }\n\n this.logger.info(`Process ${lockProcessInfo.pid} belongs to current user ${this.username}. Killing it...`);\n await this.killRemoteProcess(lockProcessInfo.pid);\n this.logger.info('Process holding DB lock has been terminated.');\n\n // Verify lock file is gone or can be removed\n const lockStillExists = await this.sshClient.checkFileExists(lockFilePath);\n if (lockStillExists) {\n await removeLockFile(lockFilePath);\n }\n }\n\n private async doStepConfigureSupervisord(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n await onProgress?.('Writing supervisord configuration...');\n state.step = 'configureSupervisord';\n\n const config = state.generatedConfig!;\n\n let supervisorConfig: string;\n if (state.shouldUseMinio) {\n supervisorConfig = generateSupervisordConfigWithMinio(\n config.minioConfig.storageDir,\n config.minioConfig.envs,\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.minioRelPath!,\n state.binPaths!.downloadedPl,\n );\n } else {\n supervisorConfig = generateSupervisordConfig(\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.downloadedPl,\n );\n }\n\n const writeResult = await this.sshClient.writeFileOnTheServer(plpath.supervisorConf(state.remoteHome!), supervisorConfig);\n if (!writeResult) {\n throw new Error(`Can not write supervisord config on the server ${plpath.workDir(state.remoteHome!)}`);\n }\n await onProgress?.('Supervisord configuration written.');\n }\n\n private async doStepCreateFoldersAndSaveFiles(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'createFoldersAndSaveFiles';\n const config = state.generatedConfig!;\n await onProgress?.('Generating folder structure...');\n for (const [filePath, content] of Object.entries(config.filesToCreate)) {\n await this.sshClient.writeFileOnTheServer(filePath, content);\n this.logger.info(`Created file ${filePath}`);\n }\n\n for (const dir of config.dirsToCreate) {\n await this.sshClient.ensureRemoteDirCreated(dir);\n this.logger.info(`Created directory ${dir}`);\n }\n await onProgress?.('Folder structure created.');\n }\n\n private async doStepGenerateNewConfig(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'generateNewConfig';\n\n await onProgress?.('Generating new config...');\n const config = await generateSshPlConfigs({\n logger: this.logger,\n workingDir: plpath.workDir(state.remoteHome!),\n portsMode: {\n type: 'customWithMinio',\n ports: {\n debug: state.ports!.debug.remote,\n grpc: state.ports!.grpc.remote,\n http: state.ports!.http!.remote,\n minio: state.ports!.minioPort.remote,\n minioConsole: state.ports!.minioConsolePort.remote,\n monitoring: state.ports!.monitoring.remote,\n\n httpLocal: state.ports!.http!.local,\n grpcLocal: state.ports!.grpc.local,\n minioLocal: state.ports!.minioPort.local,\n },\n },\n licenseMode: ops.license,\n useGlobalAccess: notEmpty(ops.useGlobalAccess),\n plConfigPostprocessing: ops.plConfigPostprocessing,\n useMinio: state.shouldUseMinio ?? false,\n });\n state.generatedConfig = { ...config };\n await onProgress?.('New config generated');\n }\n\n private async doStepFetchPorts(state: PlatformaInitState) {\n state.step = 'fetchPorts';\n state.ports = await this.fetchPorts(state.remoteHome!, state.arch!);\n\n if (!state.ports.debug.remote\n || !state.ports.grpc.remote\n || !state.ports.minioPort.remote\n || !state.ports.minioConsolePort.remote\n || !state.ports.monitoring.remote\n || !state.ports.http?.remote) {\n throw new Error(`SshPl.platformaInit: remote ports are not defined`);\n }\n }\n\n private async doStepDownloadBinaries(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'downloadBinaries';\n await onProgress?.('Downloading and uploading required binaries...');\n\n const glibcVersion = await getGlibcVersion(this.logger, this.sshClient);\n if (glibcVersion < minRequiredGlibcVersion)\n throw new Error(`glibc version ${glibcVersion} is too old. Version ${minRequiredGlibcVersion} or higher is required for Platforma.`);\n\n const downloadRes = await this.downloadBinariesAndUploadToTheServer(\n ops.localWorkdir, ops.plBinary!, state.remoteHome!, state.arch!, state.shouldUseMinio ?? false,\n );\n await onProgress?.('All required binaries have been downloaded and uploaded.');\n\n state.binPaths = { ...downloadRes, history: undefined };\n state.downloadedBinaries = downloadRes.history;\n }\n\n private async doStepDetectArch(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectArch';\n await onProgress?.('Detecting server architecture...');\n state.arch = await this.getArch();\n await onProgress?.('Server architecture detected.');\n }\n\n private async doStepDetectHome(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectHome';\n await onProgress?.('Fetching user home directory...');\n state.remoteHome = await this.getUserHomeDirectory();\n await onProgress?.('User home directory retrieved.');\n }\n\n private async doStepReadExistedConfig(\n state: PlatformaInitState,\n ops: SshPlConfig,\n onProgress: ((...args: any) => Promise<any>) | undefined,\n ): Promise<boolean> {\n state.step = 'checkAlive';\n await onProgress?.('Checking platform status...');\n state.alive = await this.isAlive();\n\n if (!state.alive?.platforma) {\n return true;\n }\n\n await onProgress?.('All required services are running.');\n\n state.existedSettings = await this.readExistedConfig(state.remoteHome!);\n if (!state.existedSettings) {\n throw new Error(`SshPl.platformaInit: platforma is alive but existed settings are not found`);\n }\n\n const sameGA = state.existedSettings.useGlobalAccess == ops.useGlobalAccess;\n const samePlVersion = state.existedSettings.plVersion == ops.plBinary!.version;\n state.needRestart = !(sameGA && samePlVersion);\n this.logger.info(`SshPl.platformaInit: need restart? ${state.needRestart}`);\n\n state.shouldUseMinio = state.existedSettings.minioIsUsed;\n if (state.shouldUseMinio) {\n this.logger.info(`SshPl.platformaInit: minio is used`);\n } else {\n this.logger.info(`SshPl.platformaInit: minio is not used`);\n }\n\n if (!state.needRestart) {\n await onProgress?.('Server setup completed.');\n return false;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n\n return true;\n }\n\n public async downloadBinariesAndUploadToTheServer(\n localWorkdir: string,\n plBinary: PlBinarySourceDownload,\n remoteHome: string,\n arch: Arch,\n shouldUseMinio: boolean,\n ) {\n const state: DownloadAndUntarState[] = [];\n try {\n const pl = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'pl', `pl-${plBinary.version}`,\n );\n state.push(pl);\n\n const supervisor = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'supervisord', plpath.supervisordDirName,\n );\n state.push(supervisor);\n\n const minioPath = plpath.minioBin(remoteHome, arch.arch);\n if (shouldUseMinio) {\n const minio = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'minio', plpath.minioDirName,\n );\n state.push(minio);\n await this.sshClient.chmod(minioPath, 0o750);\n }\n\n return {\n history: state,\n minioRelPath: shouldUseMinio ? minioPath : undefined,\n downloadedPl: plpath.platformaBin(remoteHome, arch.arch),\n };\n } catch (e: unknown) {\n const msg = `SshPl.downloadBinariesAndUploadToServer: ${e}, state: ${JSON.stringify(state)}`;\n this.logger.error(msg);\n throw e;\n }\n }\n\n private async findLockHolderWithLsof(lockFilePath: string): Promise<LockProcessInfo | null> {\n try {\n const { stdout } = await this.sshClient.exec(`lsof ${lockFilePath} 2>/dev/null || true`);\n const output = stdout.trim();\n if (!output) {\n return null;\n }\n\n // Example:\n // COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n // platforma 11628 rfiskov 10u REG 1,16 0 66670038 ./LOCK\n const lines = output.split('\\n');\n if (lines.length <= 1) {\n return null;\n }\n\n const parts = lines[1].trim().split(/\\s+/);\n if (parts.length < 3) {\n return null;\n }\n\n const pid = Number.parseInt(parts[1], 10);\n const user = parts[2];\n\n return Number.isNaN(pid) || !user ? null : { pid, user };\n } catch (e: unknown) {\n this.logger.warn(`Failed to use lsof to check lock: ${e}`);\n return null;\n }\n }\n\n private async findLockHolderWithFuser(lockFilePath: string): Promise<LockProcessInfo | null> {\n try {\n const { stdout } = await this.sshClient.exec(`fuser ${lockFilePath} 2>/dev/null || true`);\n const output = stdout.trim();\n if (!output) {\n return null;\n }\n\n // Example: ./LOCK: 11628\n const match = output.match(/: (\\d+)/);\n if (!match) {\n return null;\n }\n\n const pid = Number.parseInt(match[1], 10);\n if (Number.isNaN(pid)) {\n return null;\n }\n\n try {\n const psResult = await this.sshClient.exec(`ps -o user= -p ${pid} 2>/dev/null || true`);\n const user = psResult.stdout.trim();\n return user ? { pid, user } : null;\n } catch (e: unknown) {\n this.logger.warn(`Failed to get user for PID ${pid}: ${e}`);\n return null;\n }\n } catch (e: unknown) {\n this.logger.warn(`Failed to use fuser to check lock: ${e}`);\n return null;\n }\n }\n\n private async findLockHolder(lockFilePath: string): Promise<LockProcessInfo | null> {\n const viaLsof = await this.findLockHolderWithLsof(lockFilePath);\n if (viaLsof) {\n return viaLsof;\n }\n return this.findLockHolderWithFuser(lockFilePath);\n }\n\n private async killRemoteProcess(pid: number): Promise<void> {\n this.logger.info(`Killing process ${pid}...`);\n\n try {\n // Try graceful termination first\n await this.sshClient.exec(`kill ${pid} 2>/dev/null || true`);\n await sleep(1000);\n\n // Check if process still exists\n try {\n await this.sshClient.exec(`kill -0 ${pid} 2>/dev/null`);\n // Process still exists, force kill\n this.logger.warn(`Process ${pid} still alive after SIGTERM, forcing kill...`);\n await this.sshClient.exec(`kill -9 ${pid} 2>/dev/null || true`);\n await sleep(500);\n } catch {\n // Process is dead, nothing to do\n }\n } catch (e: unknown) {\n const msg = `Failed to kill process ${pid}: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** We have to extract pl in the remote server,\n * because Windows doesn't support symlinks\n * that are found in Linux pl binaries tgz archive.\n * For this reason, we extract all to the remote server.\n * It requires `tar` to be installed on the server\n * (it's not installed for Rocky Linux for example). */\n public async downloadAndUntar(\n localWorkdir: string,\n remoteHome: string,\n arch: Arch,\n softwareName: string,\n tgzName: string,\n ): Promise<DownloadAndUntarState> {\n const state: DownloadAndUntarState = {};\n state.binBasePath = plpath.binariesDir(remoteHome);\n await this.sshClient.ensureRemoteDirCreated(state.binBasePath);\n state.binBasePathCreated = true;\n\n let downloadBinaryResult: DownloadBinaryResult | null = null;\n const attempts = 5;\n for (let i = 1; i <= attempts; i++) {\n try {\n downloadBinaryResult = await downloadBinaryNoExtract({\n logger: this.logger,\n baseDir: localWorkdir,\n softwareName,\n tgzName,\n arch: arch.arch,\n platform: arch.platform,\n });\n break;\n } catch (e: unknown) {\n await sleep(300);\n if (i == attempts) {\n throw new Error(`downloadAndUntar: ${attempts} attempts, last error: ${e}`);\n }\n }\n }\n state.downloadResult = notEmpty(downloadBinaryResult);\n\n state.localArchivePath = upath.resolve(state.downloadResult.archivePath);\n state.remoteDir = upath.join(state.binBasePath, state.downloadResult.baseName);\n state.remoteArchivePath = state.remoteDir + '.tgz';\n\n await this.sshClient.ensureRemoteDirCreated(state.remoteDir);\n await this.sshClient.uploadFile(state.localArchivePath, state.remoteArchivePath);\n state.uploadDone = true;\n\n try {\n await this.sshClient.exec('hash tar');\n } catch (_) {\n throw new Error(`tar is not installed on the server. Please install it before running Platforma.`);\n }\n\n // TODO: Create a proper archive to avoid xattr warnings\n const untarResult = await this.sshClient.exec(\n `tar --warning=no-all -xvf ${state.remoteArchivePath} --directory=${state.remoteDir}`,\n );\n\n if (untarResult.stderr)\n throw new Error(`downloadAndUntar: untar: stderr occurred: ${untarResult.stderr}, stdout: ${untarResult.stdout}`);\n\n state.untarDone = true;\n\n return state;\n }\n\n public async needDownload(remoteHome: string, arch: Arch) {\n const checkPathSupervisor = plpath.supervisorBin(remoteHome, arch.arch);\n const checkPathMinio = plpath.minioDir(remoteHome, arch.arch);\n const checkPathPlatforma = plpath.platformaBin(remoteHome, arch.arch);\n\n if (!await this.sshClient.checkFileExists(checkPathPlatforma)\n || !await this.sshClient.checkFileExists(checkPathMinio)\n || !await this.sshClient.checkFileExists(checkPathSupervisor)) {\n return true;\n }\n\n return false;\n }\n\n public async checkIsAliveWithInterval(shouldUseMinio: boolean, interval: number = 1000, count = 15, shouldStart = true): Promise<void> {\n const maxMs = count * interval;\n\n let total = 0;\n let alive = await this.isAlive();\n while (shouldStart ? !isAllAlive(alive, shouldUseMinio) : isAllAlive(alive, shouldUseMinio)) {\n await sleep(interval);\n total += interval;\n if (total > maxMs) {\n throw new Error(`isAliveWithInterval: The process did not ${shouldStart ? 'started' : 'stopped'} after ${maxMs} ms. Live status: ${JSON.stringify(alive)}`);\n }\n alive = await this.isAlive();\n }\n }\n\n public async readExistedConfig(remoteHome: string): Promise<ConnectionInfo> {\n const connectionInfo = await this.sshClient.readFile(plpath.connectionInfo(remoteHome));\n return parseConnectionInfo(connectionInfo);\n }\n\n public async fetchPorts(remoteHome: string, arch: Arch): Promise<SshPlPorts> {\n const ports: SshPlPorts = {\n grpc: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n monitoring: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n debug: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n http: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioPort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioConsolePort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n };\n\n return ports;\n }\n\n public async getLocalFreePort(): Promise<number> {\n return new Promise((res) => {\n const srv = net.createServer();\n srv.listen(0, () => {\n const port = (srv.address() as net.AddressInfo).port;\n srv.close((_) => res(port));\n });\n });\n }\n\n public async getFreePortForPlatformaOnServer(remoteHome: string, arch: Arch): Promise<number> {\n const freePortBin = plpath.platformaFreePortBin(remoteHome, arch.arch);\n\n const { stdout, stderr } = await this.sshClient.exec(`${freePortBin}`);\n if (stderr) {\n throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n }\n\n return +stdout;\n }\n\n public async getArch(): Promise<Arch> {\n const { stdout, stderr } = await this.sshClient.exec('uname -s && uname -m');\n if (stderr)\n throw new Error(`getArch: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n\n const arr = stdout.split('\\n');\n\n return {\n platform: arr[0],\n arch: arr[1],\n };\n }\n\n public async getUserHomeDirectory() {\n const { stdout, stderr } = await this.sshClient.exec('echo $HOME');\n\n if (stderr) {\n const home = `/home/${this.username}`;\n console.warn(`getUserHomeDirectory: stderr is not empty: ${stderr}, stdout: ${stdout}, will get a default home: ${home}`);\n\n return home;\n }\n\n return stdout.trim();\n }\n}\n\ntype Arch = { platform: string; arch: string };\n\nexport type SshPlConfig = {\n localWorkdir: string;\n license: PlLicenseMode;\n useGlobalAccess?: boolean;\n plBinary?: PlBinarySourceDownload;\n\n onProgress?: (...args: any) => Promise<any>;\n plConfigPostprocessing?: (config: PlConfig) => PlConfig;\n};\n\nexport type LockProcessInfo = { pid: number; user: string };\n\nconst defaultSshPlConfig: Pick<\n SshPlConfig,\n | 'useGlobalAccess'\n | 'plBinary'\n> = {\n useGlobalAccess: false,\n plBinary: {\n type: 'Download',\n version: getDefaultPlVersion(),\n },\n};\n\ntype BinPaths = {\n history?: DownloadAndUntarState[];\n minioRelPath?: string;\n downloadedPl: string;\n};\n\ntype DownloadAndUntarState = {\n binBasePath?: string;\n binBasePathCreated?: boolean;\n downloadResult?: DownloadBinaryResult;\n attempts?: number;\n\n localArchivePath?: string;\n remoteDir?: string;\n remoteArchivePath?: string;\n uploadDone?: boolean;\n untarDone?: boolean;\n};\n\ntype PlatformaInitStep =\n 'init'\n | 'detectArch'\n | 'detectHome'\n | 'checkAlive'\n | 'stopExistedPlatforma'\n | 'checkDbLock'\n | 'downloadBinaries'\n | 'fetchPorts'\n | 'generateNewConfig'\n | 'createFoldersAndSaveFiles'\n | 'configureSupervisord'\n | 'saveNewConnectionInfo'\n | 'startPlatforma';\n\ntype PlatformaInitState = {\n step: PlatformaInitStep;\n localWorkdir?: string;\n plBinaryOps?: PlBinarySourceDownload;\n arch?: Arch;\n remoteHome?: string;\n alive?: SupervisorStatus;\n existedSettings?: ConnectionInfo;\n needRestart?: boolean;\n shouldUseMinio?: boolean;\n downloadedBinaries?: DownloadAndUntarState[];\n binPaths?: BinPaths;\n ports?: SshPlPorts;\n generatedConfig?: SshPlConfigGenerationResult;\n connectionInfo?: ConnectionInfo;\n started?: boolean;\n};\n\n/**\n * Gets the glibc version on the remote system\n * @returns The glibc version as a number\n * @throws Error if version cannot be determined\n */\nasync function getGlibcVersion(logger: MiLogger, sshClient: SshClient): Promise <number> {\n try {\n const { stdout, stderr } = await sshClient.exec('ldd --version | head -n 1');\n if (stderr) {\n throw new Error(`Failed to check glibc version: ${stderr}`);\n }\n return parseGlibcVersion(stdout);\n } catch (e: unknown) {\n logger.error(`glibc version check failed: ${e}`);\n throw e;\n }\n}\n\nexport function parseGlibcVersion(output: string): number {\n const versionMatch = output.match(/\\d+\\.\\d+/);\n if (!versionMatch) {\n throw new Error(`Could not parse glibc version from: ${output}`);\n }\n\n return parseFloat(versionMatch[0]);\n}\n"],"names":["SshClient","notEmpty","supervisorStatus","isAllAlive","supervisorCtlStart","plpath.platformaCliLogs","isSupervisordRunning","supervisorCtlShutdown","plpath.workDir","newConnectionInfo","plpath.connectionInfo","stringifyConnectionInfo","plpath.platformaDbLock","generateSupervisordConfigWithMinio","generateSupervisordConfig","plpath.supervisorConf","generateSshPlConfigs","plpath.supervisordDirName","plpath.minioBin","plpath.minioDirName","plpath.platformaBin","sleep","plpath.binariesDir","downloadBinaryNoExtract","plpath.supervisorBin","plpath.minioDir","parseConnectionInfo","getFreePort","plpath.platformaFreePortBin","getDefaultPlVersion"],"mappings":"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"}
package/dist/ssh/pl.d.ts CHANGED
@@ -38,6 +38,7 @@ export declare class SshPl {
38
38
  private removeSensitiveData;
39
39
  private doStepStartPlatforma;
40
40
  private doStepSaveNewConnectionInfo;
41
+ private doStepCheckDbLock;
41
42
  private doStepConfigureSupervisord;
42
43
  private doStepCreateFoldersAndSaveFiles;
43
44
  private doStepGenerateNewConfig;
@@ -51,6 +52,10 @@ export declare class SshPl {
51
52
  minioRelPath: string | undefined;
52
53
  downloadedPl: string;
53
54
  }>;
55
+ private findLockHolderWithLsof;
56
+ private findLockHolderWithFuser;
57
+ private findLockHolder;
58
+ private killRemoteProcess;
54
59
  /** We have to extract pl in the remote server,
55
60
  * because Windows doesn't support symlinks
56
61
  * that are found in Linux pl binaries tgz archive.
@@ -79,6 +84,10 @@ export type SshPlConfig = {
79
84
  onProgress?: (...args: any) => Promise<any>;
80
85
  plConfigPostprocessing?: (config: PlConfig) => PlConfig;
81
86
  };
87
+ export type LockProcessInfo = {
88
+ pid: number;
89
+ user: string;
90
+ };
82
91
  type BinPaths = {
83
92
  history?: DownloadAndUntarState[];
84
93
  minioRelPath?: string;
@@ -95,7 +104,7 @@ type DownloadAndUntarState = {
95
104
  uploadDone?: boolean;
96
105
  untarDone?: boolean;
97
106
  };
98
- type PlatformaInitStep = 'init' | 'detectArch' | 'detectHome' | 'checkAlive' | 'stopExistedPlatforma' | 'downloadBinaries' | 'fetchPorts' | 'generateNewConfig' | 'createFoldersAndSaveFiles' | 'configureSupervisord' | 'saveNewConnectionInfo' | 'startPlatforma';
107
+ type PlatformaInitStep = 'init' | 'detectArch' | 'detectHome' | 'checkAlive' | 'stopExistedPlatforma' | 'checkDbLock' | 'downloadBinaries' | 'fetchPorts' | 'generateNewConfig' | 'createFoldersAndSaveFiles' | 'configureSupervisord' | 'saveNewConnectionInfo' | 'startPlatforma';
99
108
  type PlatformaInitState = {
100
109
  step: PlatformaInitStep;
101
110
  localWorkdir?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pl.d.ts","sourceRoot":"","sources":["../../src/ssh/pl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pl.d.ts","sourceRoot":"","sources":["../../src/ssh/pl.ts"],"names":[],"mappings":"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"}
package/dist/ssh/pl.js CHANGED
@@ -2,7 +2,7 @@ import { SshClient } from './ssh.js';
2
2
  import { notEmpty, sleep } from '@milaboratories/ts-helpers';
3
3
  import { downloadBinaryNoExtract } from '../common/pl_binary_download.js';
4
4
  import upath from 'upath';
5
- import { platformaCliLogs, workDir, connectionInfo, supervisorConf, supervisordDirName, minioBin, minioDirName, platformaBin, binariesDir, supervisorBin, minioDir, platformaFreePortBin } from './pl_paths.js';
5
+ import { platformaCliLogs, workDir, connectionInfo, platformaDbLock, supervisorConf, supervisordDirName, minioBin, minioDirName, platformaBin, binariesDir, supervisorBin, minioDir, platformaFreePortBin } from './pl_paths.js';
6
6
  import { getDefaultPlVersion } from '../common/pl_version.js';
7
7
  import net from 'node:net';
8
8
  import { generateSshPlConfigs, getFreePort } from '@milaboratories/pl-config';
@@ -126,6 +126,7 @@ class SshPl {
126
126
  return state.existedSettings;
127
127
  }
128
128
  await this.doStepStopExistedPlatforma(state, onProgress);
129
+ await this.doStepCheckDbLock(state, onProgress);
129
130
  await onProgress?.('Installation platforma...');
130
131
  await this.doStepDownloadBinaries(state, onProgress, ops);
131
132
  await this.doStepFetchPorts(state);
@@ -171,6 +172,50 @@ class SshPl {
171
172
  await this.sshClient.writeFileOnTheServer(connectionInfo(state.remoteHome), stringifyConnectionInfo(state.connectionInfo));
172
173
  await onProgress?.('Connection information saved.');
173
174
  }
175
+ async doStepCheckDbLock(state, onProgress) {
176
+ const removeLockFile = async (lockFilePath) => {
177
+ try {
178
+ await this.sshClient.exec(`rm -f ${lockFilePath}`);
179
+ this.logger.info(`Removed stale lock file ${lockFilePath}`);
180
+ }
181
+ catch (e) {
182
+ const msg = `Failed to remove stale lock file ${lockFilePath}: ${e}`;
183
+ this.logger.error(msg);
184
+ throw new Error(msg);
185
+ }
186
+ };
187
+ state.step = 'checkDbLock';
188
+ await onProgress?.('Checking for DB lock...');
189
+ const lockFilePath = platformaDbLock(state.remoteHome);
190
+ const lockFileExists = await this.sshClient.checkFileExists(lockFilePath);
191
+ if (!lockFileExists) {
192
+ await onProgress?.('No DB lock found. Proceeding...');
193
+ return;
194
+ }
195
+ this.logger.info(`DB lock file found at ${lockFilePath}. Checking which process holds it...`);
196
+ const lockProcessInfo = await this.findLockHolder(lockFilePath);
197
+ if (!lockProcessInfo) {
198
+ this.logger.warn('Lock file exists but no process is holding it. Removing stale lock file...');
199
+ await removeLockFile(lockFilePath);
200
+ return;
201
+ }
202
+ this.logger.info(`Found process ${lockProcessInfo.pid} (user: ${lockProcessInfo.user}) holding DB lock`);
203
+ if (lockProcessInfo.user !== this.username) {
204
+ const msg = `DB lock is held by process ${lockProcessInfo.pid} `
205
+ + `owned by user '${lockProcessInfo.user}', but current user is '${this.username}'. `
206
+ + 'Cannot kill process owned by different user.';
207
+ this.logger.error(msg);
208
+ throw new Error(msg);
209
+ }
210
+ this.logger.info(`Process ${lockProcessInfo.pid} belongs to current user ${this.username}. Killing it...`);
211
+ await this.killRemoteProcess(lockProcessInfo.pid);
212
+ this.logger.info('Process holding DB lock has been terminated.');
213
+ // Verify lock file is gone or can be removed
214
+ const lockStillExists = await this.sshClient.checkFileExists(lockFilePath);
215
+ if (lockStillExists) {
216
+ await removeLockFile(lockFilePath);
217
+ }
218
+ }
174
219
  async doStepConfigureSupervisord(state, onProgress) {
175
220
  await onProgress?.('Writing supervisord configuration...');
176
221
  state.step = 'configureSupervisord';
@@ -321,6 +366,95 @@ class SshPl {
321
366
  throw e;
322
367
  }
323
368
  }
369
+ async findLockHolderWithLsof(lockFilePath) {
370
+ try {
371
+ const { stdout } = await this.sshClient.exec(`lsof ${lockFilePath} 2>/dev/null || true`);
372
+ const output = stdout.trim();
373
+ if (!output) {
374
+ return null;
375
+ }
376
+ // Example:
377
+ // COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
378
+ // platforma 11628 rfiskov 10u REG 1,16 0 66670038 ./LOCK
379
+ const lines = output.split('\n');
380
+ if (lines.length <= 1) {
381
+ return null;
382
+ }
383
+ const parts = lines[1].trim().split(/\s+/);
384
+ if (parts.length < 3) {
385
+ return null;
386
+ }
387
+ const pid = Number.parseInt(parts[1], 10);
388
+ const user = parts[2];
389
+ return Number.isNaN(pid) || !user ? null : { pid, user };
390
+ }
391
+ catch (e) {
392
+ this.logger.warn(`Failed to use lsof to check lock: ${e}`);
393
+ return null;
394
+ }
395
+ }
396
+ async findLockHolderWithFuser(lockFilePath) {
397
+ try {
398
+ const { stdout } = await this.sshClient.exec(`fuser ${lockFilePath} 2>/dev/null || true`);
399
+ const output = stdout.trim();
400
+ if (!output) {
401
+ return null;
402
+ }
403
+ // Example: ./LOCK: 11628
404
+ const match = output.match(/: (\d+)/);
405
+ if (!match) {
406
+ return null;
407
+ }
408
+ const pid = Number.parseInt(match[1], 10);
409
+ if (Number.isNaN(pid)) {
410
+ return null;
411
+ }
412
+ try {
413
+ const psResult = await this.sshClient.exec(`ps -o user= -p ${pid} 2>/dev/null || true`);
414
+ const user = psResult.stdout.trim();
415
+ return user ? { pid, user } : null;
416
+ }
417
+ catch (e) {
418
+ this.logger.warn(`Failed to get user for PID ${pid}: ${e}`);
419
+ return null;
420
+ }
421
+ }
422
+ catch (e) {
423
+ this.logger.warn(`Failed to use fuser to check lock: ${e}`);
424
+ return null;
425
+ }
426
+ }
427
+ async findLockHolder(lockFilePath) {
428
+ const viaLsof = await this.findLockHolderWithLsof(lockFilePath);
429
+ if (viaLsof) {
430
+ return viaLsof;
431
+ }
432
+ return this.findLockHolderWithFuser(lockFilePath);
433
+ }
434
+ async killRemoteProcess(pid) {
435
+ this.logger.info(`Killing process ${pid}...`);
436
+ try {
437
+ // Try graceful termination first
438
+ await this.sshClient.exec(`kill ${pid} 2>/dev/null || true`);
439
+ await sleep(1000);
440
+ // Check if process still exists
441
+ try {
442
+ await this.sshClient.exec(`kill -0 ${pid} 2>/dev/null`);
443
+ // Process still exists, force kill
444
+ this.logger.warn(`Process ${pid} still alive after SIGTERM, forcing kill...`);
445
+ await this.sshClient.exec(`kill -9 ${pid} 2>/dev/null || true`);
446
+ await sleep(500);
447
+ }
448
+ catch {
449
+ // Process is dead, nothing to do
450
+ }
451
+ }
452
+ catch (e) {
453
+ const msg = `Failed to kill process ${pid}: ${e}`;
454
+ this.logger.error(msg);
455
+ throw new Error(msg);
456
+ }
457
+ }
324
458
  /** We have to extract pl in the remote server,
325
459
  * because Windows doesn't support symlinks
326
460
  * that are found in Linux pl binaries tgz archive.
@@ -1 +1 @@
1
- {"version":3,"file":"pl.js","sources":["../../src/ssh/pl.ts"],"sourcesContent":["import type * as ssh from 'ssh2';\nimport { SshClient } from './ssh';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { sleep, notEmpty } from '@milaboratories/ts-helpers';\nimport type { DownloadBinaryResult } from '../common/pl_binary_download';\nimport { downloadBinaryNoExtract } from '../common/pl_binary_download';\nimport upath from 'upath';\nimport * as plpath from './pl_paths';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nimport net from 'node:net';\nimport type { PlConfig, PlLicenseMode, SshPlConfigGenerationResult } from '@milaboratories/pl-config';\nimport { getFreePort, generateSshPlConfigs } from '@milaboratories/pl-config';\nimport type { SupervisorStatus } from './supervisord';\nimport { supervisorStatus, supervisorStop as supervisorCtlShutdown, generateSupervisordConfigWithMinio, supervisorCtlStart, isSupervisordRunning, generateSupervisordConfig, isAllAlive } from './supervisord';\nimport type { ConnectionInfo, SshPlPorts } from './connection_info';\nimport { newConnectionInfo, parseConnectionInfo, stringifyConnectionInfo } from './connection_info';\nimport type { PlBinarySourceDownload } from '../common/pl_binary';\n\nconst minRequiredGlibcVersion = 2.28;\n\nexport class SshPl {\n private initState: PlatformaInitState = { step: 'init' };\n constructor(\n public readonly logger: MiLogger,\n public readonly sshClient: SshClient,\n private readonly username: string,\n ) { }\n\n public info() {\n return {\n username: this.username,\n initState: this.initState,\n };\n }\n\n public static async init(logger: MiLogger, config: ssh.ConnectConfig): Promise<SshPl> {\n try {\n const sshClient = await SshClient.init(logger, config);\n return new SshPl(logger, sshClient, notEmpty(config.username));\n } catch (e: unknown) {\n logger.error(`Connection error in SshClient.init: ${e}`);\n throw e;\n }\n }\n\n public cleanUp() {\n this.sshClient.close();\n }\n\n /** Provides an info if the platforma and minio are running along with the debug info. */\n public async isAlive(): Promise<SupervisorStatus> {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n return await supervisorStatus(this.logger, this.sshClient, remoteHome, arch.arch);\n }\n\n /** Starts all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async start(shouldUseMinio: boolean) {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n if (!isAllAlive(await this.isAlive(), shouldUseMinio)) {\n await supervisorCtlStart(this.sshClient, remoteHome, arch.arch);\n\n // We are waiting for Platforma to run to ensure that it has started.\n return await this.checkIsAliveWithInterval(shouldUseMinio);\n }\n } catch (e: unknown) {\n let msg = `SshPl.start: ${e}`;\n\n let logs = '';\n try {\n logs = await this.sshClient.readFile(plpath.platformaCliLogs(remoteHome));\n msg += `, platforma cli logs: ${logs}`;\n } catch (e: unknown) {\n msg += `, Can not read platforma cli logs: ${e}`;\n }\n\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async stop() {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n const alive = await this.isAlive();\n if (isSupervisordRunning(alive)) {\n await supervisorCtlShutdown(this.sshClient, remoteHome, arch.arch);\n // Check if Minio is running by looking at the alive status\n const shouldUseMinio = alive.minio === true;\n return await this.checkIsAliveWithInterval(shouldUseMinio, 1000, 15, false);\n }\n } catch (e: unknown) {\n const msg = `PlSsh.stop: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops the services, deletes a directory with the state and closes SSH connection. */\n public async reset(): Promise<boolean> {\n await this.stopAndClean();\n this.cleanUp();\n return true;\n }\n\n /** Stops platforma and deletes its state. */\n public async stopAndClean(): Promise<void> {\n const remoteHome = await this.getUserHomeDirectory();\n\n this.logger.info(`pl.reset: Stop Platforma on the server`);\n await this.stop();\n\n this.logger.info(`pl.reset: Deleting Platforma workDir ${plpath.workDir(remoteHome)} on the server`);\n await this.sshClient.deleteFolder(plpath.workDir(remoteHome));\n }\n\n /** Downloads binaries and untar them on the server,\n * generates all the configs, creates necessary dirs,\n * and finally starts all the services. */\n public async platformaInit(options: SshPlConfig): Promise<ConnectionInfo> {\n const state: PlatformaInitState = { localWorkdir: options.localWorkdir, step: 'init' };\n\n const { onProgress } = options;\n\n // merge options with default ops.\n const ops: SshPlConfig = {\n ...defaultSshPlConfig,\n ...options,\n };\n state.plBinaryOps = ops.plBinary;\n\n try {\n await this.doStepDetectArch(state, onProgress);\n await this.doStepDetectHome(state, onProgress);\n\n const needRestartPlatforma = await this.doStepReadExistedConfig(state, ops, onProgress);\n if (!needRestartPlatforma) {\n await onProgress?.('Platforma is already running. Skipping initialization.');\n return state.existedSettings!;\n }\n await this.doStepStopExistedPlatforma(state, onProgress);\n\n await onProgress?.('Installation platforma...');\n\n await this.doStepDownloadBinaries(state, onProgress, ops);\n await this.doStepFetchPorts(state);\n await this.doStepGenerateNewConfig(state, onProgress, ops);\n await this.doStepCreateFoldersAndSaveFiles(state, onProgress);\n await this.doStepConfigureSupervisord(state, onProgress);\n await this.doStepSaveNewConnectionInfo(state, onProgress, ops);\n await this.doStepStartPlatforma(state, onProgress);\n\n return state.connectionInfo!;\n } catch (e: unknown) {\n const msg = `SshPl.platformaInit: ${e}, state: ${JSON.stringify(this.removeSensitiveData(state))}`;\n this.logger.error(msg);\n\n throw new Error(msg);\n }\n }\n\n private async doStepStopExistedPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'stopExistedPlatforma';\n if (!isAllAlive(state.alive!, state.shouldUseMinio ?? false)) {\n return;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n }\n\n private removeSensitiveData(state: PlatformaInitState): PlatformaInitState {\n const stateCopy = { ...state };\n stateCopy.generatedConfig = { ...stateCopy.generatedConfig, filesToCreate: { skipped: 'sanitized' } } as SshPlConfigGenerationResult;\n return stateCopy;\n }\n\n private async doStepStartPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'startPlatforma';\n await onProgress?.('Starting Platforma on the server...');\n await this.start(state.shouldUseMinio ?? false);\n state.started = true;\n this.initState = state;\n\n await onProgress?.('Platforma has been started successfully.');\n }\n\n private async doStepSaveNewConnectionInfo(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'saveNewConnectionInfo';\n const config = state.generatedConfig!;\n await onProgress?.('Saving connection information...');\n state.connectionInfo = newConnectionInfo(\n config.plUser,\n config.plPassword,\n state.ports!,\n notEmpty(ops.useGlobalAccess),\n ops.plBinary!.version,\n state.shouldUseMinio ?? false,\n );\n await this.sshClient.writeFileOnTheServer(\n plpath.connectionInfo(state.remoteHome!),\n stringifyConnectionInfo(state.connectionInfo),\n );\n await onProgress?.('Connection information saved.');\n }\n\n private async doStepConfigureSupervisord(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n await onProgress?.('Writing supervisord configuration...');\n state.step = 'configureSupervisord';\n\n const config = state.generatedConfig!;\n\n let supervisorConfig: string;\n if (state.shouldUseMinio) {\n supervisorConfig = generateSupervisordConfigWithMinio(\n config.minioConfig.storageDir,\n config.minioConfig.envs,\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.minioRelPath!,\n state.binPaths!.downloadedPl,\n );\n } else {\n supervisorConfig = generateSupervisordConfig(\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.downloadedPl,\n );\n }\n\n const writeResult = await this.sshClient.writeFileOnTheServer(plpath.supervisorConf(state.remoteHome!), supervisorConfig);\n if (!writeResult) {\n throw new Error(`Can not write supervisord config on the server ${plpath.workDir(state.remoteHome!)}`);\n }\n await onProgress?.('Supervisord configuration written.');\n }\n\n private async doStepCreateFoldersAndSaveFiles(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'createFoldersAndSaveFiles';\n const config = state.generatedConfig!;\n await onProgress?.('Generating folder structure...');\n for (const [filePath, content] of Object.entries(config.filesToCreate)) {\n await this.sshClient.writeFileOnTheServer(filePath, content);\n this.logger.info(`Created file ${filePath}`);\n }\n\n for (const dir of config.dirsToCreate) {\n await this.sshClient.ensureRemoteDirCreated(dir);\n this.logger.info(`Created directory ${dir}`);\n }\n await onProgress?.('Folder structure created.');\n }\n\n private async doStepGenerateNewConfig(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'generateNewConfig';\n\n await onProgress?.('Generating new config...');\n const config = await generateSshPlConfigs({\n logger: this.logger,\n workingDir: plpath.workDir(state.remoteHome!),\n portsMode: {\n type: 'customWithMinio',\n ports: {\n debug: state.ports!.debug.remote,\n grpc: state.ports!.grpc.remote,\n http: state.ports!.http!.remote,\n minio: state.ports!.minioPort.remote,\n minioConsole: state.ports!.minioConsolePort.remote,\n monitoring: state.ports!.monitoring.remote,\n\n httpLocal: state.ports!.http!.local,\n grpcLocal: state.ports!.grpc.local,\n minioLocal: state.ports!.minioPort.local,\n },\n },\n licenseMode: ops.license,\n useGlobalAccess: notEmpty(ops.useGlobalAccess),\n plConfigPostprocessing: ops.plConfigPostprocessing,\n useMinio: state.shouldUseMinio ?? false,\n });\n state.generatedConfig = { ...config };\n await onProgress?.('New config generated');\n }\n\n private async doStepFetchPorts(state: PlatformaInitState) {\n state.step = 'fetchPorts';\n state.ports = await this.fetchPorts(state.remoteHome!, state.arch!);\n\n if (!state.ports.debug.remote\n || !state.ports.grpc.remote\n || !state.ports.minioPort.remote\n || !state.ports.minioConsolePort.remote\n || !state.ports.monitoring.remote\n || !state.ports.http?.remote) {\n throw new Error(`SshPl.platformaInit: remote ports are not defined`);\n }\n }\n\n private async doStepDownloadBinaries(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'downloadBinaries';\n await onProgress?.('Downloading and uploading required binaries...');\n\n const glibcVersion = await getGlibcVersion(this.logger, this.sshClient);\n if (glibcVersion < minRequiredGlibcVersion)\n throw new Error(`glibc version ${glibcVersion} is too old. Version ${minRequiredGlibcVersion} or higher is required for Platforma.`);\n\n const downloadRes = await this.downloadBinariesAndUploadToTheServer(\n ops.localWorkdir, ops.plBinary!, state.remoteHome!, state.arch!, state.shouldUseMinio ?? false,\n );\n await onProgress?.('All required binaries have been downloaded and uploaded.');\n\n state.binPaths = { ...downloadRes, history: undefined };\n state.downloadedBinaries = downloadRes.history;\n }\n\n private async doStepDetectArch(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectArch';\n await onProgress?.('Detecting server architecture...');\n state.arch = await this.getArch();\n await onProgress?.('Server architecture detected.');\n }\n\n private async doStepDetectHome(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectHome';\n await onProgress?.('Fetching user home directory...');\n state.remoteHome = await this.getUserHomeDirectory();\n await onProgress?.('User home directory retrieved.');\n }\n\n private async doStepReadExistedConfig(\n state: PlatformaInitState,\n ops: SshPlConfig,\n onProgress: ((...args: any) => Promise<any>) | undefined,\n ): Promise<boolean> {\n state.step = 'checkAlive';\n await onProgress?.('Checking platform status...');\n state.alive = await this.isAlive();\n\n if (!state.alive?.platforma) {\n return true;\n }\n\n await onProgress?.('All required services are running.');\n\n state.existedSettings = await this.readExistedConfig(state.remoteHome!);\n if (!state.existedSettings) {\n throw new Error(`SshPl.platformaInit: platforma is alive but existed settings are not found`);\n }\n\n const sameGA = state.existedSettings.useGlobalAccess == ops.useGlobalAccess;\n const samePlVersion = state.existedSettings.plVersion == ops.plBinary!.version;\n state.needRestart = !(sameGA && samePlVersion);\n this.logger.info(`SshPl.platformaInit: need restart? ${state.needRestart}`);\n\n state.shouldUseMinio = state.existedSettings.minioIsUsed;\n if (state.shouldUseMinio) {\n this.logger.info(`SshPl.platformaInit: minio is used`);\n } else {\n this.logger.info(`SshPl.platformaInit: minio is not used`);\n }\n\n if (!state.needRestart) {\n await onProgress?.('Server setup completed.');\n return false;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n\n return true;\n }\n\n public async downloadBinariesAndUploadToTheServer(\n localWorkdir: string,\n plBinary: PlBinarySourceDownload,\n remoteHome: string,\n arch: Arch,\n shouldUseMinio: boolean,\n ) {\n const state: DownloadAndUntarState[] = [];\n try {\n const pl = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'pl', `pl-${plBinary.version}`,\n );\n state.push(pl);\n\n const supervisor = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'supervisord', plpath.supervisordDirName,\n );\n state.push(supervisor);\n\n const minioPath = plpath.minioBin(remoteHome, arch.arch);\n if (shouldUseMinio) {\n const minio = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'minio', plpath.minioDirName,\n );\n state.push(minio);\n await this.sshClient.chmod(minioPath, 0o750);\n }\n\n return {\n history: state,\n minioRelPath: shouldUseMinio ? minioPath : undefined,\n downloadedPl: plpath.platformaBin(remoteHome, arch.arch),\n };\n } catch (e: unknown) {\n const msg = `SshPl.downloadBinariesAndUploadToServer: ${e}, state: ${JSON.stringify(state)}`;\n this.logger.error(msg);\n throw e;\n }\n }\n\n /** We have to extract pl in the remote server,\n * because Windows doesn't support symlinks\n * that are found in Linux pl binaries tgz archive.\n * For this reason, we extract all to the remote server.\n * It requires `tar` to be installed on the server\n * (it's not installed for Rocky Linux for example). */\n public async downloadAndUntar(\n localWorkdir: string,\n remoteHome: string,\n arch: Arch,\n softwareName: string,\n tgzName: string,\n ): Promise<DownloadAndUntarState> {\n const state: DownloadAndUntarState = {};\n state.binBasePath = plpath.binariesDir(remoteHome);\n await this.sshClient.ensureRemoteDirCreated(state.binBasePath);\n state.binBasePathCreated = true;\n\n let downloadBinaryResult: DownloadBinaryResult | null = null;\n const attempts = 5;\n for (let i = 1; i <= attempts; i++) {\n try {\n downloadBinaryResult = await downloadBinaryNoExtract({\n logger: this.logger,\n baseDir: localWorkdir,\n softwareName,\n tgzName,\n arch: arch.arch,\n platform: arch.platform,\n });\n break;\n } catch (e: unknown) {\n await sleep(300);\n if (i == attempts) {\n throw new Error(`downloadAndUntar: ${attempts} attempts, last error: ${e}`);\n }\n }\n }\n state.downloadResult = notEmpty(downloadBinaryResult);\n\n state.localArchivePath = upath.resolve(state.downloadResult.archivePath);\n state.remoteDir = upath.join(state.binBasePath, state.downloadResult.baseName);\n state.remoteArchivePath = state.remoteDir + '.tgz';\n\n await this.sshClient.ensureRemoteDirCreated(state.remoteDir);\n await this.sshClient.uploadFile(state.localArchivePath, state.remoteArchivePath);\n state.uploadDone = true;\n\n try {\n await this.sshClient.exec('hash tar');\n } catch (_) {\n throw new Error(`tar is not installed on the server. Please install it before running Platforma.`);\n }\n\n // TODO: Create a proper archive to avoid xattr warnings\n const untarResult = await this.sshClient.exec(\n `tar --warning=no-all -xvf ${state.remoteArchivePath} --directory=${state.remoteDir}`,\n );\n\n if (untarResult.stderr)\n throw new Error(`downloadAndUntar: untar: stderr occurred: ${untarResult.stderr}, stdout: ${untarResult.stdout}`);\n\n state.untarDone = true;\n\n return state;\n }\n\n public async needDownload(remoteHome: string, arch: Arch) {\n const checkPathSupervisor = plpath.supervisorBin(remoteHome, arch.arch);\n const checkPathMinio = plpath.minioDir(remoteHome, arch.arch);\n const checkPathPlatforma = plpath.platformaBin(remoteHome, arch.arch);\n\n if (!await this.sshClient.checkFileExists(checkPathPlatforma)\n || !await this.sshClient.checkFileExists(checkPathMinio)\n || !await this.sshClient.checkFileExists(checkPathSupervisor)) {\n return true;\n }\n\n return false;\n }\n\n public async checkIsAliveWithInterval(shouldUseMinio: boolean, interval: number = 1000, count = 15, shouldStart = true): Promise<void> {\n const maxMs = count * interval;\n\n let total = 0;\n let alive = await this.isAlive();\n while (shouldStart ? !isAllAlive(alive, shouldUseMinio) : isAllAlive(alive, shouldUseMinio)) {\n await sleep(interval);\n total += interval;\n if (total > maxMs) {\n throw new Error(`isAliveWithInterval: The process did not ${shouldStart ? 'started' : 'stopped'} after ${maxMs} ms. Live status: ${JSON.stringify(alive)}`);\n }\n alive = await this.isAlive();\n }\n }\n\n public async readExistedConfig(remoteHome: string): Promise<ConnectionInfo> {\n const connectionInfo = await this.sshClient.readFile(plpath.connectionInfo(remoteHome));\n return parseConnectionInfo(connectionInfo);\n }\n\n public async fetchPorts(remoteHome: string, arch: Arch): Promise<SshPlPorts> {\n const ports: SshPlPorts = {\n grpc: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n monitoring: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n debug: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n http: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioPort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioConsolePort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n };\n\n return ports;\n }\n\n public async getLocalFreePort(): Promise<number> {\n return new Promise((res) => {\n const srv = net.createServer();\n srv.listen(0, () => {\n const port = (srv.address() as net.AddressInfo).port;\n srv.close((_) => res(port));\n });\n });\n }\n\n public async getFreePortForPlatformaOnServer(remoteHome: string, arch: Arch): Promise<number> {\n const freePortBin = plpath.platformaFreePortBin(remoteHome, arch.arch);\n\n const { stdout, stderr } = await this.sshClient.exec(`${freePortBin}`);\n if (stderr) {\n throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n }\n\n return +stdout;\n }\n\n public async getArch(): Promise<Arch> {\n const { stdout, stderr } = await this.sshClient.exec('uname -s && uname -m');\n if (stderr)\n throw new Error(`getArch: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n\n const arr = stdout.split('\\n');\n\n return {\n platform: arr[0],\n arch: arr[1],\n };\n }\n\n public async getUserHomeDirectory() {\n const { stdout, stderr } = await this.sshClient.exec('echo $HOME');\n\n if (stderr) {\n const home = `/home/${this.username}`;\n console.warn(`getUserHomeDirectory: stderr is not empty: ${stderr}, stdout: ${stdout}, will get a default home: ${home}`);\n\n return home;\n }\n\n return stdout.trim();\n }\n}\n\ntype Arch = { platform: string; arch: string };\n\nexport type SshPlConfig = {\n localWorkdir: string;\n license: PlLicenseMode;\n useGlobalAccess?: boolean;\n plBinary?: PlBinarySourceDownload;\n\n onProgress?: (...args: any) => Promise<any>;\n plConfigPostprocessing?: (config: PlConfig) => PlConfig;\n};\n\nconst defaultSshPlConfig: Pick<\n SshPlConfig,\n | 'useGlobalAccess'\n | 'plBinary'\n> = {\n useGlobalAccess: false,\n plBinary: {\n type: 'Download',\n version: getDefaultPlVersion(),\n },\n};\n\ntype BinPaths = {\n history?: DownloadAndUntarState[];\n minioRelPath?: string;\n downloadedPl: string;\n};\n\ntype DownloadAndUntarState = {\n binBasePath?: string;\n binBasePathCreated?: boolean;\n downloadResult?: DownloadBinaryResult;\n attempts?: number;\n\n localArchivePath?: string;\n remoteDir?: string;\n remoteArchivePath?: string;\n uploadDone?: boolean;\n untarDone?: boolean;\n};\n\ntype PlatformaInitStep =\n 'init'\n | 'detectArch'\n | 'detectHome'\n | 'checkAlive'\n | 'stopExistedPlatforma'\n | 'downloadBinaries'\n | 'fetchPorts'\n | 'generateNewConfig'\n | 'createFoldersAndSaveFiles'\n | 'configureSupervisord'\n | 'saveNewConnectionInfo'\n | 'startPlatforma';\n\ntype PlatformaInitState = {\n step: PlatformaInitStep;\n localWorkdir?: string;\n plBinaryOps?: PlBinarySourceDownload;\n arch?: Arch;\n remoteHome?: string;\n alive?: SupervisorStatus;\n existedSettings?: ConnectionInfo;\n needRestart?: boolean;\n shouldUseMinio?: boolean;\n downloadedBinaries?: DownloadAndUntarState[];\n binPaths?: BinPaths;\n ports?: SshPlPorts;\n generatedConfig?: SshPlConfigGenerationResult;\n connectionInfo?: ConnectionInfo;\n started?: boolean;\n};\n\n/**\n * Gets the glibc version on the remote system\n * @returns The glibc version as a number\n * @throws Error if version cannot be determined\n */\nasync function getGlibcVersion(logger: MiLogger, sshClient: SshClient): Promise <number> {\n try {\n const { stdout, stderr } = await sshClient.exec('ldd --version | head -n 1');\n if (stderr) {\n throw new Error(`Failed to check glibc version: ${stderr}`);\n }\n return parseGlibcVersion(stdout);\n } catch (e: unknown) {\n logger.error(`glibc version check failed: ${e}`);\n throw e;\n }\n}\n\nexport function parseGlibcVersion(output: string): number {\n const versionMatch = output.match(/\\d+\\.\\d+/);\n if (!versionMatch) {\n throw new Error(`Could not parse glibc version from: ${output}`);\n }\n\n return parseFloat(versionMatch[0]);\n}\n"],"names":["plpath.platformaCliLogs","supervisorCtlShutdown","plpath.workDir","plpath.connectionInfo","plpath.supervisorConf","plpath.supervisordDirName","plpath.minioBin","plpath.minioDirName","plpath.platformaBin","plpath.binariesDir","plpath.supervisorBin","plpath.minioDir","connectionInfo","plpath.platformaFreePortBin"],"mappings":"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"}
1
+ {"version":3,"file":"pl.js","sources":["../../src/ssh/pl.ts"],"sourcesContent":["import type * as ssh from 'ssh2';\nimport { SshClient } from './ssh';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { sleep, notEmpty } from '@milaboratories/ts-helpers';\nimport type { DownloadBinaryResult } from '../common/pl_binary_download';\nimport { downloadBinaryNoExtract } from '../common/pl_binary_download';\nimport upath from 'upath';\nimport * as plpath from './pl_paths';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nimport net from 'node:net';\nimport type { PlConfig, PlLicenseMode, SshPlConfigGenerationResult } from '@milaboratories/pl-config';\nimport { getFreePort, generateSshPlConfigs } from '@milaboratories/pl-config';\nimport type { SupervisorStatus } from './supervisord';\nimport { supervisorStatus, supervisorStop as supervisorCtlShutdown, generateSupervisordConfigWithMinio, supervisorCtlStart, isSupervisordRunning, generateSupervisordConfig, isAllAlive } from './supervisord';\nimport type { ConnectionInfo, SshPlPorts } from './connection_info';\nimport { newConnectionInfo, parseConnectionInfo, stringifyConnectionInfo } from './connection_info';\nimport type { PlBinarySourceDownload } from '../common/pl_binary';\n\nconst minRequiredGlibcVersion = 2.28;\n\nexport class SshPl {\n private initState: PlatformaInitState = { step: 'init' };\n constructor(\n public readonly logger: MiLogger,\n public readonly sshClient: SshClient,\n private readonly username: string,\n ) { }\n\n public info() {\n return {\n username: this.username,\n initState: this.initState,\n };\n }\n\n public static async init(logger: MiLogger, config: ssh.ConnectConfig): Promise<SshPl> {\n try {\n const sshClient = await SshClient.init(logger, config);\n return new SshPl(logger, sshClient, notEmpty(config.username));\n } catch (e: unknown) {\n logger.error(`Connection error in SshClient.init: ${e}`);\n throw e;\n }\n }\n\n public cleanUp() {\n this.sshClient.close();\n }\n\n /** Provides an info if the platforma and minio are running along with the debug info. */\n public async isAlive(): Promise<SupervisorStatus> {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n return await supervisorStatus(this.logger, this.sshClient, remoteHome, arch.arch);\n }\n\n /** Starts all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async start(shouldUseMinio: boolean) {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n if (!isAllAlive(await this.isAlive(), shouldUseMinio)) {\n await supervisorCtlStart(this.sshClient, remoteHome, arch.arch);\n\n // We are waiting for Platforma to run to ensure that it has started.\n return await this.checkIsAliveWithInterval(shouldUseMinio);\n }\n } catch (e: unknown) {\n let msg = `SshPl.start: ${e}`;\n\n let logs = '';\n try {\n logs = await this.sshClient.readFile(plpath.platformaCliLogs(remoteHome));\n msg += `, platforma cli logs: ${logs}`;\n } catch (e: unknown) {\n msg += `, Can not read platforma cli logs: ${e}`;\n }\n\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops all the services on the server.\n * Idempotent semantic: we could call it several times. */\n public async stop() {\n const arch = await this.getArch();\n const remoteHome = await this.getUserHomeDirectory();\n\n try {\n const alive = await this.isAlive();\n if (isSupervisordRunning(alive)) {\n await supervisorCtlShutdown(this.sshClient, remoteHome, arch.arch);\n // Check if Minio is running by looking at the alive status\n const shouldUseMinio = alive.minio === true;\n return await this.checkIsAliveWithInterval(shouldUseMinio, 1000, 15, false);\n }\n } catch (e: unknown) {\n const msg = `PlSsh.stop: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** Stops the services, deletes a directory with the state and closes SSH connection. */\n public async reset(): Promise<boolean> {\n await this.stopAndClean();\n this.cleanUp();\n return true;\n }\n\n /** Stops platforma and deletes its state. */\n public async stopAndClean(): Promise<void> {\n const remoteHome = await this.getUserHomeDirectory();\n\n this.logger.info(`pl.reset: Stop Platforma on the server`);\n await this.stop();\n\n this.logger.info(`pl.reset: Deleting Platforma workDir ${plpath.workDir(remoteHome)} on the server`);\n await this.sshClient.deleteFolder(plpath.workDir(remoteHome));\n }\n\n /** Downloads binaries and untar them on the server,\n * generates all the configs, creates necessary dirs,\n * and finally starts all the services. */\n public async platformaInit(options: SshPlConfig): Promise<ConnectionInfo> {\n const state: PlatformaInitState = { localWorkdir: options.localWorkdir, step: 'init' };\n\n const { onProgress } = options;\n\n // merge options with default ops.\n const ops: SshPlConfig = {\n ...defaultSshPlConfig,\n ...options,\n };\n state.plBinaryOps = ops.plBinary;\n\n try {\n await this.doStepDetectArch(state, onProgress);\n await this.doStepDetectHome(state, onProgress);\n\n const needRestartPlatforma = await this.doStepReadExistedConfig(state, ops, onProgress);\n if (!needRestartPlatforma) {\n await onProgress?.('Platforma is already running. Skipping initialization.');\n return state.existedSettings!;\n }\n await this.doStepStopExistedPlatforma(state, onProgress);\n await this.doStepCheckDbLock(state, onProgress);\n\n await onProgress?.('Installation platforma...');\n\n await this.doStepDownloadBinaries(state, onProgress, ops);\n await this.doStepFetchPorts(state);\n await this.doStepGenerateNewConfig(state, onProgress, ops);\n await this.doStepCreateFoldersAndSaveFiles(state, onProgress);\n await this.doStepConfigureSupervisord(state, onProgress);\n await this.doStepSaveNewConnectionInfo(state, onProgress, ops);\n await this.doStepStartPlatforma(state, onProgress);\n\n return state.connectionInfo!;\n } catch (e: unknown) {\n const msg = `SshPl.platformaInit: ${e}, state: ${JSON.stringify(this.removeSensitiveData(state))}`;\n this.logger.error(msg);\n\n throw new Error(msg);\n }\n }\n\n private async doStepStopExistedPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'stopExistedPlatforma';\n if (!isAllAlive(state.alive!, state.shouldUseMinio ?? false)) {\n return;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n }\n\n private removeSensitiveData(state: PlatformaInitState): PlatformaInitState {\n const stateCopy = { ...state };\n stateCopy.generatedConfig = { ...stateCopy.generatedConfig, filesToCreate: { skipped: 'sanitized' } } as SshPlConfigGenerationResult;\n return stateCopy;\n }\n\n private async doStepStartPlatforma(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'startPlatforma';\n await onProgress?.('Starting Platforma on the server...');\n await this.start(state.shouldUseMinio ?? false);\n state.started = true;\n this.initState = state;\n\n await onProgress?.('Platforma has been started successfully.');\n }\n\n private async doStepSaveNewConnectionInfo(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'saveNewConnectionInfo';\n const config = state.generatedConfig!;\n await onProgress?.('Saving connection information...');\n state.connectionInfo = newConnectionInfo(\n config.plUser,\n config.plPassword,\n state.ports!,\n notEmpty(ops.useGlobalAccess),\n ops.plBinary!.version,\n state.shouldUseMinio ?? false,\n );\n await this.sshClient.writeFileOnTheServer(\n plpath.connectionInfo(state.remoteHome!),\n stringifyConnectionInfo(state.connectionInfo),\n );\n await onProgress?.('Connection information saved.');\n }\n\n private async doStepCheckDbLock(\n state: PlatformaInitState,\n onProgress?: (...args: any[]) => Promise<any>,\n ) {\n const removeLockFile = async (lockFilePath: string) => {\n try {\n await this.sshClient.exec(`rm -f ${lockFilePath}`);\n this.logger.info(`Removed stale lock file ${lockFilePath}`);\n } catch (e: unknown) {\n const msg = `Failed to remove stale lock file ${lockFilePath}: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n };\n\n state.step = 'checkDbLock';\n await onProgress?.('Checking for DB lock...');\n\n const lockFilePath = plpath.platformaDbLock(state.remoteHome!);\n const lockFileExists = await this.sshClient.checkFileExists(lockFilePath);\n\n if (!lockFileExists) {\n await onProgress?.('No DB lock found. Proceeding...');\n return;\n }\n\n this.logger.info(`DB lock file found at ${lockFilePath}. Checking which process holds it...`);\n const lockProcessInfo = await this.findLockHolder(lockFilePath);\n\n if (!lockProcessInfo) {\n this.logger.warn('Lock file exists but no process is holding it. Removing stale lock file...');\n await removeLockFile(lockFilePath);\n return;\n }\n\n this.logger.info(\n `Found process ${lockProcessInfo.pid} (user: ${lockProcessInfo.user}) holding DB lock`,\n );\n\n if (lockProcessInfo.user !== this.username) {\n const msg\n = `DB lock is held by process ${lockProcessInfo.pid} `\n + `owned by user '${lockProcessInfo.user}', but current user is '${this.username}'. `\n + 'Cannot kill process owned by different user.';\n this.logger.error(msg);\n throw new Error(msg);\n }\n\n this.logger.info(`Process ${lockProcessInfo.pid} belongs to current user ${this.username}. Killing it...`);\n await this.killRemoteProcess(lockProcessInfo.pid);\n this.logger.info('Process holding DB lock has been terminated.');\n\n // Verify lock file is gone or can be removed\n const lockStillExists = await this.sshClient.checkFileExists(lockFilePath);\n if (lockStillExists) {\n await removeLockFile(lockFilePath);\n }\n }\n\n private async doStepConfigureSupervisord(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n await onProgress?.('Writing supervisord configuration...');\n state.step = 'configureSupervisord';\n\n const config = state.generatedConfig!;\n\n let supervisorConfig: string;\n if (state.shouldUseMinio) {\n supervisorConfig = generateSupervisordConfigWithMinio(\n config.minioConfig.storageDir,\n config.minioConfig.envs,\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.minioRelPath!,\n state.binPaths!.downloadedPl,\n );\n } else {\n supervisorConfig = generateSupervisordConfig(\n await this.getFreePortForPlatformaOnServer(state.remoteHome!, state.arch!),\n config.workingDir,\n config.plConfig.configPath,\n state.binPaths!.downloadedPl,\n );\n }\n\n const writeResult = await this.sshClient.writeFileOnTheServer(plpath.supervisorConf(state.remoteHome!), supervisorConfig);\n if (!writeResult) {\n throw new Error(`Can not write supervisord config on the server ${plpath.workDir(state.remoteHome!)}`);\n }\n await onProgress?.('Supervisord configuration written.');\n }\n\n private async doStepCreateFoldersAndSaveFiles(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'createFoldersAndSaveFiles';\n const config = state.generatedConfig!;\n await onProgress?.('Generating folder structure...');\n for (const [filePath, content] of Object.entries(config.filesToCreate)) {\n await this.sshClient.writeFileOnTheServer(filePath, content);\n this.logger.info(`Created file ${filePath}`);\n }\n\n for (const dir of config.dirsToCreate) {\n await this.sshClient.ensureRemoteDirCreated(dir);\n this.logger.info(`Created directory ${dir}`);\n }\n await onProgress?.('Folder structure created.');\n }\n\n private async doStepGenerateNewConfig(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'generateNewConfig';\n\n await onProgress?.('Generating new config...');\n const config = await generateSshPlConfigs({\n logger: this.logger,\n workingDir: plpath.workDir(state.remoteHome!),\n portsMode: {\n type: 'customWithMinio',\n ports: {\n debug: state.ports!.debug.remote,\n grpc: state.ports!.grpc.remote,\n http: state.ports!.http!.remote,\n minio: state.ports!.minioPort.remote,\n minioConsole: state.ports!.minioConsolePort.remote,\n monitoring: state.ports!.monitoring.remote,\n\n httpLocal: state.ports!.http!.local,\n grpcLocal: state.ports!.grpc.local,\n minioLocal: state.ports!.minioPort.local,\n },\n },\n licenseMode: ops.license,\n useGlobalAccess: notEmpty(ops.useGlobalAccess),\n plConfigPostprocessing: ops.plConfigPostprocessing,\n useMinio: state.shouldUseMinio ?? false,\n });\n state.generatedConfig = { ...config };\n await onProgress?.('New config generated');\n }\n\n private async doStepFetchPorts(state: PlatformaInitState) {\n state.step = 'fetchPorts';\n state.ports = await this.fetchPorts(state.remoteHome!, state.arch!);\n\n if (!state.ports.debug.remote\n || !state.ports.grpc.remote\n || !state.ports.minioPort.remote\n || !state.ports.minioConsolePort.remote\n || !state.ports.monitoring.remote\n || !state.ports.http?.remote) {\n throw new Error(`SshPl.platformaInit: remote ports are not defined`);\n }\n }\n\n private async doStepDownloadBinaries(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined, ops: SshPlConfig) {\n state.step = 'downloadBinaries';\n await onProgress?.('Downloading and uploading required binaries...');\n\n const glibcVersion = await getGlibcVersion(this.logger, this.sshClient);\n if (glibcVersion < minRequiredGlibcVersion)\n throw new Error(`glibc version ${glibcVersion} is too old. Version ${minRequiredGlibcVersion} or higher is required for Platforma.`);\n\n const downloadRes = await this.downloadBinariesAndUploadToTheServer(\n ops.localWorkdir, ops.plBinary!, state.remoteHome!, state.arch!, state.shouldUseMinio ?? false,\n );\n await onProgress?.('All required binaries have been downloaded and uploaded.');\n\n state.binPaths = { ...downloadRes, history: undefined };\n state.downloadedBinaries = downloadRes.history;\n }\n\n private async doStepDetectArch(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectArch';\n await onProgress?.('Detecting server architecture...');\n state.arch = await this.getArch();\n await onProgress?.('Server architecture detected.');\n }\n\n private async doStepDetectHome(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {\n state.step = 'detectHome';\n await onProgress?.('Fetching user home directory...');\n state.remoteHome = await this.getUserHomeDirectory();\n await onProgress?.('User home directory retrieved.');\n }\n\n private async doStepReadExistedConfig(\n state: PlatformaInitState,\n ops: SshPlConfig,\n onProgress: ((...args: any) => Promise<any>) | undefined,\n ): Promise<boolean> {\n state.step = 'checkAlive';\n await onProgress?.('Checking platform status...');\n state.alive = await this.isAlive();\n\n if (!state.alive?.platforma) {\n return true;\n }\n\n await onProgress?.('All required services are running.');\n\n state.existedSettings = await this.readExistedConfig(state.remoteHome!);\n if (!state.existedSettings) {\n throw new Error(`SshPl.platformaInit: platforma is alive but existed settings are not found`);\n }\n\n const sameGA = state.existedSettings.useGlobalAccess == ops.useGlobalAccess;\n const samePlVersion = state.existedSettings.plVersion == ops.plBinary!.version;\n state.needRestart = !(sameGA && samePlVersion);\n this.logger.info(`SshPl.platformaInit: need restart? ${state.needRestart}`);\n\n state.shouldUseMinio = state.existedSettings.minioIsUsed;\n if (state.shouldUseMinio) {\n this.logger.info(`SshPl.platformaInit: minio is used`);\n } else {\n this.logger.info(`SshPl.platformaInit: minio is not used`);\n }\n\n if (!state.needRestart) {\n await onProgress?.('Server setup completed.');\n return false;\n }\n\n await onProgress?.('Stopping services...');\n await this.stop();\n\n return true;\n }\n\n public async downloadBinariesAndUploadToTheServer(\n localWorkdir: string,\n plBinary: PlBinarySourceDownload,\n remoteHome: string,\n arch: Arch,\n shouldUseMinio: boolean,\n ) {\n const state: DownloadAndUntarState[] = [];\n try {\n const pl = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'pl', `pl-${plBinary.version}`,\n );\n state.push(pl);\n\n const supervisor = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'supervisord', plpath.supervisordDirName,\n );\n state.push(supervisor);\n\n const minioPath = plpath.minioBin(remoteHome, arch.arch);\n if (shouldUseMinio) {\n const minio = await this.downloadAndUntar(\n localWorkdir, remoteHome, arch,\n 'minio', plpath.minioDirName,\n );\n state.push(minio);\n await this.sshClient.chmod(minioPath, 0o750);\n }\n\n return {\n history: state,\n minioRelPath: shouldUseMinio ? minioPath : undefined,\n downloadedPl: plpath.platformaBin(remoteHome, arch.arch),\n };\n } catch (e: unknown) {\n const msg = `SshPl.downloadBinariesAndUploadToServer: ${e}, state: ${JSON.stringify(state)}`;\n this.logger.error(msg);\n throw e;\n }\n }\n\n private async findLockHolderWithLsof(lockFilePath: string): Promise<LockProcessInfo | null> {\n try {\n const { stdout } = await this.sshClient.exec(`lsof ${lockFilePath} 2>/dev/null || true`);\n const output = stdout.trim();\n if (!output) {\n return null;\n }\n\n // Example:\n // COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n // platforma 11628 rfiskov 10u REG 1,16 0 66670038 ./LOCK\n const lines = output.split('\\n');\n if (lines.length <= 1) {\n return null;\n }\n\n const parts = lines[1].trim().split(/\\s+/);\n if (parts.length < 3) {\n return null;\n }\n\n const pid = Number.parseInt(parts[1], 10);\n const user = parts[2];\n\n return Number.isNaN(pid) || !user ? null : { pid, user };\n } catch (e: unknown) {\n this.logger.warn(`Failed to use lsof to check lock: ${e}`);\n return null;\n }\n }\n\n private async findLockHolderWithFuser(lockFilePath: string): Promise<LockProcessInfo | null> {\n try {\n const { stdout } = await this.sshClient.exec(`fuser ${lockFilePath} 2>/dev/null || true`);\n const output = stdout.trim();\n if (!output) {\n return null;\n }\n\n // Example: ./LOCK: 11628\n const match = output.match(/: (\\d+)/);\n if (!match) {\n return null;\n }\n\n const pid = Number.parseInt(match[1], 10);\n if (Number.isNaN(pid)) {\n return null;\n }\n\n try {\n const psResult = await this.sshClient.exec(`ps -o user= -p ${pid} 2>/dev/null || true`);\n const user = psResult.stdout.trim();\n return user ? { pid, user } : null;\n } catch (e: unknown) {\n this.logger.warn(`Failed to get user for PID ${pid}: ${e}`);\n return null;\n }\n } catch (e: unknown) {\n this.logger.warn(`Failed to use fuser to check lock: ${e}`);\n return null;\n }\n }\n\n private async findLockHolder(lockFilePath: string): Promise<LockProcessInfo | null> {\n const viaLsof = await this.findLockHolderWithLsof(lockFilePath);\n if (viaLsof) {\n return viaLsof;\n }\n return this.findLockHolderWithFuser(lockFilePath);\n }\n\n private async killRemoteProcess(pid: number): Promise<void> {\n this.logger.info(`Killing process ${pid}...`);\n\n try {\n // Try graceful termination first\n await this.sshClient.exec(`kill ${pid} 2>/dev/null || true`);\n await sleep(1000);\n\n // Check if process still exists\n try {\n await this.sshClient.exec(`kill -0 ${pid} 2>/dev/null`);\n // Process still exists, force kill\n this.logger.warn(`Process ${pid} still alive after SIGTERM, forcing kill...`);\n await this.sshClient.exec(`kill -9 ${pid} 2>/dev/null || true`);\n await sleep(500);\n } catch {\n // Process is dead, nothing to do\n }\n } catch (e: unknown) {\n const msg = `Failed to kill process ${pid}: ${e}`;\n this.logger.error(msg);\n throw new Error(msg);\n }\n }\n\n /** We have to extract pl in the remote server,\n * because Windows doesn't support symlinks\n * that are found in Linux pl binaries tgz archive.\n * For this reason, we extract all to the remote server.\n * It requires `tar` to be installed on the server\n * (it's not installed for Rocky Linux for example). */\n public async downloadAndUntar(\n localWorkdir: string,\n remoteHome: string,\n arch: Arch,\n softwareName: string,\n tgzName: string,\n ): Promise<DownloadAndUntarState> {\n const state: DownloadAndUntarState = {};\n state.binBasePath = plpath.binariesDir(remoteHome);\n await this.sshClient.ensureRemoteDirCreated(state.binBasePath);\n state.binBasePathCreated = true;\n\n let downloadBinaryResult: DownloadBinaryResult | null = null;\n const attempts = 5;\n for (let i = 1; i <= attempts; i++) {\n try {\n downloadBinaryResult = await downloadBinaryNoExtract({\n logger: this.logger,\n baseDir: localWorkdir,\n softwareName,\n tgzName,\n arch: arch.arch,\n platform: arch.platform,\n });\n break;\n } catch (e: unknown) {\n await sleep(300);\n if (i == attempts) {\n throw new Error(`downloadAndUntar: ${attempts} attempts, last error: ${e}`);\n }\n }\n }\n state.downloadResult = notEmpty(downloadBinaryResult);\n\n state.localArchivePath = upath.resolve(state.downloadResult.archivePath);\n state.remoteDir = upath.join(state.binBasePath, state.downloadResult.baseName);\n state.remoteArchivePath = state.remoteDir + '.tgz';\n\n await this.sshClient.ensureRemoteDirCreated(state.remoteDir);\n await this.sshClient.uploadFile(state.localArchivePath, state.remoteArchivePath);\n state.uploadDone = true;\n\n try {\n await this.sshClient.exec('hash tar');\n } catch (_) {\n throw new Error(`tar is not installed on the server. Please install it before running Platforma.`);\n }\n\n // TODO: Create a proper archive to avoid xattr warnings\n const untarResult = await this.sshClient.exec(\n `tar --warning=no-all -xvf ${state.remoteArchivePath} --directory=${state.remoteDir}`,\n );\n\n if (untarResult.stderr)\n throw new Error(`downloadAndUntar: untar: stderr occurred: ${untarResult.stderr}, stdout: ${untarResult.stdout}`);\n\n state.untarDone = true;\n\n return state;\n }\n\n public async needDownload(remoteHome: string, arch: Arch) {\n const checkPathSupervisor = plpath.supervisorBin(remoteHome, arch.arch);\n const checkPathMinio = plpath.minioDir(remoteHome, arch.arch);\n const checkPathPlatforma = plpath.platformaBin(remoteHome, arch.arch);\n\n if (!await this.sshClient.checkFileExists(checkPathPlatforma)\n || !await this.sshClient.checkFileExists(checkPathMinio)\n || !await this.sshClient.checkFileExists(checkPathSupervisor)) {\n return true;\n }\n\n return false;\n }\n\n public async checkIsAliveWithInterval(shouldUseMinio: boolean, interval: number = 1000, count = 15, shouldStart = true): Promise<void> {\n const maxMs = count * interval;\n\n let total = 0;\n let alive = await this.isAlive();\n while (shouldStart ? !isAllAlive(alive, shouldUseMinio) : isAllAlive(alive, shouldUseMinio)) {\n await sleep(interval);\n total += interval;\n if (total > maxMs) {\n throw new Error(`isAliveWithInterval: The process did not ${shouldStart ? 'started' : 'stopped'} after ${maxMs} ms. Live status: ${JSON.stringify(alive)}`);\n }\n alive = await this.isAlive();\n }\n }\n\n public async readExistedConfig(remoteHome: string): Promise<ConnectionInfo> {\n const connectionInfo = await this.sshClient.readFile(plpath.connectionInfo(remoteHome));\n return parseConnectionInfo(connectionInfo);\n }\n\n public async fetchPorts(remoteHome: string, arch: Arch): Promise<SshPlPorts> {\n const ports: SshPlPorts = {\n grpc: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n monitoring: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n debug: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n http: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioPort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n minioConsolePort: {\n local: await getFreePort(),\n remote: await this.getFreePortForPlatformaOnServer(remoteHome, arch),\n },\n };\n\n return ports;\n }\n\n public async getLocalFreePort(): Promise<number> {\n return new Promise((res) => {\n const srv = net.createServer();\n srv.listen(0, () => {\n const port = (srv.address() as net.AddressInfo).port;\n srv.close((_) => res(port));\n });\n });\n }\n\n public async getFreePortForPlatformaOnServer(remoteHome: string, arch: Arch): Promise<number> {\n const freePortBin = plpath.platformaFreePortBin(remoteHome, arch.arch);\n\n const { stdout, stderr } = await this.sshClient.exec(`${freePortBin}`);\n if (stderr) {\n throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n }\n\n return +stdout;\n }\n\n public async getArch(): Promise<Arch> {\n const { stdout, stderr } = await this.sshClient.exec('uname -s && uname -m');\n if (stderr)\n throw new Error(`getArch: stderr is not empty: ${stderr}, stdout: ${stdout}`);\n\n const arr = stdout.split('\\n');\n\n return {\n platform: arr[0],\n arch: arr[1],\n };\n }\n\n public async getUserHomeDirectory() {\n const { stdout, stderr } = await this.sshClient.exec('echo $HOME');\n\n if (stderr) {\n const home = `/home/${this.username}`;\n console.warn(`getUserHomeDirectory: stderr is not empty: ${stderr}, stdout: ${stdout}, will get a default home: ${home}`);\n\n return home;\n }\n\n return stdout.trim();\n }\n}\n\ntype Arch = { platform: string; arch: string };\n\nexport type SshPlConfig = {\n localWorkdir: string;\n license: PlLicenseMode;\n useGlobalAccess?: boolean;\n plBinary?: PlBinarySourceDownload;\n\n onProgress?: (...args: any) => Promise<any>;\n plConfigPostprocessing?: (config: PlConfig) => PlConfig;\n};\n\nexport type LockProcessInfo = { pid: number; user: string };\n\nconst defaultSshPlConfig: Pick<\n SshPlConfig,\n | 'useGlobalAccess'\n | 'plBinary'\n> = {\n useGlobalAccess: false,\n plBinary: {\n type: 'Download',\n version: getDefaultPlVersion(),\n },\n};\n\ntype BinPaths = {\n history?: DownloadAndUntarState[];\n minioRelPath?: string;\n downloadedPl: string;\n};\n\ntype DownloadAndUntarState = {\n binBasePath?: string;\n binBasePathCreated?: boolean;\n downloadResult?: DownloadBinaryResult;\n attempts?: number;\n\n localArchivePath?: string;\n remoteDir?: string;\n remoteArchivePath?: string;\n uploadDone?: boolean;\n untarDone?: boolean;\n};\n\ntype PlatformaInitStep =\n 'init'\n | 'detectArch'\n | 'detectHome'\n | 'checkAlive'\n | 'stopExistedPlatforma'\n | 'checkDbLock'\n | 'downloadBinaries'\n | 'fetchPorts'\n | 'generateNewConfig'\n | 'createFoldersAndSaveFiles'\n | 'configureSupervisord'\n | 'saveNewConnectionInfo'\n | 'startPlatforma';\n\ntype PlatformaInitState = {\n step: PlatformaInitStep;\n localWorkdir?: string;\n plBinaryOps?: PlBinarySourceDownload;\n arch?: Arch;\n remoteHome?: string;\n alive?: SupervisorStatus;\n existedSettings?: ConnectionInfo;\n needRestart?: boolean;\n shouldUseMinio?: boolean;\n downloadedBinaries?: DownloadAndUntarState[];\n binPaths?: BinPaths;\n ports?: SshPlPorts;\n generatedConfig?: SshPlConfigGenerationResult;\n connectionInfo?: ConnectionInfo;\n started?: boolean;\n};\n\n/**\n * Gets the glibc version on the remote system\n * @returns The glibc version as a number\n * @throws Error if version cannot be determined\n */\nasync function getGlibcVersion(logger: MiLogger, sshClient: SshClient): Promise <number> {\n try {\n const { stdout, stderr } = await sshClient.exec('ldd --version | head -n 1');\n if (stderr) {\n throw new Error(`Failed to check glibc version: ${stderr}`);\n }\n return parseGlibcVersion(stdout);\n } catch (e: unknown) {\n logger.error(`glibc version check failed: ${e}`);\n throw e;\n }\n}\n\nexport function parseGlibcVersion(output: string): number {\n const versionMatch = output.match(/\\d+\\.\\d+/);\n if (!versionMatch) {\n throw new Error(`Could not parse glibc version from: ${output}`);\n }\n\n return parseFloat(versionMatch[0]);\n}\n"],"names":["plpath.platformaCliLogs","supervisorCtlShutdown","plpath.workDir","plpath.connectionInfo","plpath.platformaDbLock","plpath.supervisorConf","plpath.supervisordDirName","plpath.minioBin","plpath.minioDirName","plpath.platformaBin","plpath.binariesDir","plpath.supervisorBin","plpath.minioDir","connectionInfo","plpath.platformaFreePortBin"],"mappings":"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"}
@@ -47,6 +47,9 @@ function connectionInfo(remoteHome) {
47
47
  function platformaCliLogs(remoteHome) {
48
48
  return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');
49
49
  }
50
+ function platformaDbLock(remoteHome) {
51
+ return upath.join(workDir(remoteHome), 'db', 'LOCK');
52
+ }
50
53
 
51
54
  exports.binariesDir = binariesDir;
52
55
  exports.connectionInfo = connectionInfo;
@@ -56,6 +59,7 @@ exports.minioDirName = minioDirName;
56
59
  exports.platformaBaseDir = platformaBaseDir;
57
60
  exports.platformaBin = platformaBin;
58
61
  exports.platformaCliLogs = platformaCliLogs;
62
+ exports.platformaDbLock = platformaDbLock;
59
63
  exports.platformaDir = platformaDir;
60
64
  exports.platformaFreePortBin = platformaFreePortBin;
61
65
  exports.supervisorBin = supervisorBin;
@@ -1 +1 @@
1
- {"version":3,"file":"pl_paths.cjs","sources":["../../src/ssh/pl_paths.ts"],"sourcesContent":["/** Just a lot of hardcoded paths of our current ssh deployment. */\n\nimport upath from 'upath';\nimport { newArch } from '../common/os_and_arch';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nexport const minioDirName = 'minio-2024-12-18T13-15-44Z';\nexport const supervisordDirName = 'supervisord-0.7.3';\nexport const supervisordSubDirName = 'supervisord_0.7.3_Linux_64-bit';\n\nexport function workDir(remoteHome: string) {\n return upath.join(remoteHome, '.platforma_ssh');\n}\n\nexport function binariesDir(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'binaries');\n}\n\nexport function platformaBaseDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `pl-${getDefaultPlVersion()}-${newArch(arch)}`);\n}\n\nexport function platformaDir(remoteHome: string, arch: string) {\n return upath.join(platformaBaseDir(remoteHome, arch), 'binaries');\n}\n\nexport function platformaBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'platforma');\n}\n\nexport function platformaConf(remoteHome: string): string {\n return upath.join(workDir(remoteHome), 'config.yaml');\n}\n\nexport function platformaFreePortBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'free-port');\n}\n\nexport function minioDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `minio-2024-12-18T13-15-44Z-${newArch(arch)}`);\n}\n\nexport function minioBin(remoteHome: string, arch: string) {\n return upath.join(minioDir(remoteHome, arch), 'minio');\n}\n\nexport function supervisorBinDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `supervisord-0.7.3-${newArch(arch)}`, supervisordSubDirName);\n}\n\nexport function supervisorBin(remoteHome: string, arch: string): string {\n return upath.join(supervisorBinDir(remoteHome, arch), 'supervisord');\n}\n\nexport function supervisorConf(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'supervisor.conf');\n}\n\nexport function connectionInfo(remoteHome: string) {\n return upath.join(workDir(remoteHome), `connection.txt`);\n}\n\nexport function platformaCliLogs(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');\n}\n"],"names":["getDefaultPlVersion","newArch"],"mappings":";;;;;;AAAA;AAMO,MAAM,YAAY,GAAG;AACrB,MAAM,kBAAkB,GAAG;AAC3B,MAAM,qBAAqB,GAAG;AAE/B,SAAU,OAAO,CAAC,UAAkB,EAAA;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC;AACjD;AAEM,SAAU,WAAW,CAAC,UAAkB,EAAA;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;AACpD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,MAAMA,8BAAmB,EAAE,IAAIC,mBAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC5F;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC;AACnE;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAMM,SAAU,oBAAoB,CAAC,UAAkB,EAAE,IAAY,EAAA;AACnE,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,2BAAA,EAA8BA,mBAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC3F;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;AACxD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,kBAAA,EAAqBA,mBAAO,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC;AACzG;AAEM,SAAU,aAAa,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC5D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC;AACtE;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;AAC3D;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAA,cAAA,CAAgB,CAAC;AAC1D;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAA;IACjD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,wBAAwB,CAAC;AAClE;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"pl_paths.cjs","sources":["../../src/ssh/pl_paths.ts"],"sourcesContent":["/** Just a lot of hardcoded paths of our current ssh deployment. */\n\nimport upath from 'upath';\nimport { newArch } from '../common/os_and_arch';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nexport const minioDirName = 'minio-2024-12-18T13-15-44Z';\nexport const supervisordDirName = 'supervisord-0.7.3';\nexport const supervisordSubDirName = 'supervisord_0.7.3_Linux_64-bit';\n\nexport function workDir(remoteHome: string) {\n return upath.join(remoteHome, '.platforma_ssh');\n}\n\nexport function binariesDir(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'binaries');\n}\n\nexport function platformaBaseDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `pl-${getDefaultPlVersion()}-${newArch(arch)}`);\n}\n\nexport function platformaDir(remoteHome: string, arch: string) {\n return upath.join(platformaBaseDir(remoteHome, arch), 'binaries');\n}\n\nexport function platformaBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'platforma');\n}\n\nexport function platformaConf(remoteHome: string): string {\n return upath.join(workDir(remoteHome), 'config.yaml');\n}\n\nexport function platformaFreePortBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'free-port');\n}\n\nexport function minioDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `minio-2024-12-18T13-15-44Z-${newArch(arch)}`);\n}\n\nexport function minioBin(remoteHome: string, arch: string) {\n return upath.join(minioDir(remoteHome, arch), 'minio');\n}\n\nexport function supervisorBinDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `supervisord-0.7.3-${newArch(arch)}`, supervisordSubDirName);\n}\n\nexport function supervisorBin(remoteHome: string, arch: string): string {\n return upath.join(supervisorBinDir(remoteHome, arch), 'supervisord');\n}\n\nexport function supervisorConf(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'supervisor.conf');\n}\n\nexport function connectionInfo(remoteHome: string) {\n return upath.join(workDir(remoteHome), `connection.txt`);\n}\n\nexport function platformaCliLogs(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');\n}\n\nexport function platformaDbLock(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'db', 'LOCK');\n}\n"],"names":["getDefaultPlVersion","newArch"],"mappings":";;;;;;AAAA;AAMO,MAAM,YAAY,GAAG;AACrB,MAAM,kBAAkB,GAAG;AAC3B,MAAM,qBAAqB,GAAG;AAE/B,SAAU,OAAO,CAAC,UAAkB,EAAA;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC;AACjD;AAEM,SAAU,WAAW,CAAC,UAAkB,EAAA;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;AACpD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,MAAMA,8BAAmB,EAAE,IAAIC,mBAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC5F;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC;AACnE;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAMM,SAAU,oBAAoB,CAAC,UAAkB,EAAE,IAAY,EAAA;AACnE,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,2BAAA,EAA8BA,mBAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC3F;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;AACxD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,kBAAA,EAAqBA,mBAAO,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC;AACzG;AAEM,SAAU,aAAa,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC5D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC;AACtE;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;AAC3D;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAA,cAAA,CAAgB,CAAC;AAC1D;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAA;IACjD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,wBAAwB,CAAC;AAClE;AAEM,SAAU,eAAe,CAAC,UAAkB,EAAA;AAChD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC;AACtD;;;;;;;;;;;;;;;;;;;;"}
@@ -16,4 +16,5 @@ export declare function supervisorBin(remoteHome: string, arch: string): string;
16
16
  export declare function supervisorConf(remoteHome: string): string;
17
17
  export declare function connectionInfo(remoteHome: string): string;
18
18
  export declare function platformaCliLogs(remoteHome: string): string;
19
+ export declare function platformaDbLock(remoteHome: string): string;
19
20
  //# sourceMappingURL=pl_paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pl_paths.d.ts","sourceRoot":"","sources":["../../src/ssh/pl_paths.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAMnE,eAAO,MAAM,YAAY,+BAA+B,CAAC;AACzD,eAAO,MAAM,kBAAkB,sBAAsB,CAAC;AACtD,eAAO,MAAM,qBAAqB,mCAAmC,CAAC;AAEtE,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,UAEzC;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,UAE7C;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAEhE;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAE5D;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAExD;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAExD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAEhE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,UAEhD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,UAEhD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,UAElD"}
1
+ {"version":3,"file":"pl_paths.d.ts","sourceRoot":"","sources":["../../src/ssh/pl_paths.ts"],"names":[],"mappings":"AAAA,mEAAmE;AAMnE,eAAO,MAAM,YAAY,+BAA+B,CAAC;AACzD,eAAO,MAAM,kBAAkB,sBAAsB,CAAC;AACtD,eAAO,MAAM,qBAAqB,mCAAmC,CAAC;AAEtE,wBAAgB,OAAO,CAAC,UAAU,EAAE,MAAM,UAEzC;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,UAE7C;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAEhE;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAE5D;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAExD;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAExD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAEhE;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,UAEhD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,UAEhD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,UAElD;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,UAEjD"}
@@ -45,6 +45,9 @@ function connectionInfo(remoteHome) {
45
45
  function platformaCliLogs(remoteHome) {
46
46
  return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');
47
47
  }
48
+ function platformaDbLock(remoteHome) {
49
+ return upath.join(workDir(remoteHome), 'db', 'LOCK');
50
+ }
48
51
 
49
- export { binariesDir, connectionInfo, minioBin, minioDir, minioDirName, platformaBaseDir, platformaBin, platformaCliLogs, platformaDir, platformaFreePortBin, supervisorBin, supervisorBinDir, supervisorConf, supervisordDirName, supervisordSubDirName, workDir };
52
+ export { binariesDir, connectionInfo, minioBin, minioDir, minioDirName, platformaBaseDir, platformaBin, platformaCliLogs, platformaDbLock, platformaDir, platformaFreePortBin, supervisorBin, supervisorBinDir, supervisorConf, supervisordDirName, supervisordSubDirName, workDir };
50
53
  //# sourceMappingURL=pl_paths.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pl_paths.js","sources":["../../src/ssh/pl_paths.ts"],"sourcesContent":["/** Just a lot of hardcoded paths of our current ssh deployment. */\n\nimport upath from 'upath';\nimport { newArch } from '../common/os_and_arch';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nexport const minioDirName = 'minio-2024-12-18T13-15-44Z';\nexport const supervisordDirName = 'supervisord-0.7.3';\nexport const supervisordSubDirName = 'supervisord_0.7.3_Linux_64-bit';\n\nexport function workDir(remoteHome: string) {\n return upath.join(remoteHome, '.platforma_ssh');\n}\n\nexport function binariesDir(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'binaries');\n}\n\nexport function platformaBaseDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `pl-${getDefaultPlVersion()}-${newArch(arch)}`);\n}\n\nexport function platformaDir(remoteHome: string, arch: string) {\n return upath.join(platformaBaseDir(remoteHome, arch), 'binaries');\n}\n\nexport function platformaBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'platforma');\n}\n\nexport function platformaConf(remoteHome: string): string {\n return upath.join(workDir(remoteHome), 'config.yaml');\n}\n\nexport function platformaFreePortBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'free-port');\n}\n\nexport function minioDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `minio-2024-12-18T13-15-44Z-${newArch(arch)}`);\n}\n\nexport function minioBin(remoteHome: string, arch: string) {\n return upath.join(minioDir(remoteHome, arch), 'minio');\n}\n\nexport function supervisorBinDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `supervisord-0.7.3-${newArch(arch)}`, supervisordSubDirName);\n}\n\nexport function supervisorBin(remoteHome: string, arch: string): string {\n return upath.join(supervisorBinDir(remoteHome, arch), 'supervisord');\n}\n\nexport function supervisorConf(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'supervisor.conf');\n}\n\nexport function connectionInfo(remoteHome: string) {\n return upath.join(workDir(remoteHome), `connection.txt`);\n}\n\nexport function platformaCliLogs(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');\n}\n"],"names":[],"mappings":";;;;AAAA;AAMO,MAAM,YAAY,GAAG;AACrB,MAAM,kBAAkB,GAAG;AAC3B,MAAM,qBAAqB,GAAG;AAE/B,SAAU,OAAO,CAAC,UAAkB,EAAA;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC;AACjD;AAEM,SAAU,WAAW,CAAC,UAAkB,EAAA;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;AACpD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,mBAAmB,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC5F;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC;AACnE;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAMM,SAAU,oBAAoB,CAAC,UAAkB,EAAE,IAAY,EAAA;AACnE,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,2BAAA,EAA8B,OAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC3F;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;AACxD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,kBAAA,EAAqB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC;AACzG;AAEM,SAAU,aAAa,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC5D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC;AACtE;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;AAC3D;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAA,cAAA,CAAgB,CAAC;AAC1D;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAA;IACjD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,wBAAwB,CAAC;AAClE;;;;"}
1
+ {"version":3,"file":"pl_paths.js","sources":["../../src/ssh/pl_paths.ts"],"sourcesContent":["/** Just a lot of hardcoded paths of our current ssh deployment. */\n\nimport upath from 'upath';\nimport { newArch } from '../common/os_and_arch';\nimport { getDefaultPlVersion } from '../common/pl_version';\n\nexport const minioDirName = 'minio-2024-12-18T13-15-44Z';\nexport const supervisordDirName = 'supervisord-0.7.3';\nexport const supervisordSubDirName = 'supervisord_0.7.3_Linux_64-bit';\n\nexport function workDir(remoteHome: string) {\n return upath.join(remoteHome, '.platforma_ssh');\n}\n\nexport function binariesDir(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'binaries');\n}\n\nexport function platformaBaseDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `pl-${getDefaultPlVersion()}-${newArch(arch)}`);\n}\n\nexport function platformaDir(remoteHome: string, arch: string) {\n return upath.join(platformaBaseDir(remoteHome, arch), 'binaries');\n}\n\nexport function platformaBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'platforma');\n}\n\nexport function platformaConf(remoteHome: string): string {\n return upath.join(workDir(remoteHome), 'config.yaml');\n}\n\nexport function platformaFreePortBin(remoteHome: string, arch: string): string {\n return upath.join(platformaDir(remoteHome, arch), 'free-port');\n}\n\nexport function minioDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `minio-2024-12-18T13-15-44Z-${newArch(arch)}`);\n}\n\nexport function minioBin(remoteHome: string, arch: string) {\n return upath.join(minioDir(remoteHome, arch), 'minio');\n}\n\nexport function supervisorBinDir(remoteHome: string, arch: string) {\n return upath.join(binariesDir(remoteHome), `supervisord-0.7.3-${newArch(arch)}`, supervisordSubDirName);\n}\n\nexport function supervisorBin(remoteHome: string, arch: string): string {\n return upath.join(supervisorBinDir(remoteHome, arch), 'supervisord');\n}\n\nexport function supervisorConf(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'supervisor.conf');\n}\n\nexport function connectionInfo(remoteHome: string) {\n return upath.join(workDir(remoteHome), `connection.txt`);\n}\n\nexport function platformaCliLogs(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');\n}\n\nexport function platformaDbLock(remoteHome: string) {\n return upath.join(workDir(remoteHome), 'db', 'LOCK');\n}\n"],"names":[],"mappings":";;;;AAAA;AAMO,MAAM,YAAY,GAAG;AACrB,MAAM,kBAAkB,GAAG;AAC3B,MAAM,qBAAqB,GAAG;AAE/B,SAAU,OAAO,CAAC,UAAkB,EAAA;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC;AACjD;AAEM,SAAU,WAAW,CAAC,UAAkB,EAAA;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;AACpD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,mBAAmB,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC5F;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,UAAU,CAAC;AACnE;AAEM,SAAU,YAAY,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC3D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAMM,SAAU,oBAAoB,CAAC,UAAkB,EAAE,IAAY,EAAA;AACnE,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC;AAChE;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,2BAAA,EAA8B,OAAO,CAAC,IAAI,CAAC,CAAA,CAAE,CAAC;AAC3F;AAEM,SAAU,QAAQ,CAAC,UAAkB,EAAE,IAAY,EAAA;AACvD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;AACxD;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC/D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAA,kBAAA,EAAqB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC;AACzG;AAEM,SAAU,aAAa,CAAC,UAAkB,EAAE,IAAY,EAAA;AAC5D,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC;AACtE;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;AAC3D;AAEM,SAAU,cAAc,CAAC,UAAkB,EAAA;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAA,cAAA,CAAgB,CAAC;AAC1D;AAEM,SAAU,gBAAgB,CAAC,UAAkB,EAAA;IACjD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,wBAAwB,CAAC;AAClE;AAEM,SAAU,eAAe,CAAC,UAAkB,EAAA;AAChD,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC;AACtD;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-deployments",
3
- "version": "2.12.4",
3
+ "version": "2.12.6",
4
4
  "pl-version": "1.44.0",
5
5
  "description": "MiLaboratories Platforma Backend code service run wrapper",
6
6
  "engines": {
@@ -40,8 +40,8 @@
40
40
  "utility-types": "^3.11.0",
41
41
  "vitest": "^4.0.7",
42
42
  "@milaboratories/build-configs": "1.0.8",
43
- "@milaboratories/eslint-config": "1.0.5",
44
43
  "@milaboratories/ts-configs": "1.0.6",
44
+ "@milaboratories/eslint-config": "1.0.5",
45
45
  "@milaboratories/ts-builder": "1.0.5"
46
46
  },
47
47
  "dependencies": {
@@ -53,9 +53,9 @@
53
53
  "yaml": "^2.8.0",
54
54
  "zod": "~3.23.8",
55
55
  "@milaboratories/pl-config": "1.7.9",
56
- "@milaboratories/pl-http": "1.2.0",
57
- "@milaboratories/pl-model-common": "1.21.6",
58
- "@milaboratories/ts-helpers": "1.5.4"
56
+ "@milaboratories/pl-model-common": "1.21.7",
57
+ "@milaboratories/ts-helpers": "1.5.4",
58
+ "@milaboratories/pl-http": "1.2.0"
59
59
  },
60
60
  "scripts": {
61
61
  "type-check": "ts-builder types --target node",
@@ -1,4 +1,4 @@
1
- import { describe, it, beforeAll, expect, afterAll } from 'vitest';
1
+ import { describe, it, beforeAll, expect, afterAll, vi } from 'vitest';
2
2
  import { initContainer, getConnectionForSsh, cleanUp as cleanUpT, testAssetsPath } from './common-utils';
3
3
  import { SshPl } from '../pl';
4
4
  import upath from 'upath';
@@ -189,6 +189,15 @@ describe('SshPl', async () => {
189
189
  let isAlive = await sshPl?.isAlive();
190
190
  expect(isAlive.platforma).toBe(true);
191
191
 
192
+ // Capture console output to verify lock file handling logs
193
+ const remoteHome = await sshPl.getUserHomeDirectory();
194
+ const expectedLockPath = plpath.platformaDbLock(remoteHome);
195
+
196
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
197
+ const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
198
+ const consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(() => {});
199
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
200
+
192
201
  await sshPl.platformaInit({
193
202
  localWorkdir: downloadDestination,
194
203
  license: { type: 'env' },
@@ -196,6 +205,26 @@ describe('SshPl', async () => {
196
205
  });
197
206
  isAlive = await sshPl?.isAlive();
198
207
  expect(isAlive.platforma).toBe(true);
208
+
209
+ // Collect logs from all console methods before restoring
210
+ const allConsoleCalls = [
211
+ ...consoleLogSpy.mock.calls,
212
+ ...consoleErrorSpy.mock.calls,
213
+ ...consoleInfoSpy.mock.calls,
214
+ ...consoleWarnSpy.mock.calls,
215
+ ];
216
+ const allLogs = allConsoleCalls.map(call => call.join(' ')).join('\n');
217
+
218
+ // Restore console methods
219
+ consoleLogSpy.mockRestore();
220
+ consoleErrorSpy.mockRestore();
221
+ consoleInfoSpy.mockRestore();
222
+ consoleWarnSpy.mockRestore();
223
+
224
+ // Verify lock file handling messages
225
+ expect(allLogs).toContain(`DB lock file found at ${expectedLockPath}. Checking which process holds it...`);
226
+ expect(allLogs).toContain('Lock file exists but no process is holding it. Removing stale lock file...');
227
+ expect(allLogs).toContain(`Removed stale lock file ${expectedLockPath}`);
199
228
  });
200
229
 
201
230
  it('Download pl. We have archive and extracted data', async () => {
package/src/ssh/pl.ts CHANGED
@@ -148,6 +148,7 @@ export class SshPl {
148
148
  return state.existedSettings!;
149
149
  }
150
150
  await this.doStepStopExistedPlatforma(state, onProgress);
151
+ await this.doStepCheckDbLock(state, onProgress);
151
152
 
152
153
  await onProgress?.('Installation platforma...');
153
154
 
@@ -213,6 +214,65 @@ export class SshPl {
213
214
  await onProgress?.('Connection information saved.');
214
215
  }
215
216
 
217
+ private async doStepCheckDbLock(
218
+ state: PlatformaInitState,
219
+ onProgress?: (...args: any[]) => Promise<any>,
220
+ ) {
221
+ const removeLockFile = async (lockFilePath: string) => {
222
+ try {
223
+ await this.sshClient.exec(`rm -f ${lockFilePath}`);
224
+ this.logger.info(`Removed stale lock file ${lockFilePath}`);
225
+ } catch (e: unknown) {
226
+ const msg = `Failed to remove stale lock file ${lockFilePath}: ${e}`;
227
+ this.logger.error(msg);
228
+ throw new Error(msg);
229
+ }
230
+ };
231
+
232
+ state.step = 'checkDbLock';
233
+ await onProgress?.('Checking for DB lock...');
234
+
235
+ const lockFilePath = plpath.platformaDbLock(state.remoteHome!);
236
+ const lockFileExists = await this.sshClient.checkFileExists(lockFilePath);
237
+
238
+ if (!lockFileExists) {
239
+ await onProgress?.('No DB lock found. Proceeding...');
240
+ return;
241
+ }
242
+
243
+ this.logger.info(`DB lock file found at ${lockFilePath}. Checking which process holds it...`);
244
+ const lockProcessInfo = await this.findLockHolder(lockFilePath);
245
+
246
+ if (!lockProcessInfo) {
247
+ this.logger.warn('Lock file exists but no process is holding it. Removing stale lock file...');
248
+ await removeLockFile(lockFilePath);
249
+ return;
250
+ }
251
+
252
+ this.logger.info(
253
+ `Found process ${lockProcessInfo.pid} (user: ${lockProcessInfo.user}) holding DB lock`,
254
+ );
255
+
256
+ if (lockProcessInfo.user !== this.username) {
257
+ const msg
258
+ = `DB lock is held by process ${lockProcessInfo.pid} `
259
+ + `owned by user '${lockProcessInfo.user}', but current user is '${this.username}'. `
260
+ + 'Cannot kill process owned by different user.';
261
+ this.logger.error(msg);
262
+ throw new Error(msg);
263
+ }
264
+
265
+ this.logger.info(`Process ${lockProcessInfo.pid} belongs to current user ${this.username}. Killing it...`);
266
+ await this.killRemoteProcess(lockProcessInfo.pid);
267
+ this.logger.info('Process holding DB lock has been terminated.');
268
+
269
+ // Verify lock file is gone or can be removed
270
+ const lockStillExists = await this.sshClient.checkFileExists(lockFilePath);
271
+ if (lockStillExists) {
272
+ await removeLockFile(lockFilePath);
273
+ }
274
+ }
275
+
216
276
  private async doStepConfigureSupervisord(state: PlatformaInitState, onProgress: ((...args: any) => Promise<any>) | undefined) {
217
277
  await onProgress?.('Writing supervisord configuration...');
218
278
  state.step = 'configureSupervisord';
@@ -424,6 +484,103 @@ export class SshPl {
424
484
  }
425
485
  }
426
486
 
487
+ private async findLockHolderWithLsof(lockFilePath: string): Promise<LockProcessInfo | null> {
488
+ try {
489
+ const { stdout } = await this.sshClient.exec(`lsof ${lockFilePath} 2>/dev/null || true`);
490
+ const output = stdout.trim();
491
+ if (!output) {
492
+ return null;
493
+ }
494
+
495
+ // Example:
496
+ // COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
497
+ // platforma 11628 rfiskov 10u REG 1,16 0 66670038 ./LOCK
498
+ const lines = output.split('\n');
499
+ if (lines.length <= 1) {
500
+ return null;
501
+ }
502
+
503
+ const parts = lines[1].trim().split(/\s+/);
504
+ if (parts.length < 3) {
505
+ return null;
506
+ }
507
+
508
+ const pid = Number.parseInt(parts[1], 10);
509
+ const user = parts[2];
510
+
511
+ return Number.isNaN(pid) || !user ? null : { pid, user };
512
+ } catch (e: unknown) {
513
+ this.logger.warn(`Failed to use lsof to check lock: ${e}`);
514
+ return null;
515
+ }
516
+ }
517
+
518
+ private async findLockHolderWithFuser(lockFilePath: string): Promise<LockProcessInfo | null> {
519
+ try {
520
+ const { stdout } = await this.sshClient.exec(`fuser ${lockFilePath} 2>/dev/null || true`);
521
+ const output = stdout.trim();
522
+ if (!output) {
523
+ return null;
524
+ }
525
+
526
+ // Example: ./LOCK: 11628
527
+ const match = output.match(/: (\d+)/);
528
+ if (!match) {
529
+ return null;
530
+ }
531
+
532
+ const pid = Number.parseInt(match[1], 10);
533
+ if (Number.isNaN(pid)) {
534
+ return null;
535
+ }
536
+
537
+ try {
538
+ const psResult = await this.sshClient.exec(`ps -o user= -p ${pid} 2>/dev/null || true`);
539
+ const user = psResult.stdout.trim();
540
+ return user ? { pid, user } : null;
541
+ } catch (e: unknown) {
542
+ this.logger.warn(`Failed to get user for PID ${pid}: ${e}`);
543
+ return null;
544
+ }
545
+ } catch (e: unknown) {
546
+ this.logger.warn(`Failed to use fuser to check lock: ${e}`);
547
+ return null;
548
+ }
549
+ }
550
+
551
+ private async findLockHolder(lockFilePath: string): Promise<LockProcessInfo | null> {
552
+ const viaLsof = await this.findLockHolderWithLsof(lockFilePath);
553
+ if (viaLsof) {
554
+ return viaLsof;
555
+ }
556
+ return this.findLockHolderWithFuser(lockFilePath);
557
+ }
558
+
559
+ private async killRemoteProcess(pid: number): Promise<void> {
560
+ this.logger.info(`Killing process ${pid}...`);
561
+
562
+ try {
563
+ // Try graceful termination first
564
+ await this.sshClient.exec(`kill ${pid} 2>/dev/null || true`);
565
+ await sleep(1000);
566
+
567
+ // Check if process still exists
568
+ try {
569
+ await this.sshClient.exec(`kill -0 ${pid} 2>/dev/null`);
570
+ // Process still exists, force kill
571
+ this.logger.warn(`Process ${pid} still alive after SIGTERM, forcing kill...`);
572
+ await this.sshClient.exec(`kill -9 ${pid} 2>/dev/null || true`);
573
+ await sleep(500);
574
+ } catch {
575
+ // Process is dead, nothing to do
576
+ }
577
+ } catch (e: unknown) {
578
+ const msg = `Failed to kill process ${pid}: ${e}`;
579
+ this.logger.error(msg);
580
+ throw new Error(msg);
581
+ }
582
+ }
583
+
427
584
  /** We have to extract pl in the remote server,
428
585
  * because Windows doesn't support symlinks
429
586
  * that are found in Linux pl binaries tgz archive.
@@ -616,6 +773,8 @@ export type SshPlConfig = {
616
773
  plConfigPostprocessing?: (config: PlConfig) => PlConfig;
617
774
  };
618
775
 
776
+ export type LockProcessInfo = { pid: number; user: string };
777
+
619
778
  const defaultSshPlConfig: Pick<
620
779
  SshPlConfig,
621
780
  | 'useGlobalAccess'
@@ -653,6 +812,7 @@ type PlatformaInitStep =
653
812
  | 'detectHome'
654
813
  | 'checkAlive'
655
814
  | 'stopExistedPlatforma'
815
+ | 'checkDbLock'
656
816
  | 'downloadBinaries'
657
817
  | 'fetchPorts'
658
818
  | 'generateNewConfig'
@@ -63,3 +63,7 @@ export function connectionInfo(remoteHome: string) {
63
63
  export function platformaCliLogs(remoteHome: string) {
64
64
  return upath.join(workDir(remoteHome), 'platforma_cli_logs.log');
65
65
  }
66
+
67
+ export function platformaDbLock(remoteHome: string) {
68
+ return upath.join(workDir(remoteHome), 'db', 'LOCK');
69
+ }