From cf4e5552d5d7b2f2a1e671390563e19a96394b43 Mon Sep 17 00:00:00 2001 From: Chris Hines <chris.hines@monash.edu> Date: Thu, 21 Jan 2021 16:43:33 +1100 Subject: [PATCH] if stat fails, display the error instead of immediately refreshing https://gitlab.erc.monash.edu.au/hpc-team/strudelv2_spa/-/issues/156 --- .vscode/launch.json | 15 +++++++++++++++ src/app/computesite.ts | 14 +------------- src/app/computesites.service.ts | 20 +++++++++++--------- src/app/identity.ts | 4 ++++ src/app/joblist/joblist.component.ts | 2 +- src/app/jobs.service.ts | 8 +++++--- src/app/launcher/launcher.component.html | 2 +- src/app/launcher/launcher.component.ts | 6 +++--- src/app/tes.service.ts | 1 - src/assets/config/m3apps.test.json | 2 +- 10 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7a9dfa0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/src/app/computesite.ts b/src/app/computesite.ts index aa2715f..1ad0c3d 100644 --- a/src/app/computesite.ts +++ b/src/app/computesite.ts @@ -12,7 +12,7 @@ export class Computesite { cafingerprint: string; // Certificates contain a CA fingerprint. We use this // to figure out which compute site a certificate is valid // for - appCatalog: BehaviorSubject<Strudelapp[]>; + appCatalogUri: string; appCatalogCmd: string; internalfirewall: boolean; // Does a firewall exist within the site necessitating an extra level of ssh tunnel @@ -23,18 +23,6 @@ export class Computesite { contact: string; } -export class Strudelapp { - url: string; // A url used to retrieve extra config options. May be null - name: string; // Human readable name - startscript: string; // batch script ... should NOT include resource directives - // resource directives like #SBATCH belong in the batchinterface - paramscmd: string; // command to return extra data such as passwords and tokens - // values returned here can be used in the client strings - client: {cmd: string[], redir: string}; - localbind: boolean; // does the application bind to a port on the localhost - // interface or on all interfaces. This behaviour determins - /// how we create tunnels -} export class Health { stat: string; diff --git a/src/app/computesites.service.ts b/src/app/computesites.service.ts index 42b0499..8ef1ab9 100644 --- a/src/app/computesites.service.ts +++ b/src/app/computesites.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core'; -import { Computesite, Strudelapp } from './computesite'; +import { Computesite } from './computesite'; +import { Strudelapp } from './strudelapp'; import {BehaviorSubject, of, combineLatest} from 'rxjs'; import { HttpClientModule, HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; @@ -46,7 +47,7 @@ export class ComputesitesService { let options = { headers: headers, withCredentials: false}; if (s.appCatalogUri !== null) { this.http.get<Strudelapp[]>(s.appCatalogUri,options) - .pipe(catchError(this.handleError('getStrudelApps'))) + .pipe(catchError(this.handleError(' s'))) .subscribe(resp => this.updateStrudelApps(s,resp)); } } @@ -64,7 +65,7 @@ export class ComputesitesService { if (ids != undefined && ids != null) { for (let id of ids) { this.getStrudelAppsIdentity(id) - .subscribe(resp => this.updateStrudelApps(id.site,resp)); + .subscribe(resp => this.updateStrudelApps(id,resp)); } } } @@ -81,9 +82,12 @@ export class ComputesitesService { } private getStrudelAppsCmd(identity: Identity): Observable<Strudelapp[]> { + console.log('running getStrudleAppsCmd',identity) if (identity.site.appCatalogCmd != null) { return (this.tesService.runCommand(identity,identity.site.appCatalogCmd) as Observable<Strudelapp[]>) - .pipe(catchError(this.handleError('getStrudelApps', <Strudelapp[]>[]))) + .pipe( + tap((v) => console.log('getapps',identity,' returned',v)), + catchError(this.handleError('getStrudelApps', <Strudelapp[]>[]))) } return of([] as Strudelapp[]) } @@ -107,18 +111,18 @@ export class ComputesitesService { } - updateStrudelApps(site: Computesite, apps) { + updateStrudelApps(id: Identity, apps) { var sapps: Strudelapp[]; var localapps: Strudelapp[]; sapps = <Strudelapp[]>apps; - localapps = JSON.parse(localStorage.getItem(site.name+'-apps')) + localapps = JSON.parse(localStorage.getItem(id.site.name+'-apps')) if (localapps !== null) { for (let a of localapps) { sapps.push(a); } } - site.appCatalog.next(sapps); + id.appCatalog.next(sapps); } private handleError<T> (operation = 'operation', result?: T) { @@ -160,13 +164,11 @@ export class ComputesitesService { } if (localcomputesites !== null ) { for (let cs of localcomputesites) { - cs.appCatalog = new BehaviorSubject<Strudelapp[]>([]); computesites.push(cs); } } for (let cs of resp) { let computesite = <Computesite>cs; - computesite.appCatalog = new BehaviorSubject<Strudelapp[]>([]) computesites.push(computesite); } this.computesites.next(computesites); diff --git a/src/app/identity.ts b/src/app/identity.ts index ac86100..a332f82 100644 --- a/src/app/identity.ts +++ b/src/app/identity.ts @@ -1,6 +1,7 @@ import {Computesite, Health} from './computesite'; import {Job} from './job'; import {BehaviorSubject} from 'rxjs'; +import {Strudelapp} from './strudelapp'; // Identities are defined by a username on a computer, but rather than just // DNS entry, there is extra info in the Computesite export class Identity { @@ -13,6 +14,7 @@ export class Identity { joblist: BehaviorSubject<Job[]>; quotas: any[]; expiry: number; + appCatalog: BehaviorSubject<Strudelapp[]>; constructor( username: string, site: Computesite, expiry: number) { this.username = username; this.site = site; @@ -20,8 +22,10 @@ export class Identity { this.systemalerts = new BehaviorSubject<Health[]>(null); this.accountalerts = new BehaviorSubject<Health[]>(null); this.joblist = new BehaviorSubject<Job[]>([]); + this.appCatalog = new BehaviorSubject<Strudelapp[]>([]); this.quotas = []; this.expiry = expiry; + } copy_skip_catalog(): Identity { diff --git a/src/app/joblist/joblist.component.ts b/src/app/joblist/joblist.component.ts index e336904..7aa175c 100644 --- a/src/app/joblist/joblist.component.ts +++ b/src/app/joblist/joblist.component.ts @@ -92,7 +92,7 @@ export class JoblistComponent implements OnInit { // any jobs in the joblist that we don't know which application they arem try to figure it out for (j of joblist) { if (j.app === undefined || j.app == null) { - j.app = Strudelapp.getApp(j.appname,identity.site.appCatalog.value); + j.app = Strudelapp.getApp(j.appname,identity.appCatalog.value); } if (j.identity == undefined) { j.identity = identity; diff --git a/src/app/jobs.service.ts b/src/app/jobs.service.ts index b244cac..a20b802 100644 --- a/src/app/jobs.service.ts +++ b/src/app/jobs.service.ts @@ -45,13 +45,15 @@ export class JobsService { if (error.hasOwnProperty("error") && error.error.hasOwnProperty("message")) { if (error.error.message.indexOf("Permission denied") != -1) { this.notifications.notify("Your login appears to have expired. Please log in again"); - this.authService.updateAgentContents().subscribe((_) => {return}); + //this.authService.updateAgentContents().subscribe((_) => {return}); return; } + this.notifications.notify("Unable to retrieve a list of running jobs.\nDid your session expire?\nThe error messge was " + error.error.message); + return; } - this.notifications.notify("Unable to retrieve a list of running jobs.\nDid your session expire?") console.error(error); - this.authService.updateAgentContents().subscribe((_) => {return}); + this.notifications.notify("Unable to retrieve a list of running jobs.\nDid your session expire?"); + //this.authService.updateAgentContents().subscribe((_) => {return}); } } diff --git a/src/app/launcher/launcher.component.html b/src/app/launcher/launcher.component.html index d71b9a8..1211c94 100644 --- a/src/app/launcher/launcher.component.html +++ b/src/app/launcher/launcher.component.html @@ -37,7 +37,7 @@ </button> </mat-list-item> - <app-strudelapplist [applist]=id.site.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist> + <app-strudelapplist [applist]=id.appCatalog [identity]="id" (appChange)="selectApp($event)" style="width: 100%"></app-strudelapplist> </mat-list> </mat-expansion-panel> <!--<div style="width: 100%; border-bottom: 1px solid var(--panel-border-color);"></div>--> diff --git a/src/app/launcher/launcher.component.ts b/src/app/launcher/launcher.component.ts index f9770a8..f5d037f 100644 --- a/src/app/launcher/launcher.component.ts +++ b/src/app/launcher/launcher.component.ts @@ -233,8 +233,8 @@ export class LauncherComponent implements OnInit { if (apps === null) { apps = 'accountinfo'; } - if (id.site.appCatalog.value === undefined || id.site.appCatalog.value === null || (id.site.appCatalog.value).length == 0) { - id.site.appCatalog.pipe(filter((v) => v !== null && v.length > 0),take(1)).subscribe(() => this.updateIdApp(params,appidentities)); + if (id.appCatalog.value === undefined || id.appCatalog.value === null || (id.appCatalog.value).length == 0) { + id.appCatalog.pipe(filter((v) => v !== null && v.length > 0),take(1)).subscribe(() => this.updateIdApp(params,appidentities)); return } var app: Strudelapp = this.getApp(id,apps); @@ -247,7 +247,7 @@ export class LauncherComponent implements OnInit { if (id == 'accountinfo') { return null; } - return Strudelapp.getApp(v,id.site.appCatalog.value); + return Strudelapp.getApp(v,id.appCatalog.value); } getId(v: any, appidentities: Identity[]) { diff --git a/src/app/tes.service.ts b/src/app/tes.service.ts index 9d5857b..4aaaef5 100644 --- a/src/app/tes.service.ts +++ b/src/app/tes.service.ts @@ -54,7 +54,6 @@ public openWindow$: Subject<any>; private buildParams(app: Strudelapp, identity: Identity, batchinterface: BatchInterface, appinst?: any): string { let params = new URLSearchParams(); let id = identity.copy_skip_catalog(); - id.site.appCatalog = null; if (appinst!== null) { params.set('appinstance',JSON.stringify(appinst)); } diff --git a/src/assets/config/m3apps.test.json b/src/assets/config/m3apps.test.json index b12b6fa..bcac520 100644 --- a/src/assets/config/m3apps.test.json +++ b/src/assets/config/m3apps.test.json @@ -43,7 +43,7 @@ "instactions": [ { "name": "Connect", - "paramscmd": "/usr/local/sv2/jupyter/jupyter_params.sh {jobid}", + "paramscmd": "/usr/local/sv2/jupyter/jupyter_params.py {jobid}", "client": {"cmd": null, "redir": "?token={token}"}, "states": ["RUNNING"] }, -- GitLab