From a2e175e61f4f9d2fa2c967396fc1957281024b84 Mon Sep 17 00:00:00 2001 From: antonio Date: Thu, 25 Jul 2024 09:12:17 +0200 Subject: [PATCH 1/3] Added dynamic path to look for im_client.py --- src/deploymentMenu.ts | 38 +++++++++++--------------------------- src/listDeployments.ts | 16 ++++++++++------ src/utils.ts | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 33 deletions(-) create mode 100755 src/utils.ts diff --git a/src/deploymentMenu.ts b/src/deploymentMenu.ts index 38864fa..ef97ce1 100644 --- a/src/deploymentMenu.ts +++ b/src/deploymentMenu.ts @@ -3,6 +3,8 @@ import { ContentsManager } from '@jupyterlab/services'; import { KernelManager } from '@jupyterlab/services'; import { Widget } from '@lumino/widgets'; import { Dialog } from '@jupyterlab/apputils'; +import { executeKernelCommand, getIMClientPath } from './utils'; + interface IDeployInfo { IMuser: string; @@ -179,27 +181,6 @@ function getInputValue(inputId: string): string { return input.value; } -async function executeKernelCommand( - command: string, - callback: (output: string) => void -): Promise { - try { - const kernelManager = new KernelManager(); - const kernel = await kernelManager.startNew(); - const future = kernel.requestExecute({ code: command }); - - future.onIOPub = msg => { - const content = msg.content as any; - const outputText = - content.text || (content.data && content.data['text/plain']); - callback(outputText); - }; - } catch (error) { - console.error('Error executing kernel command:', error); - deploying = false; - } -} - async function computeHash(input: string): Promise { const msgUint8 = new TextEncoder().encode(input); const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8); @@ -445,8 +426,9 @@ async function createChildsForm( //* Bash commands *// //*********************// -function selectImage(obj: IDeployInfo): string { +async function selectImage(obj: IDeployInfo): Promise { const pipeAuth = `${obj.infName}-auth-pipe`; + const imClientPath = await getIMClientPath(); let cmd = `%%bash PWD=$(pwd) @@ -473,7 +455,7 @@ function selectImage(obj: IDeployInfo): string { cmd += `echo -e "${authContent}" > $PWD/${pipeAuth} & # Create final command where the output is stored in "imageOut" - imageOut=$(python3 /usr/local/bin/im_client.py -a $PWD/${pipeAuth} -r https://im.egi.eu/im cloudimages ${obj.id}) + imageOut=$(python3 ${imClientPath} -a $PWD/${pipeAuth} -r https://im.egi.eu/im cloudimages ${obj.id}) # Remove pipe rm -f $PWD/${pipeAuth} &> /dev/null # Print IM output on stderr or stdout @@ -508,10 +490,12 @@ const getEGIToken = async () => { }); }; -function deployIMCommand(obj: IDeployInfo, mergedTemplate: string): string { +async function deployIMCommand(obj: IDeployInfo, mergedTemplate: string): Promise { const pipeAuth = `${obj.infName}-auth-pipe`; + const imClientPath = await getIMClientPath(); const imageRADL = obj.infName; const templatePath = `$PWD/deployed-templates/${imageRADL}.yaml`; + let cmd = `%%bash PWD=$(pwd) # Remove pipes if they exist @@ -539,7 +523,7 @@ function deployIMCommand(obj: IDeployInfo, mergedTemplate: string): string { cmd += `echo -e "${authContent}" > $PWD/${pipeAuth} & # Create final command where the output is stored in "imageOut" - imageOut=$(python3 /usr/local/bin/im_client.py -a $PWD/${pipeAuth} create ${templatePath} -r https://im.egi.eu/im) + imageOut=$(python3 ${imClientPath} -a $PWD/${pipeAuth} create ${templatePath} -r https://im.egi.eu/im) # Remove pipe rm -f $PWD/${pipeAuth} &> /dev/null # Print IM output on stderr or stdout @@ -921,7 +905,7 @@ async function deployInfraConfiguration( if (deployInfo.deploymentType !== 'EC2') { // Create select image command - const cmdImageNames = selectImage(deployInfo); + const cmdImageNames = await selectImage(deployInfo); try { // Execute the deployment command @@ -1106,7 +1090,7 @@ async function deployFinalRecipe( const mergedYamlContent = jsyaml.dump(mergedTemplate); // Create deploy command - const cmdDeploy = deployIMCommand(deployInfo, mergedYamlContent); + const cmdDeploy = await deployIMCommand(deployInfo, mergedYamlContent); // Show loading spinner dialogBody.innerHTML = diff --git a/src/listDeployments.ts b/src/listDeployments.ts index e08c78a..349f7c9 100644 --- a/src/listDeployments.ts +++ b/src/listDeployments.ts @@ -1,6 +1,8 @@ import { KernelManager } from '@jupyterlab/services'; import { Dialog } from '@jupyterlab/apputils'; import { Widget } from '@lumino/widgets'; +import { getIMClientPath } from './utils'; + interface IInfrastructure { IMuser: string; @@ -113,7 +115,7 @@ async function populateTable(table: HTMLTableElement): Promise { const stateCell = row.insertCell(); try { - const cmdState = infrastructureState(infrastructure); + const cmdState = await infrastructureState(infrastructure); // Execute kernel to get output const futureState = kernel.requestExecute({ code: cmdState }); @@ -149,7 +151,7 @@ async function populateTable(table: HTMLTableElement): Promise { } try { - const cmdIP = infrastructureIP(infrastructure); + const cmdIP = await infrastructureIP(infrastructure); // Execute kernel to get output const futureIP = kernel.requestExecute({ code: cmdIP }); @@ -185,7 +187,7 @@ async function populateTable(table: HTMLTableElement): Promise { await kernel.shutdown(); } -function infrastructureState(infrastructure: IInfrastructure): string { +async function infrastructureState(infrastructure: IInfrastructure): Promise { const { IMuser, IMpass, @@ -202,6 +204,7 @@ function infrastructureState(infrastructure: IInfrastructure): string { } = infrastructure; const pipeAuth = 'auth-pipe'; + const imClientPath = await getIMClientPath(); let authContent = `id=im; type=InfrastructureManager; username=${IMuser}; password=${IMpass};\n`; authContent += `id=${id}; type=${type}; host=${host};`; @@ -232,7 +235,7 @@ function infrastructureState(infrastructure: IInfrastructure): string { # Command to create the infrastructure manager client credentials echo -e "${authContent}" > $PWD/${pipeAuth} & - stateOut=$(python3 /usr/local/bin/im_client.py getstate ${infrastructureID} -r https://im.egi.eu/im -a $PWD/${pipeAuth}) + stateOut=$(python3 ${imClientPath} getstate ${infrastructureID} -r https://im.egi.eu/im -a $PWD/${pipeAuth}) # Remove pipe rm -f $PWD/${pipeAuth} &> /dev/null # Print state output on stderr or stdout @@ -248,7 +251,7 @@ function infrastructureState(infrastructure: IInfrastructure): string { return cmd; } -function infrastructureIP(infrastructure: IInfrastructure): string { +async function infrastructureIP(infrastructure: IInfrastructure): Promise { const { IMuser, IMpass, @@ -265,6 +268,7 @@ function infrastructureIP(infrastructure: IInfrastructure): string { } = infrastructure; const pipeAuth = 'auth-pipe'; + const imClientPath = await getIMClientPath(); let authContent = `id=im; type=InfrastructureManager; username=${IMuser}; password=${IMpass};\n`; authContent += `id=${id}; type=${type}; host=${host};`; @@ -295,7 +299,7 @@ function infrastructureIP(infrastructure: IInfrastructure): string { # Command to create the infrastructure manager client credentials echo -e "${authContent}" > $PWD/${pipeAuth} & - stateOut=$(python3 /usr/local/bin/im_client.py getvminfo ${infrastructureID} 0 net_interface.1.ip -r https://im.egi.eu/im -a $PWD/${pipeAuth}) + stateOut=$(python3 ${imClientPath} getvminfo ${infrastructureID} 0 net_interface.1.ip -r https://im.egi.eu/im -a $PWD/${pipeAuth}) # Remove pipe rm -f $PWD/${pipeAuth} &> /dev/null # Print state output on stderr or stdout diff --git a/src/utils.ts b/src/utils.ts new file mode 100755 index 0000000..16c8206 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,35 @@ +import { KernelManager } from '@jupyterlab/services'; + +export async function executeKernelCommand( + command: string, + callback: (output: string) => void +): Promise { + try { + const kernelManager = new KernelManager(); + const kernel = await kernelManager.startNew(); + const future = kernel.requestExecute({ code: command }); + + future.onIOPub = msg => { + const content = msg.content as any; + const outputText = + content.text || (content.data && content.data['text/plain']); + callback(outputText); + }; + } catch (error) { + console.error('Error executing kernel command:', error); + } +} + +export async function getIMClientPath(): Promise { + return new Promise((resolve, reject) => { + const cmdIMClientPath = '%%bash\n' + 'which im_client.py'; + + executeKernelCommand(cmdIMClientPath, output => { + if (output.trim()) { + resolve(output.trim()); + } else { + reject(new Error('Failed to find im_client.py path. Maybe IM-client is not installed.')); + } + }).catch(reject); + }); +} From 962df2e69b9e27a32b83819210f181196c7627ea Mon Sep 17 00:00:00 2001 From: antonio Date: Thu, 25 Jul 2024 09:19:59 +0200 Subject: [PATCH 2/3] Added deployed-templates folder --- deployed-templates/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 deployed-templates/.gitkeep diff --git a/deployed-templates/.gitkeep b/deployed-templates/.gitkeep new file mode 100644 index 0000000..e69de29 From 925cbc8aca65e8b5518fcea6aa726cefbb08e158 Mon Sep 17 00:00:00 2001 From: antonio Date: Thu, 25 Jul 2024 09:34:27 +0200 Subject: [PATCH 3/3] Linted lines --- src/deploymentMenu.ts | 6 ++++-- src/listDeployments.ts | 9 ++++++--- src/utils.ts | 6 +++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/deploymentMenu.ts b/src/deploymentMenu.ts index ef97ce1..6d91c5f 100644 --- a/src/deploymentMenu.ts +++ b/src/deploymentMenu.ts @@ -5,7 +5,6 @@ import { Widget } from '@lumino/widgets'; import { Dialog } from '@jupyterlab/apputils'; import { executeKernelCommand, getIMClientPath } from './utils'; - interface IDeployInfo { IMuser: string; IMpass: string; @@ -490,7 +489,10 @@ const getEGIToken = async () => { }); }; -async function deployIMCommand(obj: IDeployInfo, mergedTemplate: string): Promise { +async function deployIMCommand( + obj: IDeployInfo, + mergedTemplate: string +): Promise { const pipeAuth = `${obj.infName}-auth-pipe`; const imClientPath = await getIMClientPath(); const imageRADL = obj.infName; diff --git a/src/listDeployments.ts b/src/listDeployments.ts index 349f7c9..d5c8f8e 100644 --- a/src/listDeployments.ts +++ b/src/listDeployments.ts @@ -3,7 +3,6 @@ import { Dialog } from '@jupyterlab/apputils'; import { Widget } from '@lumino/widgets'; import { getIMClientPath } from './utils'; - interface IInfrastructure { IMuser: string; IMpass: string; @@ -187,7 +186,9 @@ async function populateTable(table: HTMLTableElement): Promise { await kernel.shutdown(); } -async function infrastructureState(infrastructure: IInfrastructure): Promise { +async function infrastructureState( + infrastructure: IInfrastructure +): Promise { const { IMuser, IMpass, @@ -251,7 +252,9 @@ async function infrastructureState(infrastructure: IInfrastructure): Promise { +async function infrastructureIP( + infrastructure: IInfrastructure +): Promise { const { IMuser, IMpass, diff --git a/src/utils.ts b/src/utils.ts index 16c8206..8676808 100755 --- a/src/utils.ts +++ b/src/utils.ts @@ -28,7 +28,11 @@ export async function getIMClientPath(): Promise { if (output.trim()) { resolve(output.trim()); } else { - reject(new Error('Failed to find im_client.py path. Maybe IM-client is not installed.')); + reject( + new Error( + 'Failed to find im_client.py path. Maybe IM-client is not installed.' + ) + ); } }).catch(reject); });