Merge branch 'DATALAB-2091' into DATALAB-2258
diff --git a/infrastructure-provisioning/src/general/files/gcp/jupyter_description.json b/infrastructure-provisioning/src/general/files/gcp/jupyter_description.json
index a94ba57..4c759bb 100644
--- a/infrastructure-provisioning/src/general/files/gcp/jupyter_description.json
+++ b/infrastructure-provisioning/src/general/files/gcp/jupyter_description.json
@@ -29,5 +29,9 @@
"version": "jupyter_notebook-6.0.2",
"vendor": "GCP"
}
+ ],
+ "gpu_types": [
+ {"Size": "S", "Gpu_type": "nvidia-tesla-t4"},
+ {"Size": "M", "Gpu_type": "nvidia-tesla-v100"}
]
}
\ No newline at end of file
diff --git a/infrastructure-provisioning/src/general/lib/os/debian/edge_lib.py b/infrastructure-provisioning/src/general/lib/os/debian/edge_lib.py
index e379901..1e727e7 100644
--- a/infrastructure-provisioning/src/general/lib/os/debian/edge_lib.py
+++ b/infrastructure-provisioning/src/general/lib/os/debian/edge_lib.py
@@ -128,8 +128,10 @@
with cd('/tmp/src/luarocks-3.3.1/'):
sudo('./configure')
sudo('make install')
+ sudo('luarocks install lua-resty-jwt 0.2.2 --tree /usr/local/openresty/lualib/resty/')
sudo('luarocks install lua-resty-openidc --tree /usr/local/openresty/lualib/resty/')
+ sudo('luarocks install lua-resty-jwt 0.2.2')
sudo('luarocks install lua-resty-openidc')
sudo('useradd -r nginx')
diff --git a/services/datalab-model/src/main/java/com/epam/datalab/dto/computational/UserComputationalResource.java b/services/datalab-model/src/main/java/com/epam/datalab/dto/computational/UserComputationalResource.java
index 8a52ece..b5c8b13 100644
--- a/services/datalab-model/src/main/java/com/epam/datalab/dto/computational/UserComputationalResource.java
+++ b/services/datalab-model/src/main/java/com/epam/datalab/dto/computational/UserComputationalResource.java
@@ -72,9 +72,20 @@
@JsonProperty("emr_version")
private String awsClusterVersion;
private int totalInstanceCount;
+ @JsonProperty("masterGPUType")
+ private String masterGPUType;
+ @JsonProperty("slaveGPUType")
+ private String slaveGPUType;
+ @JsonProperty("masterGPUCount")
+ private String masterGPUCount;
+ @JsonProperty("slaveGPUCount")
+ private String slaveGPUCount;
+ private boolean enabledGPU;
+
protected List<ClusterConfig> config;
private Map<String, String> tags;
+
public UserComputationalResource(String computationalName, String computationalId, String imageName,
String templateName, String status, Date uptime, SchedulerJobDTO schedulerData,
boolean reuploadKeyRequired, List<ResourceURL> resourceUrl,
diff --git a/services/datalab-model/src/main/java/com/epam/datalab/dto/gcp/computational/GcpComputationalResource.java b/services/datalab-model/src/main/java/com/epam/datalab/dto/gcp/computational/GcpComputationalResource.java
index dea7d4d..72485e0 100644
--- a/services/datalab-model/src/main/java/com/epam/datalab/dto/gcp/computational/GcpComputationalResource.java
+++ b/services/datalab-model/src/main/java/com/epam/datalab/dto/gcp/computational/GcpComputationalResource.java
@@ -89,5 +89,10 @@
this.slaveGPUCount = slaveGPUCount;
this.slaveGPUType = slaveGPUType;
this.enabledGPU = enabledGPU;
+ super.setMasterGPUCount(masterGPUCount);
+ super.setSlaveGPUCount(slaveGPUCount);
+ super.setMasterGPUType(masterGPUType);
+ super.setSlaveGPUType(slaveGPUType);
+ super.setEnabledGPU(enabledGPU);
}
}
diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
index b7ad081..d758fd4 100644
--- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
@@ -21,6 +21,7 @@
import com.epam.datalab.auth.UserInfo;
import com.epam.datalab.backendapi.conf.SelfServiceApplicationConfiguration;
+import com.epam.datalab.backendapi.dao.ComputationalDAO;
import com.epam.datalab.backendapi.dao.ExploratoryDAO;
import com.epam.datalab.backendapi.domain.BillingReport;
import com.epam.datalab.backendapi.domain.EndpointDTO;
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts
index 198152e..7e8ceaf 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-browser.component.ts
@@ -93,6 +93,7 @@
this.bucketStatus = this.data.bucketStatus;
this.buckets = this.data.buckets;
this.cloud = this.getCloud();
+ // this.cloud = 'azure';
}
ngOnDestroy() {
@@ -128,7 +129,6 @@
this.addedFiles = [];
}
-
public toggleSelectedFile(file, type) {
type === 'file' ? file.isSelected = !file.isSelected : file.isFolderSelected = !file.isFolderSelected;
this.selected = this.folderItems.filter(item => item.isSelected);
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-data.service.ts b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-data.service.ts
index 8573105..bf168ca 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-data.service.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/bucket-data.service.ts
@@ -146,8 +146,9 @@
parent.children.unshift(name as TodoItemNode);
} else {
if (name) {
+ console.log('parentObject', parent.object);
const child = {item: name, children: [], object: JSON.parse(JSON.stringify(parent.object))};
- child.object.object = child.object.object.slice(0, -1) + child.item + '/';
+ child.object.object = child.object.object.replace(/ا/g, '') + child.item + '/';
parent.children.unshift(child as TodoItemNode);
} else {
parent.children.unshift({item: '', children: [], object: {}} as TodoItemNode);
@@ -166,35 +167,35 @@
public removeItem(parent, child) {
parent.children.splice( parent.children.indexOf(child), 1);
this._bucketData.next(this.data);
- }
+ }
- public processFiles = (files, target, object) => {
- let pointer = target;
- files.forEach((file) => {
- if (!pointer[file]) {
- pointer[file] = {};
- }
- pointer = pointer[file];
- if (!pointer.obj) {
- pointer.obj = object;
- }
-
- });
- }
-
- public processFolderArray = (acc, curr) => {
- const files = curr.object.split('/');
- this.processFiles(files, acc, curr);
-
- return acc;
- }
-
- public convertToFolderTree = (data) => {
- const finalData = data.reduce(this.processFolderArray, {});
- if (Object.keys(finalData).length === 0) {
- return '';
+ public processFiles = (files, target, object) => {
+ let pointer = target;
+ files.forEach((file) => {
+ if (!pointer[file]) {
+ pointer[file] = {};
}
- return finalData;
+ pointer = pointer[file];
+ if (!pointer.obj) {
+ pointer.obj = object;
+ }
+
+ });
+ }
+
+ public processFolderArray = (acc, curr) => {
+ const files = curr.object.split('/');
+ this.processFiles(files, acc, curr);
+
+ return acc;
+ }
+
+ public convertToFolderTree = (data) => {
+ const finalData = data.reduce(this.processFolderArray, {});
+ if (Object.keys(finalData).length === 0) {
+ return '';
}
+ return finalData;
+ }
}
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts
index 28ed2c0..1721bbc 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/bucket-browser/folder-tree/folder-tree.component.ts
@@ -76,9 +76,22 @@
this.dataSource.data = data;
const subject = this.dataSource._flattenedData;
const subjectData = subject.getValue();
+ console.log('selected', this.selectedFolder);
+ console.log('data', subjectData);
if (this.selectedFolder) {
- this.selectedFolder = subjectData.find(v => v.item === this.selectedFolder.item &&
- v.level === this.selectedFolder.level && v.obj === this.selectedFolder.obj);
+ if (this.cloud !== 'azure') {
+ this.selectedFolder = subjectData.find(v => v.item === this.selectedFolder.item &&
+ v.level === this.selectedFolder.level && v.obj === this.selectedFolder.obj);
+ } else {
+ const selectedFolderPath = this.selectedFolder.obj.slice(0, this.selectedFolder.obj.lastIndexOf('/') + 1);
+ this.selectedFolder = subjectData.find(v => {
+ const objectPath = v.obj.slice(0, v.obj.lastIndexOf('/') + 1);
+ console.log('objectPath', selectedFolderPath);
+ console.log('selectedFolderPath', selectedFolderPath);
+ return v.item === this.selectedFolder.item &&
+ v.level === this.selectedFolder.level && objectPath === selectedFolderPath;
+ });
+ }
}
this.expandAllParents(this.selectedFolder || subjectData[0]);
this.showItem(this.selectedFolder || subjectData[0]);
@@ -151,6 +164,7 @@
if (el) {
this.treeControl.expand(el);
this.selectedFolder = el;
+ console.log(this.selectedFolder);
const path = this.getPath(el);
this.path = [];
const data = {
@@ -224,6 +238,9 @@
public removeItem(node: TodoItemFlatNode) {
const parentNode = this.flatNodeMap.get(this.getParentNode(node));
const childNode = this.flatNodeMap.get(node);
+ if (this.cloud === 'azure') {
+ parentNode.object.object = parentNode.object.object.replace(/ا/g, '');
+ }
this.bucketDataService.emptyFolder = null;
this.bucketDataService.removeItem(parentNode!, childNode);
this.resetForm();
@@ -257,6 +274,8 @@
this.toastr.error(error.message || 'Folder creation error!', 'Oops!');
});
} else {
+ flatParent.object.object = flatParent.object.object.replace(/ا/g, '');
+ parent.obj = parent.obj.replace(/ا/g, '');
this.bucketDataService.insertItem(flatParent, itemValue, false);
this.toastr.success('Folder successfully created!', 'Success!');
this.folderCreating = false;
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html
index 5ab9801..d4db786 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html
@@ -77,7 +77,7 @@
<span *ngIf="DICTIONARY[PROVIDER].cloud_provider === 'gcp' && resource.image === 'docker.datalab-dataengine-service'">1</span>
</div>
</div>
- <div class="row-wrap"
+ <div class="row-wrap"
*ngIf="DICTIONARY[PROVIDER].cloud_provider === 'gcp' && resource.image === 'docker.datalab-dataengine-service'">
<div class="col">
<p>Slave instance number:</p>
@@ -90,13 +90,38 @@
</div>
<div class="col"><span>{{ resource[DICTIONARY[PROVIDER][resource.image].master_node_shape] }}</span></div>
</div>
- <div class="row-wrap" *ngIf="resource.image === 'docker.datalab-dataengine-service'">
+ <div class="row-wrap" *ngIf="resource.image === 'docker.datalab-dataengine-service'">
<div class="col">
<p>Slave instance size:</p>
</div>
<div class="col"><span>{{ resource[DICTIONARY[PROVIDER][resource.image].slave_node_shape] }}</span></div>
</div>
-
+ <ng-template [ngIf]="resource?.enabledGPU">
+ <div class="row-wrap">
+ <div class="col">
+ <p>Master GPU type:</p>
+ </div>
+ <div class="col"><span>{{resource.masterGPUType}}</span></div>
+ </div>
+ <div class="row-wrap">
+ <div class="col">
+ <p>Slave GPU type:</p>
+ </div>
+ <div class="col"><span>{{resource.slaveGPUType}}</span></div>
+ </div>
+ <div class="row-wrap">
+ <div class="col">
+ <p>Master GPU count:</p>
+ </div>
+ <div class="col"><span>{{resource.masterGPUCount}}</span></div>
+ </div>
+ <div class="row-wrap">
+ <div class="col">
+ <p>Slave GPU count:</p>
+ </div>
+ <div class="col"><span>{{resource.slaveGPUCount}}</span></div>
+ </div>
+ </ng-template>
<div *ngIf="resource.status === 'running'">
<div class="row-wrap">
<p class="time_info">Up time {{upTimeInHours}} hour(s) since {{resource.up_time ? (resource.up_time | longDate) : "not specified."
@@ -127,7 +152,6 @@
</p>
</div>
</div>
-
<div class="checkbox-group" *ngIf="resource.image === 'docker.datalab-dataengine'
&& resource.status === 'running'
&& environment.image !== 'docker.datalab-zeppelin'
@@ -167,7 +191,6 @@
</div>
</div>
-
<div class="row-wrap detail-info content-box" *ngIf="resource.error_message">
<p class="failed">{{resource.error_message}}</p>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html
index 80f81f1..9de8286 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.html
@@ -86,7 +86,7 @@
</div>
</mat-option>
</ng-template>
- <mat-option *ngIf="model.isEmpty(filteredList) && !validity_format && autoComplete === 'ENABLED'">
+ <mat-option *ngIf="!filteredList?.length && !validity_format && autoComplete === 'ENABLED'">
<span class="configuring">No matches found</span>
</mat-option>
<mat-option *ngIf="validity_format?.length > 0 && autoComplete === 'ENABLED'">
@@ -108,7 +108,7 @@
class="library-input"
[placeholder]="'Enter library version (optional)'"
[(ngModel)]="lib.version"
- [disabled]="!lib.name"
+ [disabled]="!lib.name.trim()"
(keyup)="validateVersion(lib.version)"
(keydown.enter)="addLibrary(lib)"
>
@@ -118,15 +118,15 @@
Library version can only contain Latin letters, numbers and special characters -, _, :, /, ~, ., +.
</span>
<span class="plus-icon"
- [ngClass]="{'not-allow': lib.name?.length < 2
- || (autoComplete === 'ENABLED' && !isLibSelected )
+ [ngClass]="{'not-allow': lib.name?.trim().length < 2
+ || (autoComplete === 'ENABLED' && !isLibSelected && filteredList?.length)
|| this.selectedLib?.isInSelectedList || isVersionInvalid || autoComplete === 'UPDATING'}"
[matTooltip]="this.selectedLib?.isInSelectedList ? 'Library is in selected list' : 'Please select library from autocomplete'"
matTooltipPosition="above" [matTooltipDisabled]="(!this.selectedLib?.isInSelectedList && isLibSelected) || lib.name?.length < 2 || !this.selectedLib?.isInSelectedList && autoComplete === 'NONE'"
>
<mat-icon
(click)="addLibrary(lib)"
- [ngClass]="{'not-allowed': lib.name?.length < 2 || (autoComplete === 'ENABLED' && !isLibSelected)
+ [ngClass]="{'not-allowed': lib.name?.trim().length < 2 || (autoComplete === 'ENABLED' && !isLibSelected && filteredList?.length)
|| this.selectedLib?.isInSelectedList || isVersionInvalid || autoComplete === 'UPDATING'}">add</mat-icon>
</span>
</div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts
index 42ed182..45bc6d5 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/install-libraries/install-libraries.component.ts
@@ -223,7 +223,7 @@
this.selectedLib = {
name: this.lib.name,
version: this.lib.version,
- isInSelectedList: this.model.selectedLibs.some(el => el.name.toLowerCase() === this.lib.name.toLowerCase())
+ isInSelectedList: this.model.selectedLibs.some(el => el.name.toLowerCase() === this.lib.name.toLowerCase().trim())
};
} else {
this.selectedLib = null;
@@ -231,20 +231,20 @@
}
public addLibrary(item): void {
- if ((this.autoComplete === 'ENABLED' && !this.isLibSelected )
+ if ((this.autoComplete === 'ENABLED' && !this.isLibSelected && this.filteredList?.length)
|| (this.selectedLib && this.selectedLib.isInSelectedList) || this.isVersionInvalid || this.autoComplete === 'UPDATING') {
return;
}
-
+ this.validity_format = '';
this.isLibSelected = false;
if ( (!this.selectedLib && !this.isVersionInvalid) || (!this.selectedLib.isInSelectedList && !this.isVersionInvalid)) {
if ( this.group !== 'java') {
- this.model.selectedLibs.push({ group: this.group, name: item.name, version: item.version || 'N/A' });
+ this.model.selectedLibs.push({ group: this.group, name: item.name.trim(), version: item.version.trim() || 'N/A' });
} else {
this.model.selectedLibs.push({
group: this.group,
name: item.name.substring(0, item.name.lastIndexOf(':')),
- version: item.name.substring(item.name.lastIndexOf(':') + 1) || 'N/A'
+ version: item.name.substring(item.name.lastIndexOf(':') + 1).trim() || 'N/A'
});
}
this.libSearch.setValue('');
@@ -427,10 +427,10 @@
}
private getMatchedLibs() {
- if (!this.lib.name || this.lib.name.length < 2) {
+ if (!this.lib.name || this.lib.name.trim().length < 2) {
return;
}
- this.model.getLibrariesList(this.group, this.lib.name.toLowerCase())
+ this.model.getLibrariesList(this.group, this.lib.name.trim().toLowerCase())
.pipe(
takeUntil(this.unsubscribe$)
)