You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1198 lines
38 KiB
1198 lines
38 KiB
unit Unit1; |
|
|
|
{$mode objfpc}{$H+} |
|
|
|
interface |
|
|
|
uses |
|
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, Process, lclintf |
|
{$IFDEF WINDOWS} |
|
,ShellApi |
|
{$ENDIF} |
|
; |
|
|
|
type |
|
|
|
{ TForm1 } |
|
|
|
TForm1 = class(TForm) |
|
Button1: TButton; |
|
Button10: TButton; |
|
Button11: TButton; |
|
Button12: TButton; |
|
Button13: TButton; |
|
Button14: TButton; |
|
Button15: TButton; |
|
Button16: TButton; |
|
Button17: TButton; |
|
Button18: TButton; |
|
Button19: TButton; |
|
Button2: TButton; |
|
Button20: TButton; |
|
Button21: TButton; |
|
Button22: TButton; |
|
Button23: TButton; |
|
Button24: TButton; |
|
Button25: TButton; |
|
Button26: TButton; |
|
Button27: TButton; |
|
Button28: TButton; |
|
Button29: TButton; |
|
Button3: TButton; |
|
Button30: TButton; |
|
Button31: TButton; |
|
Button32: TButton; |
|
Button33: TButton; |
|
Button34: TButton; |
|
Button35: TButton; |
|
Button36: TButton; |
|
Button37: TButton; |
|
Button38: TButton; |
|
Button39: TButton; |
|
Button4: TButton; |
|
Button40: TButton; |
|
Button41: TButton; |
|
Button5: TButton; |
|
Button6: TButton; |
|
Button7: TButton; |
|
Button8: TButton; |
|
Button9: TButton; |
|
Label1: TLabel; |
|
Label27: TLabel; |
|
LabelCPU3: TLabel; |
|
LabelMEM3: TLabel; |
|
Label12: TLabel; |
|
LabelCPU4: TLabel; |
|
LabelMEM4: TLabel; |
|
Label15: TLabel; |
|
Label16: TLabel; |
|
LabelCPU5: TLabel; |
|
LabelMEM5: TLabel; |
|
Label19: TLabel; |
|
LabelCPU1: TLabel; |
|
Label20: TLabel; |
|
LabelCPU6: TLabel; |
|
LabelMEM6: TLabel; |
|
Label23: TLabel; |
|
Label24: TLabel; |
|
Label25: TLabel; |
|
Label26: TLabel; |
|
LabelMEM1: TLabel; |
|
Label4: TLabel; |
|
Label5: TLabel; |
|
Label6: TLabel; |
|
LabelCPU2: TLabel; |
|
LabelMEM2: TLabel; |
|
Label9: TLabel; |
|
LabelStatus: TLabel; |
|
Memo1: TMemo; |
|
Memo2: TMemo; |
|
Memo3: TMemo; |
|
Memo4: TMemo; |
|
Memo5: TMemo; |
|
Memo6: TMemo; |
|
Shape1: TShape; |
|
Shape2: TShape; |
|
Shape3: TShape; |
|
Shape5: TShape; |
|
Shape7: TShape; |
|
Shape8: TShape; |
|
Timer1: TTimer; |
|
procedure Button10Click(Sender: TObject); |
|
procedure Button11Click(Sender: TObject); |
|
procedure Button12Click(Sender: TObject); |
|
procedure Button13Click(Sender: TObject); |
|
procedure Button14Click(Sender: TObject); |
|
procedure Button15Click(Sender: TObject); |
|
procedure Button16Click(Sender: TObject); |
|
procedure Button17Click(Sender: TObject); |
|
procedure Button18Click(Sender: TObject); |
|
procedure Button19Click(Sender: TObject); |
|
procedure Button1Click(Sender: TObject); |
|
procedure Button20Click(Sender: TObject); |
|
procedure Button21Click(Sender: TObject); |
|
procedure Button22Click(Sender: TObject); |
|
procedure Button23Click(Sender: TObject); |
|
procedure Button24Click(Sender: TObject); |
|
procedure Button25Click(Sender: TObject); |
|
procedure Button26Click(Sender: TObject); |
|
procedure Button27Click(Sender: TObject); |
|
procedure Button28Click(Sender: TObject); |
|
procedure Button29Click(Sender: TObject); |
|
procedure Button2Click(Sender: TObject); |
|
procedure Button30Click(Sender: TObject); |
|
procedure Button31Click(Sender: TObject); |
|
procedure Button32Click(Sender: TObject); |
|
procedure Button33Click(Sender: TObject); |
|
procedure Button34Click(Sender: TObject); |
|
procedure Button35Click(Sender: TObject); |
|
procedure Button36Click(Sender: TObject); |
|
procedure Button37Click(Sender: TObject); |
|
procedure Button38Click(Sender: TObject); |
|
procedure Button39Click(Sender: TObject); |
|
procedure Button3Click(Sender: TObject); |
|
procedure Button40Click(Sender: TObject); |
|
procedure Button41Click(Sender: TObject); |
|
procedure Button4Click(Sender: TObject); |
|
procedure Button5Click(Sender: TObject); |
|
procedure Button6Click(Sender: TObject); |
|
procedure Button7Click(Sender: TObject); |
|
procedure Button8Click(Sender: TObject); |
|
procedure Button9Click(Sender: TObject); |
|
procedure FormCreate(Sender: TObject); |
|
procedure FormShow(Sender: TObject); |
|
procedure Label6Click(Sender: TObject); |
|
procedure Memo1Change(Sender: TObject); |
|
procedure Timer1Timer(Sender: TObject); |
|
private |
|
|
|
public |
|
|
|
end; |
|
|
|
var |
|
Form1: TForm1; |
|
haumea_unlocked, hlrn_unlocked: Boolean; |
|
favouriteTerminalStart, favouriteTerminalEnd: String; |
|
|
|
implementation |
|
|
|
uses Unit2, Unit3; |
|
|
|
{$R *.lfm} |
|
|
|
procedure OpenNmonUrl(hostname: String); |
|
begin |
|
OpenUrl('http://phywiki.io-warnemuende.de/local_htmls/nmon/nmon_stat_'+hostname+'.html') |
|
end; |
|
|
|
function funIstVerzeichnisLeer(strVerzeichnis: string): boolean; |
|
// check if directory empty |
|
var |
|
srDatensatz: TSearchRec; |
|
intI: integer; |
|
begin |
|
Result := False; |
|
|
|
FindFirst(IncludeTrailingPathDelimiter(strVerzeichnis) + '*', faAnyFile, srDatensatz); |
|
|
|
for intI := 1 to 2 do |
|
if (srDatensatz.Name = '.') or (srDatensatz.Name = '..') then |
|
Result := FindNext(srDatensatz) <> 0; |
|
|
|
FindClose(srDatensatz); |
|
end; |
|
|
|
procedure ShowUsageInfo(var sl: TStringList; var LabelCPU: TLabel; var LabelMEM: TLabel; var Memo: TMemo); |
|
begin |
|
LabelCPU.Caption := 'CPUs used (total): '+trim(sl[0])+' ('+trim(sl[1])+')'; |
|
sl.Delete(0); sl.Delete(0); |
|
LabelMEM.Caption := 'RAM used (total): '+ |
|
IntToStr(round(StrToInt(trim(sl[0]))/1024/1024))+' GB ('+ |
|
IntToStr(round(StrToInt(trim(sl[1]))/1024/1024))+' GB)'; |
|
sl.Delete(0); sl.Delete(0); |
|
Memo.Lines.Clear; |
|
while (sl.count>1) and (sl[0]<>'*****') do |
|
begin |
|
Memo.Lines.Add(sl[0]); |
|
sl.Delete(0); |
|
end; |
|
sl.Delete(0); |
|
Memo.SelStart := 0; |
|
Memo.SelLength := 0; |
|
end; |
|
|
|
function SpaceItem(var s: String): String; |
|
//returns the text before the first space and removes this part from the input string |
|
begin |
|
s:=trim(s); |
|
if pos(' ',s)>0 then |
|
begin |
|
result:=copy(s,1,pos(' ',s)-1); |
|
s:=trim(copy(s,pos(' ',s)+1,length(s))); |
|
end |
|
else |
|
begin |
|
result:=s; |
|
s:=''; |
|
end; |
|
end; |
|
|
|
function MyRunProcess(command: String; hidden: Boolean; wait: Boolean; var process: TProcess): TStringList; |
|
var |
|
mycommand: String; |
|
AProcess: TProcess; |
|
AStringList: TStringList; |
|
si: String; |
|
begin |
|
AProcess := TProcess.Create(nil); |
|
//split into command and arguments |
|
mycommand:=command; |
|
AProcess.Executable := SpaceItem(mycommand); |
|
while mycommand<>'' do |
|
AProcess.Parameters.Add(spaceItem(myCommand)); |
|
if wait then |
|
AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes] |
|
else |
|
AProcess.Options := AProcess.Options + [poUsePipes]; |
|
if hidden then |
|
AProcess.ShowWindow := swoHide |
|
else |
|
AProcess.Options := AProcess.Options + [poNewConsole]; |
|
AProcess.Execute; |
|
AStringList := TStringList.Create; |
|
if wait then AStringList.LoadFromStream(AProcess.Output); |
|
process := AProcess; |
|
Result := AStringList; |
|
end; |
|
|
|
function MyRunProcess(command: String; hidden: Boolean; wait: Boolean): TStringList; overload; |
|
var |
|
AProcess: TProcess; |
|
AStringList: TStringList; |
|
begin |
|
AStringList:=MyRunProcess(command,hidden,wait,AProcess); |
|
AProcess.Free; |
|
Result := AStringList; |
|
end; |
|
|
|
procedure unlock_haumea; |
|
begin |
|
MyRunProcess('xterm -e ssh-add '+GetUserDir+'/.ssh/id_rsa_unirostock',false,true); |
|
haumea_unlocked:=true; |
|
end; |
|
|
|
procedure unlock_hlrn; |
|
begin |
|
MyRunProcess('xterm -e ssh-add '+GetUserDir+'/.ssh/id_rsa_hlrn',false,true); |
|
hlrn_unlocked:=true; |
|
end; |
|
|
|
procedure ShowErrorDisconnectedIOW; |
|
begin |
|
if MessageDlg('Connection failed', |
|
'Could not connect to IOW server rdpserv. Please check if you are in the IOW Intranet.'+chr(13)+ |
|
'Would you like to see instructions how to connect?',mtConfirmation,[mbYes,mbAbort],0,mbAbort)=mrYes then |
|
OpenUrl('https://intranet.io-warnemuende.de/vpn-access-to-the-iow.html'); |
|
end; |
|
|
|
procedure ShowErrorDisconnectedHaumea; |
|
begin |
|
if MessageDlg('Connection failed', |
|
'Could not connect to haumea1. Please check if your settings in ~/.ssh/config are correct.'+chr(13)+ |
|
'Would you like to see instructions how to connect?',mtConfirmation,[mbYes,mbAbort],0,mbAbort)=mrYes then |
|
OpenUrl('http://phywiki.io-warnemuende.de/do/view/Server/UniRostockClusterDocu'); |
|
end; |
|
|
|
function PortFromUserid(userid: Integer; where: String='IOW'; what: String='JUPYTER'): Integer; |
|
begin |
|
Result:=0; |
|
if (where='IOW' ) and (what='JUPYTER') then Result:=userid+10000; |
|
if (where='REMOTE') and (what='JUPYTER') then Result:=userid+10000; |
|
if (where='IOW' ) and (what='XPRA') then Result:=userid+20000; |
|
if (where='REMOTE') and (what='XPRA') then Result:=userid+20000; |
|
end; |
|
|
|
procedure StartJupyterlabIOW(hostname: String); |
|
var |
|
sl, sl1: TStringList; |
|
username, command, s: String; |
|
userid, port, ReadSize: Integer; |
|
process: TProcess; |
|
Buffer: array[0..100000] of char; |
|
found, hasGPU: boolean; |
|
portBlocked: Boolean; |
|
F: TextFile; |
|
begin |
|
hasGPU := (hostname='phy-4'); |
|
// Show Form2 to enter details for parallel processing and job registration |
|
Form2.Edit1.Text:=hostname; |
|
Form2.Label2.Visible:=true; |
|
Form2.SpinEdit1.Visible:=true; |
|
Form2.SpinEdit1.Value:=1; |
|
Form2.Label3.Visible := hasGPU; |
|
Form2.Edit2.Visible := hasGPU; |
|
Form2.Edit2.Text := 'no GPUs'; |
|
Form2.Label4.Visible:=true; |
|
Form2.Edit3.Visible:=true; |
|
Form2.Edit3.Text:=''; |
|
Form2.SpinEdit2.Value:=8; |
|
Form2.Label6.Visible:=false; |
|
Form2.ComboBox1.Visible:=false; |
|
Form2.Tag:=0; |
|
Form2.ShowModal; |
|
Application.ProcessMessages; |
|
if Form2.Tag<>1 then exit; |
|
|
|
Form1.LabelStatus.Caption:='connecting to IOW...'; |
|
Form1.LabelStatus.Repaint; |
|
found:=false; // we will try to find the token in the output |
|
// get IOW username and userid |
|
sl:=MyRunProcess('ssh rdpserv whoami ; id -u',true,true); |
|
if sl.count=2 then |
|
begin |
|
username:=trim(sl[0]); |
|
userid:=StrToInt(sl[1]); |
|
port:=PortFromUserid(userid,'IOW'); |
|
// write the jupyterlab script |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/jupyterlab_iow.sh'); |
|
rewrite(F); |
|
writeln(F,'source ~/.bashrc'); |
|
writeln(F,'source ~/.bash_profile'); |
|
writeln(F,'module load miniconda3'); |
|
writeln(F,'ncores='+IntToStr(Form2.SpinEdit1.Value)); |
|
if Form2.Edit3.Text<>'' then |
|
begin |
|
writeln(F,'echo $BASHPID > PID'); |
|
if hasGPU then |
|
writeln(F,'echo "$ncores CPU cores and '+Form2.Edit2.Text+'" >> PID') |
|
else |
|
writeln(F,'echo "$ncores CPU cores" >> PID'); |
|
writeln(F,'echo "runs '+IntToStr(Form2.SpinEdit2.Value)+' hours" >> PID'); |
|
writeln(F,'echo "'+Form2.Edit3.Text+'" >> PID'); |
|
writeln(F,'add_to_list < PID'); |
|
end; |
|
writeln(F,'export OMP_NUM_THREADS=$ncores'); |
|
writeln(F,'export OPENBLAS_NUM_THREADS=$ncores'); |
|
writeln(F,'export MKL_NUM_THREADS=$ncores'); |
|
writeln(F,'export VECLIB_MAXIMUM_THREADS=$ncores'); |
|
writeln(F,'export NUMEXPR_NUM_THREADS=$ncores'); |
|
writeln(F,'jupyter lab'); |
|
closefile(F); |
|
Form1.LabelStatus.Caption:='transferring job script...'; |
|
Form1.LabelStatus.Repaint; |
|
// copy the jupyterlab script to IOW |
|
command := 'scp '+ExtractFilePath(application.ExeName)+'/jupyterlab_iow.sh rdpserv:/home/nis/'+username; |
|
MyRunProcess(command,true,true); |
|
// convert to unix line endings and set execute permissions |
|
command := 'ssh rdpserv dos2unix /home/nis/'+username+'/jupyterlab_iow.sh'; |
|
MyRunProcess(command,true,true); |
|
command := 'ssh rdpserv chmod u+x /home/nis/'+username+'/jupyterlab_iow.sh'; |
|
MyRunProcess(command,true,true); |
|
Form1.LabelStatus.Caption:='checking if port is free...'; |
|
Form1.LabelStatus.Repaint; |
|
// check if port is in use |
|
portBlocked:=false; |
|
command := 'ssh rdpserv fuser '+IntToStr(port)+'/tcp'; |
|
sl1:=MyRunProcess(command,true,true); |
|
if sl1.Count>=1 then portBlocked:=true; |
|
sl1.Free; |
|
command := 'ssh rdpserv ssh '+hostname+' fuser '+IntToStr(port)+'/tcp'; |
|
sl1:=MyRunProcess(command,true,true); |
|
if sl1.Count>=1 then portBlocked:=true; |
|
sl1.Free; |
|
if portBlocked then |
|
if MessageDlg('port in use','Port '+IntToStr(port)+' is already in use by another process. Kill that process?',mtConfirmation,[mbYes,mbAbort],0,mbAbort)=mrYes then |
|
begin |
|
command := 'ssh rdpserv fuser -k -n tcp '+IntToStr(port); |
|
MyRunProcess(command,true,true); |
|
command := 'ssh rdpserv ssh '+hostname+' fuser -k -n tcp '+IntToStr(port); |
|
MyRunProcess(command,true,true); |
|
sleep(1000); |
|
end |
|
else |
|
exit; |
|
Form1.LabelStatus.Caption:='running jupyterlab command...'; |
|
Form1.LabelStatus.Repaint; |
|
// prepare the jupyterlab command and run it |
|
command := 'ssh -t rdpserv -L '+IntToStr(port)+':localhost:'+IntToStr(port)+ |
|
' ssh -t '+hostname+' -L '+IntToStr(port)+':localhost:'+IntToStr(port)+ |
|
' /bin/bash -c "/home/nis/'+username+'/jupyterlab_iow.sh 2>&1"'; |
|
{$IFDEF LINUX} |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/command.sh'); |
|
Rewrite(F); |
|
writeln(F,command); |
|
closefile(F); |
|
MyRunProcess('/bin/bash -e '+ExtractFilePath(Application.ExeName)+'/command.sh',true,false,process); |
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
MyRunProcess(command,true,false,process); |
|
{$ENDIF} |
|
// seek the output for the token |
|
while (process.Running or (process.Output.NumBytesAvailable > 0)) and (not found) do |
|
begin |
|
Form1.LabelStatus.Caption:='waiting for the token...'; |
|
Form1.LabelStatus.Repaint; |
|
if process.Output.NumBytesAvailable > 0 then |
|
begin |
|
// make sure that we don't read more data than we have allocated |
|
// in the buffer |
|
ReadSize := process.Output.NumBytesAvailable; |
|
if ReadSize > SizeOf(Buffer) then |
|
ReadSize := SizeOf(Buffer); |
|
// now read the output into the buffer |
|
process.Output.Read(Buffer[0], ReadSize); |
|
// and if it contains a token, then open a URL in the browser |
|
s:=Buffer; |
|
if pos('?token=',s)>0 then |
|
begin |
|
s:=copy(s,pos('?token=',s)+7,48); |
|
Form1.LabelStatus.Caption:='opening browser...'; |
|
Form1.LabelStatus.Repaint; |
|
OpenUrl('http://127.0.0.1:'+IntToStr(port)+'?token='+s); |
|
found:=true; |
|
end; |
|
end; |
|
end; |
|
end |
|
else |
|
ShowErrorDisconnectedIOW; |
|
Form1.Timer1Timer(Form1); |
|
sl.Free; |
|
Form1.LabelStatus.Caption:=''; |
|
end; |
|
|
|
procedure StartJupyterlabRemote(hostname: String='haumea1'); |
|
var |
|
sl, sl1: TStringList; |
|
username, command, s: String; |
|
i, userid, port, ReadSize: Integer; |
|
process, process1: TProcess; |
|
Buffer: array[0..100000] of char; |
|
found, hasGPU: boolean; |
|
portBlocked: Boolean; |
|
F: TextFile; |
|
remoteBasepath, nodeName: String; |
|
begin |
|
{$IFDEF WINDOWS} |
|
// first we need to start the ssh-agent to enable passwordless login |
|
MyRunProcess('powershell -command "& {&''Start-Service'' ssh-agent}"',true,true); |
|
{$ENDIF} |
|
{$IFDEF Linux} |
|
// we need to unlock a key to allow passwordless login |
|
if (hostname='haumea1') and (haumea_unlocked=false) then unlock_haumea; |
|
if (hostname='blogin') and (hlrn_unlocked=false) then unlock_hlrn; |
|
if (hostname='glogin') and (hlrn_unlocked=false) then unlock_hlrn; |
|
{$ENDIF} |
|
if hostname='haumea1' then remoteBasepath:='/data'; |
|
if hostname='blogin' then remoteBasepath:='/scratch/usr'; |
|
if hostname='glogin' then remoteBasepath:='/scratch/usr'; |
|
// Show Form2 to enter details for parallel processing and job registration |
|
Form2.Edit1.Text:=hostname; |
|
Form2.Label2.Visible:=false; |
|
Form2.SpinEdit1.Visible:=false; |
|
Form2.Label3.Visible := false; |
|
Form2.Edit2.Visible := false; |
|
Form2.Label4.Visible:=false; |
|
Form2.Edit3.Visible:=false; |
|
Form2.SpinEdit2.Value:=8; |
|
Form2.Label6.Visible:=true; |
|
Form2.ComboBox1.Visible:=true; |
|
Form2.ComboBox1.Items.Clear; |
|
if hostname='haumea1' then |
|
begin |
|
Form2.ComboBox1.Items.Add('compute'); |
|
Form2.ComboBox1.Items.Add('requeue'); |
|
end |
|
else if hostname='blogin' then |
|
begin |
|
Form2.ComboBox1.Items.Add('standard96'); |
|
Form2.ComboBox1.Items.Add('standard96:test'); |
|
Form2.ComboBox1.Items.Add('large96'); |
|
Form2.ComboBox1.Items.Add('large96:test'); |
|
Form2.ComboBox1.Items.Add('huge96'); |
|
end |
|
else if hostname='glogin' then |
|
begin |
|
Form2.ComboBox1.Items.Add('medium40'); |
|
Form2.ComboBox1.Items.Add('medium40:test'); |
|
Form2.ComboBox1.Items.Add('large40'); |
|
Form2.ComboBox1.Items.Add('large40:test'); |
|
Form2.ComboBox1.Items.Add('standard96'); |
|
Form2.ComboBox1.Items.Add('standard96:test'); |
|
Form2.ComboBox1.Items.Add('large96'); |
|
Form2.ComboBox1.Items.Add('large96:test'); |
|
Form2.ComboBox1.Items.Add('huge96'); |
|
end; |
|
Form2.ComboBox1.ItemIndex:=0; |
|
Form2.Tag:=0; |
|
Form2.ShowModal; |
|
Application.ProcessMessages; |
|
if Form2.Tag <> 1 then exit; |
|
|
|
Form1.LabelStatus.Caption:='connecting to '+hostname+'...'; |
|
Form1.LabelStatus.Repaint; |
|
found:=false; // we will try to find the token in the output |
|
// get remote location username and userid |
|
sl:=MyRunProcess('ssh '+hostname+' whoami ; id -u',true,true); |
|
if sl.count=2 then |
|
begin |
|
username:=trim(sl[0]); |
|
userid:=StrToInt(sl[1]); |
|
port:=PortFromUserid(userid,'REMOTE'); |
|
// write the jupyterlab script |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/jupyterlab_remote.sh'); |
|
rewrite(F); |
|
writeln(F,'#!/bin/bash'); |
|
writeln(F,'#'); |
|
writeln(F,'#SBATCH --job-name=jupyter'); |
|
writeln(F,'#SBATCH --output='+remoteBasepath+'/%u/.jupyter_out.txt'); |
|
writeln(F,'#SBATCH --nodes 1'); |
|
writeln(F,'#SBATCH --ntasks=1'); |
|
writeln(F,'#SBATCH -t '+IntToStr(Form2.SpinEdit2.Value)+':00:00'); |
|
writeln(F,'#SBATCH -p '+Form2.ComboBox1.Items[Form2.ComboBox1.ItemIndex]); |
|
writeln(F,''); |
|
writeln(F,'source ~/.bashrc'); |
|
writeln(F,'PATH=$PATH:$HOME/.local/bin:$HOME/bin'); |
|
writeln(F,''); |
|
writeln(F,'export PATH'); |
|
writeln(F,''); |
|
if hostname='haumea1' then |
|
begin |
|
writeln(F,'export MODULEPATH=$MODULEPATH:/data/iow/iow-modules/DATAFORMATS'); |
|
writeln(F,'export MODULEPATH=$MODULEPATH:/data/iow/iow-modules/VISUALISATION'); |
|
writeln(F,'export MODULEPATH=$MODULEPATH:/data/iow/iow-modules/MPI'); |
|
writeln(F,'export MODULEPATH=$MODULEPATH:/data/iow/iow-modules/NUMERICS'); |
|
writeln(F,'module load miniconda3'); |
|
end |
|
else |
|
writeln(F,'module load anaconda3'); |
|
writeln(F,''); |
|
writeln(F,'export OMP_NUM_THREADS=40'); |
|
writeln(F,'export KMP_AFFINITY=compact,1,0,granularity=fine'); |
|
writeln(F,'export MKLDNN_VERBOSE=1'); |
|
writeln(F,'export MYJUPYTERPORT='+IntToStr(port)); |
|
writeln(F,'export XDG_RUNTIME_DIR="'+remoteBasepath+'/$USER"'); |
|
writeln(F,'hostname > '+remoteBasepath+'/'+username+'/.jupyterlab_hostname.txt'); |
|
writeln(F,'jupyter lab --port $MYJUPYTERPORT --ip 0.0.0.0 --no-browser --notebook-dir="'+remoteBasepath+'/$USER"'); |
|
closefile(F); |
|
Form1.LabelStatus.Caption:='transferring job script...'; |
|
Form1.LabelStatus.Repaint; |
|
// copy the jupyterlab script to IOW |
|
command := 'scp '+ExtractFilePath(application.ExeName)+'/jupyterlab_remote.sh '+hostname+':'+remoteBasepath+'/'+username; |
|
MyRunProcess(command,true,true); |
|
// convert to unix line endings and set execute permissions |
|
command := 'ssh '+hostname+' sed -i ''s/\r//'' '+remoteBasepath+'/'+username+'/jupyterlab_remote.sh'; |
|
MyRunProcess(command,true,true); |
|
command := 'ssh '+hostname+' chmod u+x '+remoteBasepath+'/'+username+'/jupyterlab_remote.sh'; |
|
MyRunProcess(command,true,true); |
|
Form1.LabelStatus.Caption:='checking if port is free...'; |
|
Form1.LabelStatus.Repaint; |
|
// check if port is in use |
|
portBlocked:=false; |
|
command := 'ssh '+hostname+' fuser '+IntToStr(port)+'/tcp'; |
|
sl1:=MyRunProcess(command,true,true); |
|
if sl1.Count>=1 then portBlocked:=true; |
|
sl1.Free; |
|
if portBlocked then |
|
if MessageDlg('port in use','Port '+IntToStr(port)+' is already in use by another process. Kill that process?',mtConfirmation,[mbYes,mbAbort],0,mbAbort)=mrYes then |
|
begin |
|
command := 'ssh '+hostname+' fuser -k -n tcp '+IntToStr(port); |
|
MyRunProcess(command,true,true); |
|
sleep(1000); |
|
end |
|
else |
|
exit; |
|
// delete output files of an old jupyterlab job if exists |
|
Form1.LabelStatus.Caption:='cleaning up old files...'; |
|
Form1.LabelStatus.Repaint; |
|
command := 'ssh -q '+hostname+' "if [ -f '+remoteBasepath+'/'+username+ |
|
'/.jupyter_out.txt ] ; then rm '+remoteBasepath+'/'+username+'/.jupyter_out.txt ; fi"'; |
|
{$IFDEF LINUX} |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/command.sh'); |
|
Rewrite(F); |
|
writeln(F,command); |
|
closefile(F); |
|
MyRunProcess('/bin/bash -e '+ExtractFilePath(Application.ExeName)+'/command.sh',true,true); |
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
MyRunProcess(command,true,true); |
|
{$ENDIF} |
|
command := 'ssh -q '+hostname+' "if [ -f '+remoteBasepath+'/'+username+ |
|
'/.jupyterlab_hostname.txt ] ; then rm '+remoteBasepath+'/'+username+'/.jupyterlab_hostname.txt ; fi"'; |
|
{$IFDEF LINUX} |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/command.sh'); |
|
Rewrite(F); |
|
writeln(F,command); |
|
closefile(F); |
|
MyRunProcess('/bin/bash -e '+ExtractFilePath(Application.ExeName)+'/command.sh',true,true); |
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
MyRunProcess(command,true,true); |
|
{$ENDIF} |
|
// prepare the command to submit the job and run it |
|
Form1.LabelStatus.Caption:='submitting job...'; |
|
Form1.LabelStatus.Repaint; |
|
command := 'ssh '+hostname+' sbatch '+remoteBasepath+'/'+username+'/jupyterlab_remote.sh'; |
|
MyRunProcess(command,true,true); |
|
// wait until the output file exists |
|
Form1.LabelStatus.Caption:='waiting for job to start...'; |
|
Form1.LabelStatus.Repaint; |
|
found:=false; |
|
while not found do |
|
begin |
|
command:='ssh '+hostname+' ls '+remoteBasepath+'/'+username+'/.jupyter_out.txt'; |
|
sl1:=MyRunProcess(command,true,true); |
|
if sl1.Count>0 then found:=true; |
|
sl1.Free; |
|
sleep(1000); |
|
end; |
|
// then, get the node name |
|
Form1.LabelStatus.Caption:='job is running, checking on which node...'; |
|
Form1.LabelStatus.Repaint; |
|
command:='ssh '+hostname+' cat '+remoteBasepath+'/'+username+'/.jupyterlab_hostname.txt'; |
|
sl1:=MyRunProcess(command,true,true); |
|
while sl1.count<1 do |
|
begin |
|
sleep(500); |
|
sl1.Free; |
|
sl1:=MyRunProcess(command,true,true); |
|
end; |
|
nodeName:=sl1[0]; |
|
// open SSH tunnel for the ports |
|
Form1.LabelStatus.Caption:='opening ssh tunnel...'; |
|
Form1.LabelStatus.Repaint; |
|
command := 'ssh -L '+IntToStr(port)+':localhost:'+IntToStr(port)+' '+hostname+ |
|
' ssh -L '+IntToStr(port)+':localhost:'+IntToStr(port)+ |
|
' -N '+nodeName+' & 2>/dev/null'; |
|
{$IFDEF LINUX} |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/command.sh'); |
|
Rewrite(F); |
|
writeln(F,command); |
|
closefile(F); |
|
MyRunProcess('/bin/bash -e '+ExtractFilePath(Application.ExeName)+'/command.sh',true,false,process); |
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
MyRunProcess(command,true,false,process); |
|
{$ENDIF} |
|
// grep until we find the token |
|
Form1.LabelStatus.Caption:='waiting for token...'; |
|
Form1.LabelStatus.Repaint; |
|
command := 'ssh '+hostname+' grep "token" '+remoteBasepath+'/'+username+'/.jupyter_out.txt 2>/dev/null'; |
|
found:=false; |
|
while not found do |
|
begin |
|
sl1 := MyRunProcess(command,true,true); |
|
for i:=0 to sl1.Count-1 do |
|
if pos('?token=',sl1[i])>0 then |
|
begin |
|
s:=copy(sl1[i],pos('?token=',sl1[i])+7,48); |
|
if not found then |
|
begin |
|
Form1.LabelStatus.Caption:='opening browser...'; |
|
Form1.LabelStatus.Repaint; |
|
OpenUrl('http://127.0.0.1:'+IntToStr(port)+'?token='+s); |
|
end; |
|
found:=true; |
|
end; |
|
sleep(1000); |
|
end; |
|
end |
|
else |
|
if hostname='haumea1' then ShowErrorDisconnectedHaumea; |
|
sl.Free; |
|
Form1.LabelStatus.Caption:=''; |
|
end; |
|
|
|
procedure StartConsoleIOW(hostname: String); |
|
var |
|
sl: TStringList; |
|
F: TextFile; |
|
begin |
|
// get IOW username and userid |
|
sl:=MyRunProcess('ssh rdpserv whoami ; id -u',true,true); |
|
if sl.count=2 then |
|
begin |
|
// run command in console |
|
{$IFDEF Linux} |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/command.sh'); |
|
Rewrite(F); |
|
writeln(F,'ssh -t -X rdpserv ssh -X '+hostname); |
|
closefile(F); |
|
MyRunProcess(FavouriteTerminalStart+' '+ExtractFilePath(application.ExeName)+'/command.sh'+FavouriteTerminalEnd,false,false); |
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
ShellExecute(0,nil, PChar('cmd'),PChar('/C ssh -t rdpserv ssh '+hostname),nil,1); |
|
{$ENDIF} |
|
end |
|
else |
|
ShowErrorDisconnectedIOW; |
|
sl.Free; |
|
end; |
|
|
|
procedure StartConsoleRemote(hostname: String='haumea1'); |
|
var |
|
sl: TStringList; |
|
F: TextFile; |
|
begin |
|
// first we need to start the ssh-agent to enable passwordless login |
|
{$IFDEF WINDOWS} |
|
MyRunProcess('powershell -command "& {&''Start-Service'' ssh-agent}"',true,true); |
|
{$ENDIF} |
|
{$IFDEF Linux} |
|
// we need to unlock a key to allow passwordless login |
|
if (hostname='haumea1') and (haumea_unlocked=false) then unlock_haumea; |
|
if (hostname='blogin') and (hlrn_unlocked=false) then unlock_hlrn; |
|
if (hostname='glogin') and (hlrn_unlocked=false) then unlock_hlrn; |
|
{$ENDIF} |
|
// get haumea username and userid |
|
sl:=MyRunProcess('ssh '+hostname+' whoami ; id -u',true,true); |
|
if sl.count=2 then |
|
begin |
|
// run command in console |
|
{$IFDEF Linux} |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/command.sh'); |
|
Rewrite(F); |
|
writeln(F,'ssh -X '+hostname); |
|
closefile(F); |
|
MyRunProcess(FavouriteTerminalStart+' '+ExtractFilePath(application.ExeName)+'/command.sh'+FavouriteTerminalEnd,false,false); |
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
ShellExecute(0,nil, PChar('cmd'),PChar('/C ssh '+hostname),nil,1); |
|
{$ENDIF} |
|
end |
|
else |
|
if hostname='haumea1' then ShowErrorDisconnectedHaumea; |
|
sl.Free; |
|
end; |
|
|
|
procedure StartXpraIOW(hostname: String); |
|
var |
|
sl, sl1: TStringList; |
|
username, command, s: String; |
|
userid, port, ReadSize: Integer; |
|
process: TProcess; |
|
Buffer: array[0..100000] of char; |
|
found: boolean; |
|
portBlocked: Boolean; |
|
begin |
|
found:=false; // we will seek the output to find out when the server is running |
|
// get IOW username and userid |
|
Form1.LabelStatus.Caption:='connecting to IOW...'; |
|
Form1.LabelStatus.Repaint; |
|
sl:=MyRunProcess('ssh rdpserv whoami ; id -u',true,true); |
|
if sl.count=2 then |
|
begin |
|
username:=trim(sl[0]); |
|
userid:=StrToInt(sl[1]); |
|
port:=PortFromUserid(userid,'IOW','XPRA'); |
|
Form1.LabelStatus.Caption:='sending xpra script...'; |
|
Form1.LabelStatus.Repaint; |
|
// copy the xpra script to IOW |
|
command := 'scp '+ExtractFilePath(application.ExeName)+'/xpra_iow.sh rdpserv:/home/nis/'+username; |
|
MyRunProcess(command,true,true); |
|
// set execute permissions |
|
command := 'ssh rdpserv chmod u+x /home/nis/'+username+'/xpra_iow.sh'; |
|
MyRunProcess(command,true,true); |
|
// check if port is in use |
|
Form1.LabelStatus.Caption:='checking if port is free...'; |
|
Form1.LabelStatus.Repaint; |
|
portBlocked:=false; |
|
command := 'ssh rdpserv fuser '+IntToStr(port)+'/tcp'; |
|
sl1:=MyRunProcess(command,true,true); |
|
if sl1.Count>=1 then portBlocked:=true; |
|
sl1.Free; |
|
command := 'ssh rdpserv ssh '+hostname+' fuser '+IntToStr(port)+'/tcp'; |
|
sl1:=MyRunProcess(command,true,true); |
|
if sl1.Count>=1 then portBlocked:=true; |
|
sl1.Free; |
|
if portBlocked then |
|
if MessageDlg('port in use','Port '+IntToStr(port)+' is already in use by another process. Kill that process?',mtConfirmation,[mbYes,mbAbort],0,mbAbort)=mrYes then |
|
begin |
|
command := 'ssh rdpserv fuser -k -n tcp '+IntToStr(port); |
|
MyRunProcess(command,true,true); |
|
command := 'ssh rdpserv ssh '+hostname+' fuser -k -n tcp '+IntToStr(port); |
|
MyRunProcess(command,true,true); |
|
sleep(1000); |
|
end |
|
else |
|
exit; |
|
// prepare the xpra command and run it |
|
Form1.LabelStatus.Caption:='starting xpra...'; |
|
Form1.LabelStatus.Repaint; |
|
command := 'ssh -t -X rdpserv -L '+IntToStr(port)+':localhost:'+IntToStr(port)+ |
|
' ssh -t -X '+hostname+' -L '+IntToStr(port)+':localhost:'+IntToStr(port)+ |
|
' /bin/bash -c /home/nis/'+username+'/xpra_iow.sh 2>&1'; |
|
MyRunProcess(command,true,false,process); |
|
// seek the output for the term "running" |
|
Form1.LabelStatus.Caption:='waiting until xpra has started...'; |
|
Form1.LabelStatus.Repaint; |
|
while (process.Running or (process.Output.NumBytesAvailable > 0)) and (not found) do |
|
begin |
|
if process.Output.NumBytesAvailable > 0 then |
|
begin |
|
// make sure that we don't read more data than we have allocated |
|
// in the buffer |
|
ReadSize := process.Output.NumBytesAvailable; |
|
if ReadSize > SizeOf(Buffer) then |
|
ReadSize := SizeOf(Buffer); |
|
// now read the output into the buffer |
|
process.Output.Read(Buffer[0], ReadSize); |
|
// and if it contains a token, then open a URL in the browser |
|
s:=Buffer; |
|
if pos('running',s)>0 then |
|
begin |
|
sleep(3000); //wait until it really starts |
|
Form1.LabelStatus.Caption:='opening browser...'; |
|
Form1.LabelStatus.Repaint; |
|
OpenUrl('http://127.0.0.1:'+IntToStr(port)); |
|
found:=true; |
|
end; |
|
end; |
|
end; |
|
end |
|
else |
|
ShowErrorDisconnectedIOW; |
|
sl.Free; |
|
Form1.LabelStatus.Caption:=''; |
|
end; |
|
|
|
{ TForm1 } |
|
|
|
procedure TForm1.Button10Click(Sender: TObject); |
|
{$IFDEF Linux} |
|
var |
|
found: Boolean; |
|
{$ENDIF} |
|
begin |
|
{$IFDEF Linux} |
|
found:=false; |
|
if DirectoryExists('/public') then |
|
if funIstVerzeichnisLeer('/public')=false then |
|
begin |
|
MyRunProcess('gdk-open /public',false,false); |
|
end; |
|
if not found then |
|
ShowMessage('"/public" directory is not mounted on your machine. Please add it to the /etc/fstab or open a console on one of the phy servers and run "cd /public"') |
|
|
|
{$ENDIF} |
|
{$IFDEF WINDOWS} |
|
MyRunProcess('explorer \\netapp1.io-warnemuende.de\public',false,false); |
|
{$ENDIF} |
|
end; |
|
|
|
procedure TForm1.Button11Click(Sender: TObject); |
|
begin |
|
OpenUrl('https://git.io-warnemuende.de/'); |
|
end; |
|
|
|
procedure TForm1.Button12Click(Sender: TObject); |
|
begin |
|
OpenNmonUrl('PHY-2'); |
|
end; |
|
|
|
procedure TForm1.Button13Click(Sender: TObject); |
|
begin |
|
StartJupyterlabIOW('phy-2'); |
|
end; |
|
|
|
procedure TForm1.Button14Click(Sender: TObject); |
|
begin |
|
StartConsoleIOW('phy-2'); |
|
end; |
|
|
|
procedure TForm1.Button15Click(Sender: TObject); |
|
begin |
|
StartXpraIOW('phy-2'); |
|
end; |
|
|
|
procedure TForm1.Button16Click(Sender: TObject); |
|
begin |
|
OpenNmonUrl('PHY-3'); |
|
end; |
|
|
|
procedure TForm1.Button17Click(Sender: TObject); |
|
begin |
|
StartJupyterlabIOW('phy-3'); |
|
end; |
|
|
|
procedure TForm1.Button18Click(Sender: TObject); |
|
begin |
|
StartConsoleIOW('phy-3'); |
|
end; |
|
|
|
procedure TForm1.Button19Click(Sender: TObject); |
|
begin |
|
StartXpraIOW('phy-3'); |
|
end; |
|
|
|
procedure TForm1.Button1Click(Sender: TObject); |
|
begin |
|
MyRunProcess(FavouriteTerminalStart+' '+ExtractFilePath(application.ExeName)+'/command.sh'+FavouriteTerminalEnd,false,false); |
|
OpenUrl('http://phywiki.io-warnemuende.de/pub/Server/IntroductionNewColleagues/new_colleagues_introduction_it.pdf'); |
|
end; |
|
|
|
procedure TForm1.Button20Click(Sender: TObject); |
|
begin |
|
OpenNmonUrl('PHY-4'); |
|
end; |
|
|
|
procedure TForm1.Button21Click(Sender: TObject); |
|
begin |
|
StartJupyterlabIOW('phy-4'); |
|
end; |
|
|
|
procedure TForm1.Button22Click(Sender: TObject); |
|
begin |
|
StartConsoleIOW('phy-4'); |
|
end; |
|
|
|
procedure TForm1.Button23Click(Sender: TObject); |
|
begin |
|
StartXpraIOW('phy-4'); |
|
end; |
|
|
|
procedure TForm1.Button24Click(Sender: TObject); |
|
begin |
|
OpenNmonUrl('PHY-10'); |
|
end; |
|
|
|
procedure TForm1.Button25Click(Sender: TObject); |
|
begin |
|
StartJupyterlabIOW('phy-10'); |
|
end; |
|
|
|
procedure TForm1.Button26Click(Sender: TObject); |
|
begin |
|
StartConsoleIOW('phy-10'); |
|
end; |
|
|
|
procedure TForm1.Button27Click(Sender: TObject); |
|
begin |
|
StartXpraIOW('phy-10'); |
|
end; |
|
|
|
procedure TForm1.Button28Click(Sender: TObject); |
|
begin |
|
OpenNmonUrl('PHY-11'); |
|
end; |
|
|
|
procedure TForm1.Button29Click(Sender: TObject); |
|
begin |
|
StartJupyterlabIOW('phy-11'); |
|
end; |
|
|
|
procedure TForm1.Button2Click(Sender: TObject); |
|
begin |
|
OpenNmonUrl('phy-1'); |
|
end; |
|
|
|
procedure TForm1.Button30Click(Sender: TObject); |
|
begin |
|
StartConsoleIOW('phy-11'); |
|
end; |
|
|
|
procedure TForm1.Button31Click(Sender: TObject); |
|
begin |
|
StartXpraIOW('phy-11'); |
|
end; |
|
|
|
procedure TForm1.Button32Click(Sender: TObject); |
|
begin |
|
OpenUrl('http://phywiki.io-warnemuende.de/do/view/Server/UniRostockClusterDocumentationList'); |
|
end; |
|
|
|
procedure TForm1.Button33Click(Sender: TObject); |
|
begin |
|
StartJupyterlabRemote('haumea1'); |
|
end; |
|
|
|
procedure TForm1.Button34Click(Sender: TObject); |
|
begin |
|
StartConsoleRemote('haumea1'); |
|
end; |
|
|
|
procedure TForm1.Button35Click(Sender: TObject); |
|
begin |
|
OpenUrl('http://phywiki.io-warnemuende.de/do/view/Server/HLRNApplicationProcedure'); |
|
end; |
|
|
|
procedure TForm1.Button36Click(Sender: TObject); |
|
begin |
|
StartJupyterlabRemote('blogin'); |
|
end; |
|
|
|
procedure TForm1.Button37Click(Sender: TObject); |
|
begin |
|
StartConsoleRemote('blogin'); |
|
end; |
|
|
|
procedure TForm1.Button38Click(Sender: TObject); |
|
begin |
|
StartJupyterlabRemote('glogin'); |
|
end; |
|
|
|
procedure TForm1.Button39Click(Sender: TObject); |
|
begin |
|
StartConsoleRemote('glogin'); |
|
end; |
|
|
|
procedure TForm1.Button3Click(Sender: TObject); |
|
begin |
|
StartJupyterlabIOW('phy-1'); |
|
end; |
|
|
|
procedure TForm1.Button40Click(Sender: TObject); |
|
begin |
|
timer1timer(self); |
|
end; |
|
|
|
procedure TForm1.Button41Click(Sender: TObject); |
|
begin |
|
Form3.ShowModal; |
|
end; |
|
|
|
procedure TForm1.Button4Click(Sender: TObject); |
|
begin |
|
StartConsoleIOW('phy-1'); |
|
end; |
|
|
|
procedure TForm1.Button5Click(Sender: TObject); |
|
begin |
|
StartXpraIOW('phy-1'); |
|
end; |
|
|
|
procedure TForm1.Button6Click(Sender: TObject); |
|
begin |
|
OpenUrl('http://phywiki.io-warnemuende.de/'); |
|
end; |
|
|
|
procedure TForm1.Button7Click(Sender: TObject); |
|
begin |
|
OpenUrl('https://email.io-warnemuende.de/'); |
|
end; |
|
|
|
procedure TForm1.Button8Click(Sender: TObject); |
|
begin |
|
OpenUrl('https://chat.io-warnemuende.de/'); |
|
end; |
|
|
|
procedure TForm1.Button9Click(Sender: TObject); |
|
begin |
|
OpenURL('https://owncloud.io-warnemuende.de') |
|
end; |
|
|
|
procedure TForm1.FormCreate(Sender: TObject); |
|
var |
|
F: TextFile; |
|
begin |
|
// we have not yet unlocked haumea and hlrn keys |
|
haumea_unlocked:=false; |
|
hlrn_unlocked:=false; |
|
// users can overwrite the terminal they want to use |
|
favouriteTerminalStart:='xterm -e '; |
|
favouriteTerminalEnd:=''; |
|
if FileExists(ExtractFilePath(Application.ExeName)+'/favourite_terminal.txt') then |
|
begin |
|
AssignFile(F,ExtractFilePath(Application.ExeName)+'/favourite_terminal.txt'); |
|
Reset(F); |
|
if not EOF(F) then |
|
readln(F,favouriteTerminalStart); |
|
readln(F,favouriteTerminalEnd); |
|
closefile(F); |
|
end; |
|
end; |
|
|
|
procedure TForm1.FormShow(Sender: TObject); |
|
var |
|
F: TextFile; |
|
s: String; |
|
seeking: Boolean; |
|
begin |
|
Timer1timer(self); |
|
// now try to read user names from ~/.ssh/config |
|
Form3.Edit1.Text:=''; Form3.Edit2.Text:=''; // IOW username and password |
|
Form3.Edit3.Text:=''; Form3.Edit4.Text:=''; // Haumea username and password |
|
Form3.Edit5.Text:=''; Form3.Edit6.Text:=''; // HLRN username and password |
|
if FileExists(GetUserDir+'/.ssh/config') then |
|
begin |
|
assignFile(F,GetUserDir+'/.ssh/config'); |
|
reset(F); |
|
seeking:=false; |
|
while not EOF(F) do |
|
begin |
|
readln(F,s); |
|
if copy(lowercase(trim(s)),1,12)='host rdpserv' then |
|
seeking:=true |
|
else |
|
if seeking then |
|
begin |
|
if copy(lowercase(trim(s)),1,5)='user ' then |
|
begin |
|
Form3.Edit1.text:=trim(copy(trim(s),5,length(s))); |
|
seeking:=false; |
|
end; |
|
if copy(lowercase(trim(s)),1,5)='host ' then seeking:=false; |
|
end; |
|
end; |
|
closefile(F); |
|
|
|
assignFile(F,GetUserDir+'/.ssh/config'); |
|
reset(F); |
|
seeking:=false; |
|
while not EOF(F) do |
|
begin |
|
readln(F,s); |
|
if copy(lowercase(trim(s)),1,11)='host haumea' then |
|
seeking:=true |
|
else |
|
if seeking then |
|
begin |
|
if copy(lowercase(trim(s)),1,5)='user ' then |
|
begin |
|
Form3.Edit3.text:=trim(copy(trim(s),5,length(s))); |
|
seeking:=false; |
|
end; |
|
if copy(lowercase(trim(s)),1,5)='host ' then seeking:=false; |
|
end; |
|
end; |
|
closefile(F); |
|
|
|
assignFile(F,GetUserDir+'/.ssh/config'); |
|
reset(F); |
|
seeking:=false; |
|
while not EOF(F) do |
|
begin |
|
readln(F,s); |
|
if copy(lowercase(trim(s)),1,11)='host blogin' then |
|
seeking:=true |
|
else |
|
if seeking then |
|
begin |
|
if copy(lowercase(trim(s)),1,5)='user ' then |
|
begin |
|
Form3.Edit5.text:=trim(copy(trim(s),5,length(s))); |
|
seeking:=false; |
|
end; |
|
if copy(lowercase(trim(s)),1,5)='host ' then seeking:=false; |
|
end; |
|
end; |
|
closefile(F); |
|
end; |
|
end; |
|
|
|
procedure TForm1.Label6Click(Sender: TObject); |
|
begin |
|
|
|
end; |
|
|
|
procedure TForm1.Memo1Change(Sender: TObject); |
|
begin |
|
|
|
end; |
|
|
|
procedure TForm1.Timer1Timer(Sender: TObject); |
|
var |
|
AStringList: TStringList; |
|
begin |
|
AStringList:=MyRunProcess('ssh rdpserv /sw/sys/scripts/combine_machine_usage',true,true); |
|
if AStringList.Count>0 then |
|
begin |
|
// fill the information in into the GUI |
|
ShowUsageInfo(AStringList,LabelCPU1, LabelMEM1, Memo1); |
|
ShowUsageInfo(AStringList,LabelCPU2, LabelMEM2, Memo2); |
|
ShowUsageInfo(AStringList,LabelCPU3, LabelMEM3, Memo3); |
|
ShowUsageInfo(AStringList,LabelCPU4, LabelMEM4, Memo4); |
|
ShowUsageInfo(AStringList,LabelCPU5, LabelMEM5, Memo5); |
|
ShowUsageInfo(AStringList,LabelCPU6, LabelMEM6, Memo6); |
|
end |
|
else |
|
begin |
|
ShowErrorDisconnectedIOW; |
|
Halt; |
|
end; |
|
AStringList.Free; |
|
end; |
|
|
|
end. |
|
|
|
|