diff --git a/hooks/env b/hooks/env index 5bde6fa55c..265e6c184b 100644 --- a/hooks/env +++ b/hooks/env @@ -1,7 +1,7 @@ -[ -n "$SOURCE_BRANCH" ] || SOURCE_BRANCH=$(git symbolic-ref -q --short HEAD) +SOURCE_BRANCH=$(git symbolic-ref -q --short HEAD) -if [[ $SOURCE_BRANCH = "prod" ]] || [[ $SOURCE_BRANCH == *.*.* ]] ; then - ANGULAR_MODE="prod" +if $(git describe --exact-match --tags HEAD) "$ret" -eq 0 || [ $SOURCE_BRANCH = "master" ]; then + ANGULAR_MODE="prod" else - ANGULAR_MODE="stage" -fi + ANGULAR_MODE="stage" +fi \ No newline at end of file diff --git a/src/app/api-connector/applications.service.ts b/src/app/api-connector/applications.service.ts index 6a5eae5125..7328d3d159 100644 --- a/src/app/api-connector/applications.service.ts +++ b/src/app/api-connector/applications.service.ts @@ -39,6 +39,69 @@ export class ApplicationsService { }); } + + + requestRenewal(data) { + let parameter = data; + + + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + 'Content-Type': 'application/json' + }); + return this.http.post(this.settings.getApiBaseURL() + 'application/requestRenewal/',parameter, + { + headers: header, + withCredentials: true + }); + } + + approveRenewal(application_id: number) { + + + let urlSearchParams = new URLSearchParams(); + urlSearchParams.append('project_application_id', application_id.toString()); + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + return this.http.post(this.settings.getApiBaseURL() + 'application/approveRenewal/', urlSearchParams, + { + headers: header, + withCredentials: true + }); + } + + declineRenewal(application_id: number) { + + + let urlSearchParams = new URLSearchParams(); + urlSearchParams.append('project_application_id', application_id.toString()); + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + return this.http.post(this.settings.getApiBaseURL() + 'application/declineRenewal/', urlSearchParams, + { + headers: header, + withCredentials: true + }); + } + + + getAllApplicationsRenewalRequests() { + return this.http.get(this.settings.getApiBaseURL() + 'application/applicationRenewalRequests/', { + withCredentials: true, + params: {format: this.settings.getApiFormat()} + }); + } + + getApplicationsRenewalRequest(application_id: number) { + return this.http.get(this.settings.getApiBaseURL() + 'application/getApplicationRenewalRequestById/', { + withCredentials: true, + params: {format: this.settings.getApiFormat(),'project_application_id':application_id} + }); + } + + deleteApplication(application_id: number) { diff --git a/src/app/api-connector/group.service.ts b/src/app/api-connector/group.service.ts index f66c55ba93..aeecc3d6e1 100644 --- a/src/app/api-connector/group.service.ts +++ b/src/app/api-connector/group.service.ts @@ -343,7 +343,7 @@ export class GroupService { return this.http.post(this.settings.getApiBaseURL() + 'group/setPerunId/', urlSearchParams, { withCredentials: true, headers: header - }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) + }) } diff --git a/src/app/api-connector/image.service.ts b/src/app/api-connector/image.service.ts index acfb508177..91648abcab 100644 --- a/src/app/api-connector/image.service.ts +++ b/src/app/api-connector/image.service.ts @@ -1,5 +1,6 @@ import {Injectable} from '@angular/core'; import {Image} from '../virtualmachines/virtualmachinemodels/image'; +import {SnapshotModel} from "../virtualmachines/virtualmachinemodels/snapshot.model"; import {Http, Response, Headers, RequestOptions} from '@angular/http'; import {Observable} from 'rxjs/Rx'; import {URLSearchParams} from '@angular/http'; @@ -17,7 +18,6 @@ export class ImageService { let urlSearchParams = new URLSearchParams(); - return this.http.get(this.settings.getConnectorBaseUrl() + 'images/getImages/', { withCredentials: true, search: urlSearchParams @@ -39,38 +39,83 @@ export class ImageService { } - addImageTags(imageTag:string, description:string): Observable { + addImageTags(imageTag: string, description: string): Observable { let header = new Headers({ 'X-CSRFToken': this.settings.getCSRFToken(), }); let urlSearchParams = new URLSearchParams(); - urlSearchParams.append('imageTag',imageTag) - urlSearchParams.append('description',description) + urlSearchParams.append('imageTag', imageTag) + urlSearchParams.append('description', description) - return this.http.post(this.settings.getConnectorBaseUrl() + 'images/addImageTag/', urlSearchParams,{ + return this.http.post(this.settings.getConnectorBaseUrl() + 'images/addImageTag/', urlSearchParams, { withCredentials: true, - headers:header + headers: header }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) } - deleteImageTag(imageTag:string): Observable { + deleteImageTag(imageTag: string): Observable { let header = new Headers({ 'X-CSRFToken': this.settings.getCSRFToken(), }); let urlSearchParams = new URLSearchParams(); - urlSearchParams.append('imageTag',imageTag) + urlSearchParams.append('imageTag', imageTag) + + + return this.http.post(this.settings.getConnectorBaseUrl() + 'images/deleteImageTag/', urlSearchParams, { + withCredentials: true, + headers: header + }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) + + } + + + createSnapshot(snaptshot_instance: string, snapshot_name: string,): Observable { + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + let urlSearchParams = new URLSearchParams(); + urlSearchParams.append('snapshot_name', snapshot_name) + urlSearchParams.append('snapshot_instance', snaptshot_instance) - return this.http.post(this.settings.getConnectorBaseUrl() + 'images/deleteImageTag/', urlSearchParams,{ + return this.http.post(this.settings.getConnectorBaseUrl() + 'images/createSnapshot/', urlSearchParams, { withCredentials: true, - headers:header + headers: header }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) } + deleteSnapshot(snapshot_id: string): Observable { + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + let urlSearchParams = new URLSearchParams(); + + urlSearchParams.append('snapshot_id', snapshot_id) + + return this.http.post(this.settings.getConnectorBaseUrl() + 'images/deleteSnapshot/', urlSearchParams, { + withCredentials: true, + headers: header + }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) + + + } + + getSnapshotsByUser(): Observable { + let urlSearchParams = new URLSearchParams(); + + + return this.http.get(this.settings.getConnectorBaseUrl() + 'images/getSnapshots/', { + withCredentials: true, + search: urlSearchParams + }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) + + + } + } diff --git a/src/app/api-connector/user.service.ts b/src/app/api-connector/user.service.ts index 03d5212210..73b5364bc7 100644 --- a/src/app/api-connector/user.service.ts +++ b/src/app/api-connector/user.service.ts @@ -102,5 +102,21 @@ export class UserService { } + sendHelpMail(subject, message, reply): Observable { + let urlSearchParams = new URLSearchParams(); + urlSearchParams.append('subject', subject); + urlSearchParams.append('message', message); + urlSearchParams.append('reply', reply); + + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + return this.http.post(this.settings.getApiBaseURL() + 'user/sendHelpMail/', urlSearchParams, { + withCredentials: true, + headers: header, + }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) + + } + } diff --git a/src/app/api-connector/virtualmachine.service.ts b/src/app/api-connector/virtualmachine.service.ts index b398961de5..76b8476704 100644 --- a/src/app/api-connector/virtualmachine.service.ts +++ b/src/app/api-connector/virtualmachine.service.ts @@ -7,6 +7,7 @@ import {ApiSettings} from './api-settings.service' import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; import {VirtualMachine} from '../virtualmachines/virtualmachinemodels/virtualmachine'; +import {Volume} from "../virtualmachines/virtualmachinemodels/volume"; @Injectable() export class VirtualmachineService { @@ -17,7 +18,6 @@ export class VirtualmachineService { } - startVM(flavor: string, image: string, servername: string, project: string, projectid: string, diskspace?: string): Observable { let header = new Headers({ @@ -60,7 +60,18 @@ export class VirtualmachineService { }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) } - checkStatusInactiveVms(elixir_id: string): Observable { + getActiveVmsByProject(groupid: string): Observable { + let urlSearchParams = new URLSearchParams(); + urlSearchParams.append('groupid', groupid) + + return this.http.get(this.baseVmUrl + 'getActiveVmsByProject/', { + withCredentials: true, + search: urlSearchParams + }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')) + } + + + checkStatusInactiveVms(elixir_id: string): Observable { let urlSearchParams = new URLSearchParams(); urlSearchParams.append('elixir_id', elixir_id) @@ -80,10 +91,10 @@ export class VirtualmachineService { urlSearchParams.append('openstack_id', openstack_id) - return this.http.post(this.baseVmUrl + 'checkStatusVm/',urlSearchParams, { + return this.http.post(this.baseVmUrl + 'checkStatusVm/', urlSearchParams, { withCredentials: true, - headers:header + headers: header }); } @@ -129,4 +140,66 @@ export class VirtualmachineService { }); } + + getVolumesByUser(): Observable { + let urlSearchParams = new URLSearchParams(); + + return this.http.get(this.settings.getConnectorBaseUrl() + 'volumes/get_volumes/', { + withCredentials: true, + search: urlSearchParams + }).map((res: Response) => res.json()).catch((error: any) => Observable.throw(error.json().error || 'Server error')); + + + } + + attachVolumetoServer(volume_id: string, instance_id: string): Observable { + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + let urlSearchParams = new URLSearchParams(); + + urlSearchParams.append('volume_id', volume_id) + urlSearchParams.append('instance_id', instance_id) + + + return this.http.post(this.settings.getConnectorBaseUrl() + 'volumes/attachVolume/', urlSearchParams, { + withCredentials: true, + headers: header, + }); + } + + + deleteVolume(volume_id: string): Observable { + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + let urlSearchParams = new URLSearchParams(); + + urlSearchParams.append('volume_id', volume_id) + + + return this.http.post(this.settings.getConnectorBaseUrl() + 'volumes/deleteVolume/', urlSearchParams, { + withCredentials: true, + headers: header, + }); + } + + + deleteVolumeAttachment(volume_id: string, instance_id: string): Observable { + let header = new Headers({ + 'X-CSRFToken': this.settings.getCSRFToken(), + }); + let urlSearchParams = new URLSearchParams(); + + urlSearchParams.append('volume_id', volume_id) + urlSearchParams.append('instance_id', instance_id) + + + return this.http.post(this.settings.getConnectorBaseUrl() + 'volumes/deleteVolumeAttachment/', urlSearchParams, { + withCredentials: true, + headers: header, + }); + } + + } diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 3813059ebe..3604024163 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -30,6 +30,10 @@ export const routes: Routes = [ path: 'userinfo', loadChildren: './userinfo/userinfo.module#UserinfoModule' }, + { + path: 'help', + loadChildren: './help/help.module#HelpModule' + }, { path: 'project-management', loadChildren: './projectmanagement/projectmanagement.module#ProjectManagementModule' diff --git a/src/app/applications/application.model.ts b/src/app/applications/application.model.ts index 21830a8f28..acc8fb2f9a 100644 --- a/src/app/applications/application.model.ts +++ b/src/app/applications/application.model.ts @@ -1,3 +1,5 @@ +import {ApplicationExtension} from "./application_extension.model"; + export class Application { private _Id: number; private _Name: string; @@ -23,12 +25,20 @@ export class Application { private _OpenStackProject: boolean; private _ComputeCenterDetails:[string,string][]; private _DaysRunning: number; + private _ApplicationExtension:ApplicationExtension; constructor() { } + get ApplicationExtension():ApplicationExtension{ + return this._ApplicationExtension; + } + + set ApplicationExtension(value:ApplicationExtension){ + this._ApplicationExtension=value; + } get DaysRunning():number{ return this._DaysRunning; } diff --git a/src/app/applications/application_extension.model.ts b/src/app/applications/application_extension.model.ts new file mode 100644 index 0000000000..884d5a1f8f --- /dev/null +++ b/src/app/applications/application_extension.model.ts @@ -0,0 +1,125 @@ +export class ApplicationExtension { + private _Id: number; + private _Lifetime: number; + private _VMsRequested: number; + private _CoresPerVM: number; + private _RamPerVM: number; + private _VolumeLimit: number; + private _VolumeCounter: number; + private _ObjectStorage: number; + private _SpecialHardware: string[]; + private _Comment: string; + private _DateSubmitted: string; + private _OpenStackProject: boolean; + + constructor() { + } + + + get Lifetime(): number { + return this._Lifetime; + } + + set Lifetime(value: number) { + this._Lifetime = value; + } + + + + + get OpenStackProject(): boolean { + return this._OpenStackProject + } + + set OpenStackProject(value: boolean) { + this._OpenStackProject = value; + } + + + get Id(): number { + return this._Id; + } + + set Id(value: number) { + this._Id = value; + } + + + set Comment(value: string) { + this._Comment = value; + } + + get Comment(): string { + return this._Comment; + } + + + + get VMsRequested(): number { + return this._VMsRequested; + } + + set VMsRequested(value: number) { + this._VMsRequested = value; + } + + get CoresPerVM(): number { + return this._CoresPerVM; + } + + set CoresPerVM(value: number) { + this._CoresPerVM = value; + } + + get RamPerVM(): number { + return this._RamPerVM; + } + + set RamPerVM(value: number) { + this._RamPerVM = value; + } + + get VolumeLimit(): number { + return this._VolumeLimit; + } + + set VolumeLimit(value: number) { + this._VolumeLimit = value; + } + + + get VolumeCounter(): number { + return this._VolumeCounter; + } + + set VolumeCounter(value: number) { + this._VolumeCounter = value; + } + + get ObjectStorage(): number { + return this._ObjectStorage; + } + + set ObjectStorage(value: number) { + this._ObjectStorage = value; + } + + get SpecialHardware(): string[] { + return this._SpecialHardware; + } + + set SpecialHardware(value: string[]) { + this._SpecialHardware = value; + } + + + get DateSubmitted(): string { + return this._DateSubmitted; + } + + set DateSubmitted(value: string) { + this._DateSubmitted = value; + } + + +} diff --git a/src/app/applications/applications.component.html b/src/app/applications/applications.component.html index a0fe08982d..e36eb16ce0 100755 --- a/src/app/applications/applications.component.html +++ b/src/app/applications/applications.component.html @@ -13,247 +13,353 @@

Applications Overview

- - - - - - - - - - - - - +
+
Project NameShort NameLifetimeDate submittedStatusActions
+ - - - - - - + + + + + + - - - - - - -
{{ application.Name }}{{application.Shortname}}{{ application.Lifetime }}{{ application.DateSubmitted }}{{ application.Status }} - - - - - Project NameShort NameLifetimeDate submittedStatusActions
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Description{{ application.Description }}
Comment{{ application.Comment }}
VMs{{ application.VMsRequested }} VMs
Cores/VM{{ application.CoresPerVM }} Cores per VM
RAM{{ application.RamPerVM }} GB
Storage Limit{{ application.VolumeLimit }} GB
Volume Counter{{ application.VolumeCounter }} GB
ObjectStorage{{ application.ObjectStorage }} GB
Special Hardware{{ sh["special_hardware_name"] }} -
OpenStackProject{{application.OpenStackProject}}
-
-
-
- - - - -
-
-
- Applications for review -
-
- -
- -
- - - - - - - - - - - - - - - + + + + - - - + - - - - - - -
Project NameShort NameDate submittedUserInstituteCompute CenterActions
{{ application.Name }} {{application.Shortname}}{{ application.Lifetime }} {{ application.DateSubmitted }} - {{ application.User }} - {{application.Institute}}{{ application.Status }} - - - - + +
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Description{{ application.Description }}
Comment{{ application.Comment }}
Workgroup{{ application.Workgroup }}
Lifetime{{ application.Lifetime }} months
VMs{{ application.VMsRequested }} VMs
Cores/VM{{ application.CoresPerVM }} Cores per VM
RAM{{ application.RamPerVM }} GB
Storage Limit{{ application.VolumeLimit }} GB
Volume Counter{{ application.VolumeCounter }} GB
ObjectStorage{{ application.ObjectStorage }} GB
Special Hardware{{ sh["special_hardware_name"] }} -
OpenStackProject{{application.OpenStackProject}}
Last status changed{{ application.DateStatusChanged }}
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description{{ application.Description }} +
Comment{{ application.Comment }} + {{application.ApplicationExtension?.Comment}} +
VMs{{ application.VMsRequested }} VMs + {{application.ApplicationExtension?.VMsRequested}} VMs +
Cores/VM{{ application.CoresPerVM }} Cores per VM + {{application.ApplicationExtension?.CoresPerVM}} Cores per + VM +
RAM{{ application.RamPerVM }} GB + {{application.ApplicationExtension?.RamPerVM}} GB +
Storage Limit{{ application.VolumeLimit }} GB + {{application.ApplicationExtension?.VolumeLimit}} GB +
Volume Counter{{ application.VolumeCounter }} GB + {{application.ApplicationExtension?.VolumeCounter}} GB +
ObjectStorage{{ application.ObjectStorage }} GB + {{application.ApplicationExtension?.ObjectStorage}} GB +
Special Hardware{{ sh["special_hardware_name"] }} + + {{ sh }} +
OpenStackProject{{application.OpenStackProject}}
+
+ + +
+
+ +
+ + +
+
+
+ Applications for review +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Project NameShort NameDate submittedUserInstituteCompute CenterActions
{{ application.Name }}{{application.Shortname}}{{ application.DateSubmitted }} + {{ application.User }} + {{application.Institute}} + + {{application.ComputeCenter[0]}} + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description{{ application.Description }} +
Workgroup{{ application.Workgroup }} +
OpenStackProject{{application.OpenStackProject}} +
Comment{{ application.Comment }} + {{application.ApplicationExtension?.Comment}} +
Lifetime{{ application.Lifetime }} months + {{application.ApplicationExtension?.Lifetime + + application.Lifetime}} months +
VMs{{ application.VMsRequested }} VMs + {{application.ApplicationExtension?.VMsRequested}} VMs +
RAM{{ application.RamPerVM }} GB + {{application.ApplicationExtension?.RamPerVM}} GB +
Cores/VM{{ application.CoresPerVM }} Cores per VM + {{application.ApplicationExtension?.CoresPerVM}} Cores + per VM +
Storage Limit{{ application.VolumeLimit }} GB + {{application.ApplicationExtension?.VolumeLimit}} GB +
Volume Counter{{ application.VolumeCounter }} GB + {{application.ApplicationExtension?.VolumeCounter}} GB +
ObjectStorage{{ application.ObjectStorage }} GB + {{application.ApplicationExtension?.ObjectStorage}} GB +
Special Hardware{{ sh["special_hardware_name"] }} + + {{ sh }} +
Last status changed{{ application.DateStatusChanged }} +
+
+
+
+
@@ -271,134 +377,143 @@

Applications Overview

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+
Project NameShort NameDate submittedUserInstituteFacilityStatusActions
{{ application.Name }}{{application.Shortname}}{{ application.DateSubmitted }}{{ application.User }}{{ application.Institute }}{{application.ComputeCenter[0]}}{{ getStatusById(application.Status) }} - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Description{{ application.Description }}
Comment{{ application.Comment }}
Workgroup{{ application.Workgroup }}
Lifetime{{ application.Lifetime }}
VMs{{ application.VMsRequested }}
Cores/VM{{ application.CoresPerVM }}
RAM{{ application.RamPerVM }}
Storage Limit{{ application.VolumeLimit }}
Volume Counter{{ application.VolumeCounter }} GB
ObjectStorage{{ application.ObjectStorage }}
Special Hardware{{ sh["special_hardware_name"] }} -
Last status changed{{ application.DateStatusChanged }}
DaysRunning{{application.DaysRunning}}
Facility Details -
    -
  • Name: {{application.ComputeCenter[0]}}
  • -
  • - {{details[0]}}: {{details[1]}} - {{details[1]}} -
  • -
-
- -
-
+ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - -
Project NameShort NameDate submittedUserInstituteFacilityStatusActions
{{ application.Name }}{{application.Shortname}}{{ application.DateSubmitted }}{{ application.User }}{{ application.Institute }}{{application.ComputeCenter[0]}}{{ getStatusById(application.Status) }} + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Description{{ application.Description }}
Comment{{ application.Comment }}
Workgroup{{ application.Workgroup }}
Lifetime{{ application.Lifetime }}
VMs{{ application.VMsRequested }}
Cores/VM{{ application.CoresPerVM }}
RAM{{ application.RamPerVM }}
Storage Limit{{ application.VolumeLimit }}
Volume Counter{{ application.VolumeCounter }} GB
ObjectStorage{{ application.ObjectStorage }}
Special Hardware{{ sh["special_hardware_name"] }} +
Last status changed{{ application.DateStatusChanged }}
DaysRunning{{application.DaysRunning}}
Facility Details +
    +
  • Name: {{application.ComputeCenter[0]}}
  • +
  • + {{details[0]}}: {{details[1]}} + {{details[1]}} +
  • +
+
+
+ +
+
+ + + +
@@ -455,3 +570,221 @@ + + diff --git a/src/app/applications/applications.component.ts b/src/app/applications/applications.component.ts index 945d5729ac..ca28a973b2 100644 --- a/src/app/applications/applications.component.ts +++ b/src/app/applications/applications.component.ts @@ -11,13 +11,15 @@ import {SpecialHardware} from "./special_hardware.model"; import {ModalDirective} from 'ngx-bootstrap/modal/modal.component'; import {ResourcesManager} from "../perun-connector/resources_manager"; import {GroupService} from "../api-connector/group.service"; -import * as moment from 'moment'; +import * as moment from 'moment'; import {UserService} from "../api-connector/user.service"; +import {ApplicationExtension} from "./application_extension.model"; +import {NgForm} from '@angular/forms'; @Component({ templateUrl: 'applications.component.html', - providers: [UserService,GroupService, PerunSettings, ApplicationsService, ApplicationStatusService, SpecialHardwareService, ApiSettings] + providers: [UserService, GroupService, PerunSettings, ApplicationsService, ApplicationStatusService, SpecialHardwareService, ApiSettings] }) export class ApplicationsComponent { @@ -25,8 +27,10 @@ export class ApplicationsComponent { is_vo_admin = false; all_applications: Application[] = []; application_status: ApplicationStatus[] = []; + all_applications_renewal: ApplicationExtension[] = []; special_hardware: SpecialHardware[] = []; - computeCenters: [string,number][]; + computeCenters: [string, number][]; + selectedApplication: Application; public deleteId: number; //notification Modal variables @@ -35,8 +39,11 @@ export class ApplicationsComponent { public notificationModalMessage: string = "Please wait..."; public notificationModalType: string = "info"; public notificationModalIsClosable: boolean = false; - private APPROVED_STATUS=2; - + private APPROVED_STATUS = 2; + private EXTENSION_STATUS = 4; + private EXTENSTION_STATUS_STRING = 'extension requested'; + public FPGA = 1; + public GPU = 2; collapse_status: { [id: string]: boolean } = {}; @@ -44,14 +51,15 @@ export class ApplicationsComponent { private applicationstatusservice: ApplicationStatusService, private specialhardwareservice: SpecialHardwareService, private perunsettings: PerunSettings, - private userservice:UserService, + private userservice: UserService, private groupservice: GroupService) { this.getUserApplications(); this.getAllApplications(); this.getApplicationStatus(); this.getSpecialHardware(); - this.getComputeCenters(); + this.getComputeCenters() + } @@ -62,6 +70,39 @@ export class ApplicationsComponent { }) } + + setSelectedApplication(application: any) { + this.selectedApplication = application; + } + + onSubmit(f: NgForm) { + let values = {}; + values['project_application_renewal_special_hardware'] = this.special_hardware.filter(hardware => hardware.Checked).map(hardware => hardware.Id) + for (let v in f.controls) { + if (f.controls[v].value) { + values[v] = f.controls[v].value; + } + } + values['project_application_id'] = this.selectedApplication.Id; + this.requestExtension(values); + + } + + ngFormSetDefault(f: NgForm) { + f.reset({ + project_application_renewal_vms_requested : this.selectedApplication.VMsRequested, + project_application_renewal_cores_per_vm : this.selectedApplication.CoresPerVM, + project_application_renewal_ram_per_vm : this.selectedApplication.RamPerVM, + project_application_renewal_volume_limit: this.selectedApplication.VolumeLimit, + project_application_renewal_volume_counter: this.selectedApplication.VolumeCounter, + project_application_renewal_object_storage: this.selectedApplication.ObjectStorage, + project_application_renewal_comment: this.selectedApplication.Comment, + + + }) + + } + getUserApplications() { this.applicataionsservice .getUserApplications().toPromise() @@ -72,7 +113,7 @@ export class ApplicationsComponent { let a = new Application(); a.Id = aj["project_application_id"]; a.Name = aj["project_application_name"]; - a.Shortname=aj["project_application_shortname"]; + a.Shortname = aj["project_application_shortname"]; a.Lifetime = aj["project_application_lifetime"]; a.DateSubmitted = aj["project_application_date_submitted"]; a.Status = aj["project_application_status"]["application_status_name"]; @@ -85,9 +126,45 @@ export class ApplicationsComponent { a.ObjectStorage = aj["project_application_object_storage"]; a.SpecialHardware = aj["project_application_special_hardware"]; a.OpenStackProject = aj["project_application_openstack_project"]; - a.Comment= aj["project_application_comment"]; + a.Comment = aj["project_application_comment"]; + if (a.Status.toString() == this.EXTENSTION_STATUS_STRING) { + this.applicataionsservice.getApplicationsRenewalRequest(a.Id).subscribe(result => { + res = result.json(); + let r = new ApplicationExtension(); + + + r.Id = res['project_application']; + r.Lifetime = res['project_application_renewal_lifetime']; + r.VolumeLimit = res['project_application_renewal_volume_limit']; + r.VolumeCounter = res['project_application_renewal_volume_counter']; + r.VMsRequested = res['project_application_renewal_vms_requested']; + r.Comment = res['project_application_renewal_comment']; + r.CoresPerVM = res['project_application_renewal_cores_per_vm']; + r.ObjectStorage = res['project_application_renewal_object_storage']; + r.RamPerVM = res['project_application_renewal_ram_per_vm']; + r.Comment = res['project_application_renewal_comment']; + let special_hardware = []; + if (res['project_application_renewal_special_hardware'] != null) { + let special_hardware_string = res['project_application_renewal_special_hardware'].toString(); + + for (let c = 0; c < special_hardware_string.length; c++) { + let sh = special_hardware_string.charAt(c) == this.FPGA ? "FPGA" : "GPU"; + special_hardware.push(sh) + + } + + r.SpecialHardware = special_hardware; + } + a.ApplicationExtension = r; + this.user_applications.push(a) + }) + + } + else { + this.user_applications.push(a) + } + - this.user_applications.push(a) } }); } @@ -116,130 +193,208 @@ export class ApplicationsComponent { }); } + getAllApplicationsExtensions() { + + } + getAllApplications() { //todo check if user is VO Admin let user_id: number; let admin_vos: {}; - console.log(this.userservice) this.userservice .getLoggedUser().toPromise() - .then(userdata =>{ + .then(userdata => { //TODO catch errors user_id = userdata.json()["id"]; return this.userservice.getVosWhereUserIsAdmin(user_id).toPromise(); }).then(function (adminvos) { admin_vos = adminvos.json(); }).then(result => { - //check if user is a Vo admin so we can serv according buttons - for (let vkey in admin_vos) { - if (admin_vos[vkey]["id"] == this.perunsettings.getPerunVO().toString()) { - this.is_vo_admin = true; - this.applicataionsservice - .getAllApplications().toPromise() - .then(result => { - let res = result.json(); - for (let key in res) { - let aj = res[key]; - let a = new Application(); - a.Id = aj["project_application_id"]; - - a.Name = aj["project_application_name"]; - a.Shortname=aj["project_application_shortname"]; - a.Description = aj["project_application_description"]; - a.Lifetime = aj["project_application_lifetime"]; - - a.VMsRequested = aj["project_application_vms_requested"]; - a.RamPerVM = aj["project_application_ram_per_vm"]; - a.CoresPerVM = aj["project_application_cores_per_vm"]; - a.VolumeLimit = aj["project_application_volume_limit"]; - a.VolumeCounter = aj["project_application_volume_counter"]; - - a.ObjectStorage = aj["project_application_object_storage"]; - a.SpecialHardware = aj["project_application_special_hardware"]; - - a.Institute = aj["project_application_institute"]; - a.Workgroup = aj["project_application_workgroup"]; - - a.DateSubmitted = aj["project_application_date_submitted"]; - a.DateStatusChanged = aj["project_application_date_status_changed"]; - a.User = aj["project_application_user"]["username"]; - a.UserEmail = aj["project_application_user"]["email"]; - a.Status = aj["project_application_status"]; - if (a.Status==this.APPROVED_STATUS){ - a.DaysRunning=Math.ceil((Math.abs(Date.now() - new Date(a.DateStatusChanged).getTime())) / (1000 * 3600 * 24)); + //check if user is a Vo admin so we can serv according buttons + for (let vkey in admin_vos) { + if (admin_vos[vkey]["id"] == this.perunsettings.getPerunVO().toString()) { + this.is_vo_admin = true; + this.applicataionsservice + .getAllApplications().toPromise() + .then(result => { + let res = result.json(); + + for (let key in res) { + + let aj = res[key]; + let a = new Application(); + a.Id = aj["project_application_id"]; + + a.Name = aj["project_application_name"]; + a.Shortname = aj["project_application_shortname"]; + a.Description = aj["project_application_description"]; + a.Lifetime = aj["project_application_lifetime"]; + + a.VMsRequested = aj["project_application_vms_requested"]; + a.RamPerVM = aj["project_application_ram_per_vm"]; + a.CoresPerVM = aj["project_application_cores_per_vm"]; + a.VolumeLimit = aj["project_application_volume_limit"]; + a.VolumeCounter = aj["project_application_volume_counter"]; + + a.ObjectStorage = aj["project_application_object_storage"]; + a.SpecialHardware = aj["project_application_special_hardware"]; + + a.Institute = aj["project_application_institute"]; + a.Workgroup = aj["project_application_workgroup"]; + + a.DateSubmitted = aj["project_application_date_submitted"]; + a.DateStatusChanged = aj["project_application_date_status_changed"]; + a.User = aj["project_application_user"]["username"]; + a.UserEmail = aj["project_application_user"]["email"]; + a.Status = aj["project_application_status"]; + if (a.Status == this.APPROVED_STATUS) { + a.DaysRunning = Math.ceil((Math.abs(Date.now() - new Date(a.DateStatusChanged).getTime())) / (1000 * 3600 * 24)); - } - a.Comment= aj["project_application_comment"]; - a.OpenStackProject = aj["project_application_openstack_project"]; - if (a.Status !== 1) { - if (aj['project_application_perun_id']){ - this.groupservice.getFacilityByGroup(aj['project_application_perun_id']).subscribe(result => { - - let details = result['Details']; - let details_array = []; - for (let detail in details) { - let detail_tuple = [detail, details[detail]]; - details_array.push(detail_tuple); - } + } - a.ComputecenterDetails = details_array; - a.ComputeCenter = [result['Facility'],result['FacilityID']]; + a.Comment = aj["project_application_comment"]; + a.OpenStackProject = aj["project_application_openstack_project"]; + if (a.Status !== 1) { + if (aj['project_application_perun_id']) { + this.groupservice.getFacilityByGroup(aj['project_application_perun_id']).subscribe(result => { + + let details = result['Details']; + let details_array = []; + for (let detail in details) { + let detail_tuple = [detail, details[detail]]; + details_array.push(detail_tuple); + } + + a.ComputecenterDetails = details_array; + a.ComputeCenter = [result['Facility'], result['FacilityID']]; + + if (a.Status == this.EXTENSION_STATUS) { + this.applicataionsservice.getApplicationsRenewalRequest(a.Id).subscribe(result => { + res = result.json() + let r = new ApplicationExtension(); + + r.Id = res['project_application']; + r.Lifetime = res['project_application_renewal_lifetime']; + r.VolumeLimit = res['project_application_renewal_volume_limit']; + r.VolumeCounter = res['project_application_renewal_volume_counter']; + r.VMsRequested = res['project_application_renewal_vms_requested']; + r.Comment = res['project_application_renewal_comment']; + r.CoresPerVM = res['project_application_renewal_cores_per_vm']; + r.ObjectStorage = res['project_application_renewal_object_storage']; + r.RamPerVM = res['project_application_renewal_ram_per_vm']; + r.Comment = res['project_application_renewal_comment']; + let special_hardware = []; + if (res['project_application_renewal_special_hardware'] != null) { + let special_hardware_string = res['project_application_renewal_special_hardware'].toString(); + + for (let c = 0; c < special_hardware_string.length; c++) { + let sh = special_hardware_string.charAt(c) == this.FPGA ? "FPGA" : "GPU"; + special_hardware.push(sh) + + } + + r.SpecialHardware = special_hardware; + } + a.ApplicationExtension = r + this.all_applications.push(a) + }) + + } + else { + this.all_applications.push((a)) + } + + }) + + } + } + else { + a.ComputeCenter = ['None', -1] + + if (a.Status == this.EXTENSION_STATUS) { + this.applicataionsservice.getApplicationsRenewalRequest(a.Id).subscribe(result => { + res = result.json() + let r = new ApplicationExtension(); + + r.Id = res['project_application']; + r.Lifetime = res['project_application_renewal_lifetime']; + r.VolumeLimit = res['project_application_renewal_volume_limit']; + r.VolumeCounter = res['project_application_renewal_volume_counter']; + r.VMsRequested = res['project_application_renewal_vms_requested']; + r.Comment = res['project_application_renewal_comment']; + r.CoresPerVM = res['project_application_renewal_cores_per_vm']; + r.ObjectStorage = res['project_application_renewal_object_storage']; + r.RamPerVM = res['project_application_renewal_ram_per_vm']; + r.Comment = res['project_application_renewal_comment']; + let special_hardware = []; + if (res['project_application_renewal_special_hardware'] != null) { + let special_hardware_string = res['project_application_renewal_special_hardware'].toString(); + + for (let c = 0; c < special_hardware_string.length; c++) { + let sh = special_hardware_string.charAt(c) == this.FPGA ? "FPGA" : "GPU"; + special_hardware.push(sh) + + } + + r.SpecialHardware = special_hardware; + } + + a.ApplicationExtension = r + this.all_applications.push(a) + }) - this.all_applications.push(a) + } + else { + this.all_applications.push((a)) + } - }) } - else if (a.Shortname){ - this.groupservice.getFacilityByGroup(a.Shortname).subscribe(result => { - - let details = result['Details']; - let details_array = []; - for (let detail in details) { - let detail_tuple = [detail, details[detail]]; - details_array.push(detail_tuple); - } - a.ComputecenterDetails = details_array; - a.ComputeCenter = [result['Facility'],result['FacilityID']]; + } + }); + break; + } + } - this.all_applications.push(a) + } + ) + } - })} - else { - this.groupservice.getFacilityByGroup(a.Name).subscribe(result => { - let details = result['Details']; - let details_array = []; - for (let detail in details) { - let detail_tuple = [detail, details[detail]]; - details_array.push(detail_tuple); - } + public requestExtension(data) { - a.ComputecenterDetails = details_array; - a.ComputeCenter = [result['Facility'],result['FacilityID']]; + this.applicataionsservice.requestRenewal(data).subscribe(result => { + this.user_applications = []; + this.all_applications = []; + this.getUserApplications(); + this.getAllApplications(); + }) - this.all_applications.push(a) - }) + } - } - } - else { - a.ComputeCenter = ['None',-1] + public approveExtension(application_id: number) { + this.applicataionsservice.approveRenewal(application_id).subscribe(result => { + this.user_applications = []; + this.all_applications = []; + this.getUserApplications(); + this.getAllApplications(); + }) + } - this.all_applications.push(a) - } - } - }); - break; - } - } - }); + public declineExtension(application_id: number) { + this.applicataionsservice.declineRenewal(application_id).subscribe(result => { + this.user_applications = []; + this.all_applications = []; + this.getUserApplications(); + this.getAllApplications(); + }) } + public getCollapseStatus(id: string) { if (id in this.collapse_status) { return this.collapse_status[id]; @@ -264,11 +419,11 @@ export class ApplicationsComponent { return s; } - public lifeTimeReached(lifetime:number,running:number,status_changed_string:string):string{ - let status_changed=new Date(status_changed_string); - let LifetimeDays = Math.ceil(Math.abs(moment(status_changed).add(lifetime, 'months').toDate().getTime() - status_changed.getTime())) / (1000 * 3600 * 24) + public lifeTimeReached(lifetime: number, running: number, status_changed_string: string): string { + let status_changed = new Date(status_changed_string); + let LifetimeDays = Math.ceil(Math.abs(moment(status_changed).add(lifetime, 'months').toDate().getTime() - status_changed.getTime())) / (1000 * 3600 * 24) - return (LifetimeDays - running) < 0 ? "red" :"black"; + return (LifetimeDays - running) < 0 ? "red" : "black"; } public getIdByStatus(name: string): number { @@ -281,12 +436,13 @@ export class ApplicationsComponent { return s; } - public resetNotificationModal(){ - this.notificationModalTitle= "Notification"; - this.notificationModalMessage="Please wait..."; + public resetNotificationModal() { + this.notificationModalTitle = "Notification"; + this.notificationModalMessage = "Please wait..."; this.notificationModalType = "info"; this.notificationModalIsClosable = false; } + public updateNotificaitonModal(title: string, message: string, closable: true, type: string) { this.notificationModalTitle = title; this.notificationModalMessage = message; @@ -295,12 +451,13 @@ export class ApplicationsComponent { } - public createGroup(name, description, manager_elixir_id, application_id, compute_center, openstack_project,numberofVms,volumelimit,lifetime,longname,volumecounter) { + public createGroup(name, description, manager_elixir_id, application_id, compute_center, openstack_project, numberofVms, volumelimit, lifetime, longname, volumecounter) { //get memeber id in order to add the user later as the new member and manager of the group let manager_member_id: number; let manager_member_user_id: number; let new_group_id: number; + let re = /[-:. ,/]/gi let shortNameDate=name + (new Date(Date.now()).toLocaleString().replace(re,'')); this.userservice.getMemberByExtSourceNameAndExtLogin(manager_elixir_id).toPromise() @@ -317,27 +474,28 @@ export class ApplicationsComponent { new_group_id = group["id"]; //add the application user to the group - return this.groupservice.addMember(new_group_id, manager_member_id,compute_center).toPromise(); + return this.groupservice.addMember(new_group_id, manager_member_id, compute_center).toPromise(); }).then(null_result => { - return this.groupservice.addAdmin(new_group_id, manager_member_user_id,compute_center).toPromise(); + return this.groupservice.addAdmin(new_group_id, manager_member_user_id, compute_center).toPromise(); }).then(null_result => { return this.applicationstatusservice.setApplicationStatus(application_id, this.getIdByStatus("approved"), compute_center).toPromise(); }).then(null_result => { //setting approved status for Perun Group - let APPRVOVED=2; + let APPRVOVED = 2; this.groupservice.setPerunGroupStatus(new_group_id, APPRVOVED).toPromise(); this.groupservice.setdeNBIDirectAcces(new_group_id, openstack_project).toPromise(); - if (compute_center != 'undefined'){ - this.groupservice.assignGroupToResource(new_group_id.toString(), compute_center).subscribe();} - this.groupservice.setShortname(new_group_id.toString(),name).subscribe(); - this.groupservice.setName(new_group_id.toString(),longname).subscribe(); - this.groupservice.setNumberOfVms(new_group_id.toString(),numberofVms.toString()).subscribe(); - this.groupservice.setDescription(new_group_id.toString(),description).subscribe(); - this.groupservice.setLifetime(new_group_id.toString(),lifetime.toString()).subscribe(); - this.groupservice.setPerunId(new_group_id.toString(),application_id).subscribe(); - this.groupservice.setGroupVolumeLimit(new_group_id,volumelimit).subscribe(); - this.groupservice.setGroupVolumeCounter(new_group_id,volumecounter).subscribe(); + if (compute_center != 'undefined') { + this.groupservice.assignGroupToResource(new_group_id.toString(), compute_center).subscribe(); + } + this.groupservice.setShortname(new_group_id.toString(), name).subscribe(); + this.groupservice.setName(new_group_id.toString(), longname).subscribe(); + this.groupservice.setNumberOfVms(new_group_id.toString(), numberofVms.toString()).subscribe(); + this.groupservice.setDescription(new_group_id.toString(), description).subscribe(); + this.groupservice.setLifetime(new_group_id.toString(), lifetime.toString()).subscribe(); + this.groupservice.setPerunId(new_group_id.toString(), application_id).subscribe(); + this.groupservice.setGroupVolumeLimit(new_group_id, volumelimit).subscribe(); + this.groupservice.setGroupVolumeCounter(new_group_id, volumecounter).subscribe(); //update modal this.updateNotificaitonModal("Success", "The new project was created", true, "success"); //update applications @@ -365,38 +523,35 @@ export class ApplicationsComponent { }); } - public deleteApplication(application_id){ - this.applicataionsservice.deleteApplication(application_id).toPromise() - .then(result => { - this.updateNotificaitonModal('Success', 'The application has been successfully removed', true, 'success'); - }).then( result => { - this.user_applications=[]; - this.all_applications=[]; - this.getUserApplications(); - this.getAllApplications(); - }) - .catch(error => { + public deleteApplication(application_id) { + this.applicataionsservice.deleteApplication(application_id).toPromise() + .then(result => { + this.updateNotificaitonModal('Success', 'The application has been successfully removed', true, 'success'); + }).then(result => { + this.user_applications = []; + this.all_applications = []; + this.getUserApplications(); + this.getAllApplications(); + }) + .catch(error => { this.updateNotificaitonModal("Failed", "Application could not be removed!", true, "danger"); }); } public activeApplicationsAvailable(): boolean { - for (let application of this.all_applications) { - if (application.Status == 1) { - return true; + for (let application of this.all_applications) { + if (application.Status == 1 || application.Status == 4) { + return true; + } } - } } - public setDeleteId(applicationId) { + public setDeleteId(applicationId) { this.deleteId = applicationId; } - - - public comingSoon() { alert("This functinality will be implemented soon!") } diff --git a/src/app/applications/applications.module.ts b/src/app/applications/applications.module.ts index 91acf548d0..8a9ffa92d1 100644 --- a/src/app/applications/applications.module.ts +++ b/src/app/applications/applications.module.ts @@ -15,7 +15,6 @@ import {VmOverviewComponent} from "../virtualmachines/vmOverview.component"; import {AddsinglevmComponent} from "./addsinglevm.component"; import {AddcloudapplicationComponent} from "./addcloudapplication.component"; - @NgModule({ imports: [ ApplicationsRoutingModule, diff --git a/src/app/facility_manager/facilityprojectsoverview.component.html b/src/app/facility_manager/facilityprojectsoverview.component.html index 9575200bee..9a37fc5045 100644 --- a/src/app/facility_manager/facilityprojectsoverview.component.html +++ b/src/app/facility_manager/facilityprojectsoverview.component.html @@ -26,6 +26,7 @@

Projects Overview: {{selectedFacility['Facility']}}
+
@@ -34,6 +35,7 @@

Projects Overview: {{selectedFacility['Facility']}}

+ @@ -48,6 +50,7 @@

Projects Overview: {{selectedFacility['Facility']}}

+
Description Date createdExpiration Date Days running Lifetime in Days Actions{{ project.DateCreated }}{{project.DateEnd}} {{ project.DaysRunning }} {{project.LifetimeDays}} @@ -61,6 +64,7 @@

Projects Overview: {{selectedFacility['Facility']}}

+
@@ -81,6 +85,7 @@

Projects Overview

Projects
+
@@ -16,6 +17,7 @@

Projects Overview

+ @@ -32,9 +34,9 @@

Projects Overview

{{project.ComputeCenter[0]}}

+ - +
Description Facility Date createdExpiration Date Days running Lifetime in Days Actions {{ project.DateCreated }}{{project.DateEnd}} {{ project.DaysRunning }}{{project.LifetimeDays}}{{project.LifetimeDays}}
+
@@ -85,6 +89,7 @@