You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by di...@apache.org on 2026/08/11 14:06:16 UTC
(airavata) branch refactor-single-module updated: Refactoring data models and adding scp data models
This is an automated email from the ASF dual-hosted git repository.
DImuthuUpe pushed a commit to branch refactor-single-module
in repository https://gitbox.apache.org/repos/asf/airavata.git
The following commit(s) were added to refs/heads/refactor-single-module by this push:
new 62b70035a3 Refactoring data models and adding scp data models
62b70035a3 is described below
commit 62b70035a386bd089f3c03a37078fddd2ef8c0f1
Author: DImuthuUpe <di...@gmail.com>
AuthorDate: Tue Aug 11 10:06:10 2026 -0400
Refactoring data models and adding scp data models
---
...usterController.java => ClusterController.java} | 36 +++---
.../airavata/api/ClusterCredentialController.java | 65 ++++++++++
.../airavata/api/ClusterPartitionController.java | 61 +++++++++
.../org/apache/airavata/api/SCPDataController.java | 63 ++++++++++
.../api/SlurmClusterCredentialController.java | 68 ----------
.../airavata/api/SlurmPartitionController.java | 60 ---------
.../BatchApplicationDeploymentEntity.java | 8 +-
.../model/deployment/BatchJobConfigs.java | 2 +-
.../service/BatchApplicationDeploymentService.java | 10 +-
...stDto.java => ClusterCredentialRequestDto.java} | 2 +-
...eDto.java => ClusterCredentialResponseDto.java} | 12 +-
...estDto.java => ClusterPartitionRequestDto.java} | 2 +-
...seDto.java => ClusterPartitionResponseDto.java} | 2 +-
...usterRequestDto.java => ClusterRequestDto.java} | 4 +-
...terResponseDto.java => ClusterResponseDto.java} | 8 +-
...ialMapper.java => ClusterCredentialMapper.java} | 12 +-
...{SlurmClusterMapper.java => ClusterMapper.java} | 16 +--
...tionMapper.java => ClusterPartitionMapper.java} | 14 +--
...ialEntity.java => ClusterCredentialEntity.java} | 18 +--
...{SlurmClusterEntity.java => ClusterEntity.java} | 8 +-
...tionEntity.java => ClusterPartitionEntity.java} | 8 +-
.../repository/ClusterCredentialRepository.java | 16 +++
...sitory.java => ClusterPartitionRepository.java} | 8 +-
...usterRepository.java => ClusterRepository.java} | 4 +-
.../SlurmClusterCredentialRepository.java | 16 ---
...lService.java => ClusterCredentialService.java} | 58 ++++-----
...onService.java => ClusterPartitionService.java} | 50 ++++----
...lurmClusterService.java => ClusterService.java} | 32 ++---
.../airavata/data/dto/SCPDataRequestDto.java | 68 ++++++++++
.../airavata/data/dto/SCPDataResponseDto.java | 80 ++++++++++++
.../apache/airavata/data/mapper/SCPDataMapper.java | 37 ++++++
.../airavata/data/model/DataProvisionStatus.java | 10 ++
.../apache/airavata/data/model/SCPDataEntity.java | 102 +++++++++++++++
.../data/repository/SCPDataRepository.java | 12 ++
.../airavata/data/service/SCPDataService.java | 138 +++++++++++++++++++++
35 files changed, 809 insertions(+), 301 deletions(-)
diff --git a/src/main/java/org/apache/airavata/api/SlurmClusterController.java b/src/main/java/org/apache/airavata/api/ClusterController.java
similarity index 51%
rename from src/main/java/org/apache/airavata/api/SlurmClusterController.java
rename to src/main/java/org/apache/airavata/api/ClusterController.java
index 936050b878..6ddc31af5c 100644
--- a/src/main/java/org/apache/airavata/api/SlurmClusterController.java
+++ b/src/main/java/org/apache/airavata/api/ClusterController.java
@@ -2,9 +2,9 @@ package org.apache.airavata.api;
import jakarta.validation.Valid;
import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterResponseDto;
-import org.apache.airavata.compute.service.SlurmClusterService;
+import org.apache.airavata.compute.dto.ClusterRequestDto;
+import org.apache.airavata.compute.dto.ClusterResponseDto;
+import org.apache.airavata.compute.service.ClusterService;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@@ -17,41 +17,41 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
-@RequestMapping("/api/v1/slurm-clusters")
-public class SlurmClusterController {
+@RequestMapping("/api/v1/clusters")
+public class ClusterController {
- private final SlurmClusterService slurmClusterService;
+ private final ClusterService clusterService;
- public SlurmClusterController(SlurmClusterService slurmClusterService) {
- this.slurmClusterService = slurmClusterService;
+ public ClusterController(ClusterService clusterService) {
+ this.clusterService = clusterService;
}
@GetMapping
- public List<SlurmClusterResponseDto> getAllClusters() {
- return slurmClusterService.getAllClusters();
+ public List<ClusterResponseDto> getAllClusters() {
+ return clusterService.getAllClusters();
}
@GetMapping("/{clusterId}")
- public SlurmClusterResponseDto getCluster(@PathVariable String clusterId) {
- return slurmClusterService.getCluster(clusterId);
+ public ClusterResponseDto getCluster(@PathVariable String clusterId) {
+ return clusterService.getCluster(clusterId);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
- public SlurmClusterResponseDto createCluster(@Valid @RequestBody SlurmClusterRequestDto request) {
- return slurmClusterService.createCluster(request);
+ public ClusterResponseDto createCluster(@Valid @RequestBody ClusterRequestDto request) {
+ return clusterService.createCluster(request);
}
@PutMapping("/{clusterId}")
- public SlurmClusterResponseDto updateCluster(
- @PathVariable String clusterId, @Valid @RequestBody SlurmClusterRequestDto request) {
- return slurmClusterService.updateCluster(clusterId, request);
+ public ClusterResponseDto updateCluster(
+ @PathVariable String clusterId, @Valid @RequestBody ClusterRequestDto request) {
+ return clusterService.updateCluster(clusterId, request);
}
/** Deleting a cluster also deletes its partitions. */
@DeleteMapping("/{clusterId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteCluster(@PathVariable String clusterId) {
- slurmClusterService.deleteCluster(clusterId);
+ clusterService.deleteCluster(clusterId);
}
}
diff --git a/src/main/java/org/apache/airavata/api/ClusterCredentialController.java b/src/main/java/org/apache/airavata/api/ClusterCredentialController.java
new file mode 100644
index 0000000000..bcc8c4b0db
--- /dev/null
+++ b/src/main/java/org/apache/airavata/api/ClusterCredentialController.java
@@ -0,0 +1,65 @@
+package org.apache.airavata.api;
+
+import jakarta.validation.Valid;
+import java.util.List;
+import org.apache.airavata.compute.dto.ClusterCredentialRequestDto;
+import org.apache.airavata.compute.dto.ClusterCredentialResponseDto;
+import org.apache.airavata.compute.service.ClusterCredentialService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+/** The owning user is never a request parameter — see {@code ClusterCredentialService.createCredential}. */
+@RestController
+@RequestMapping("/api/v1/cluster-credentials")
+public class ClusterCredentialController {
+
+ private final ClusterCredentialService clusterCredentialService;
+
+ public ClusterCredentialController(ClusterCredentialService clusterCredentialService) {
+ this.clusterCredentialService = clusterCredentialService;
+ }
+
+ /** Every binding across every user — admin only. Optionally scoped to {@code clusterId}. */
+ @GetMapping
+ public List<ClusterCredentialResponseDto> getAllCredentials(@RequestParam(required = false) String clusterId) {
+ return clusterCredentialService.getAllCredentials(clusterId);
+ }
+
+ /** The caller's own bindings. Optionally scoped to {@code clusterId}. */
+ @GetMapping("/me")
+ public List<ClusterCredentialResponseDto> getMyCredentials(@RequestParam(required = false) String clusterId) {
+ return clusterCredentialService.getMyCredentials(clusterId);
+ }
+
+ @GetMapping("/{id}")
+ public ClusterCredentialResponseDto getCredential(@PathVariable String id) {
+ return clusterCredentialService.getCredential(id);
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public ClusterCredentialResponseDto createCredential(@Valid @RequestBody ClusterCredentialRequestDto request) {
+ return clusterCredentialService.createCredential(request);
+ }
+
+ @PutMapping("/{id}")
+ public ClusterCredentialResponseDto updateCredential(
+ @PathVariable String id, @Valid @RequestBody ClusterCredentialRequestDto request) {
+ return clusterCredentialService.updateCredential(id, request);
+ }
+
+ @DeleteMapping("/{id}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteCredential(@PathVariable String id) {
+ clusterCredentialService.deleteCredential(id);
+ }
+}
diff --git a/src/main/java/org/apache/airavata/api/ClusterPartitionController.java b/src/main/java/org/apache/airavata/api/ClusterPartitionController.java
new file mode 100644
index 0000000000..c9d69d776c
--- /dev/null
+++ b/src/main/java/org/apache/airavata/api/ClusterPartitionController.java
@@ -0,0 +1,61 @@
+package org.apache.airavata.api;
+
+import jakarta.validation.Valid;
+import java.util.List;
+import org.apache.airavata.compute.dto.ClusterPartitionRequestDto;
+import org.apache.airavata.compute.dto.ClusterPartitionResponseDto;
+import org.apache.airavata.compute.service.ClusterPartitionService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+/** Partitions are a sub-resource of their cluster; every path is scoped by cluster id. */
+@RestController
+@RequestMapping("/api/v1/clusters/{clusterId}/partitions")
+public class ClusterPartitionController {
+
+ private final ClusterPartitionService clusterPartitionService;
+
+ public ClusterPartitionController(ClusterPartitionService clusterPartitionService) {
+ this.clusterPartitionService = clusterPartitionService;
+ }
+
+ @GetMapping
+ public List<ClusterPartitionResponseDto> getPartitions(@PathVariable String clusterId) {
+ return clusterPartitionService.getPartitions(clusterId);
+ }
+
+ @GetMapping("/{partitionId}")
+ public ClusterPartitionResponseDto getPartition(
+ @PathVariable String clusterId, @PathVariable String partitionId) {
+ return clusterPartitionService.getPartition(clusterId, partitionId);
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public ClusterPartitionResponseDto createPartition(
+ @PathVariable String clusterId, @Valid @RequestBody ClusterPartitionRequestDto request) {
+ return clusterPartitionService.createPartition(clusterId, request);
+ }
+
+ @PutMapping("/{partitionId}")
+ public ClusterPartitionResponseDto updatePartition(
+ @PathVariable String clusterId,
+ @PathVariable String partitionId,
+ @Valid @RequestBody ClusterPartitionRequestDto request) {
+ return clusterPartitionService.updatePartition(clusterId, partitionId, request);
+ }
+
+ @DeleteMapping("/{partitionId}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deletePartition(@PathVariable String clusterId, @PathVariable String partitionId) {
+ clusterPartitionService.deletePartition(clusterId, partitionId);
+ }
+}
diff --git a/src/main/java/org/apache/airavata/api/SCPDataController.java b/src/main/java/org/apache/airavata/api/SCPDataController.java
new file mode 100644
index 0000000000..7effd6eb94
--- /dev/null
+++ b/src/main/java/org/apache/airavata/api/SCPDataController.java
@@ -0,0 +1,63 @@
+package org.apache.airavata.api;
+
+import jakarta.validation.Valid;
+import java.util.List;
+import org.apache.airavata.data.dto.SCPDataRequestDto;
+import org.apache.airavata.data.dto.SCPDataResponseDto;
+import org.apache.airavata.data.service.SCPDataService;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+/** The owning user is never a request parameter — see {@code SCPDataService.createData}. */
+@RestController
+@RequestMapping("/api/v1/scp-data")
+public class SCPDataController {
+
+ private final SCPDataService scpDataService;
+
+ public SCPDataController(SCPDataService scpDataService) {
+ this.scpDataService = scpDataService;
+ }
+
+ /** Every data registration across every user — admin only. */
+ @GetMapping
+ public List<SCPDataResponseDto> getAllData() {
+ return scpDataService.getAllData();
+ }
+
+ /** The caller's own data registrations. */
+ @GetMapping("/me")
+ public List<SCPDataResponseDto> getMyData() {
+ return scpDataService.getMyData();
+ }
+
+ @GetMapping("/{id}")
+ public SCPDataResponseDto getData(@PathVariable String id) {
+ return scpDataService.getData(id);
+ }
+
+ @PostMapping
+ @ResponseStatus(HttpStatus.CREATED)
+ public SCPDataResponseDto createData(@Valid @RequestBody SCPDataRequestDto request) {
+ return scpDataService.createData(request);
+ }
+
+ @PutMapping("/{id}")
+ public SCPDataResponseDto updateData(@PathVariable String id, @Valid @RequestBody SCPDataRequestDto request) {
+ return scpDataService.updateData(id, request);
+ }
+
+ @DeleteMapping("/{id}")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
+ public void deleteData(@PathVariable String id) {
+ scpDataService.deleteData(id);
+ }
+}
diff --git a/src/main/java/org/apache/airavata/api/SlurmClusterCredentialController.java b/src/main/java/org/apache/airavata/api/SlurmClusterCredentialController.java
deleted file mode 100644
index 63923c1a0c..0000000000
--- a/src/main/java/org/apache/airavata/api/SlurmClusterCredentialController.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.apache.airavata.api;
-
-import jakarta.validation.Valid;
-import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialResponseDto;
-import org.apache.airavata.compute.service.SlurmClusterCredentialService;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestController;
-
-/** The owning user is never a request parameter — see {@code SlurmClusterCredentialService.createCredential}. */
-@RestController
-@RequestMapping("/api/v1/slurm-cluster-credentials")
-public class SlurmClusterCredentialController {
-
- private final SlurmClusterCredentialService slurmClusterCredentialService;
-
- public SlurmClusterCredentialController(SlurmClusterCredentialService slurmClusterCredentialService) {
- this.slurmClusterCredentialService = slurmClusterCredentialService;
- }
-
- /** Every binding across every user — admin only. Optionally scoped to {@code clusterId}. */
- @GetMapping
- public List<SlurmClusterCredentialResponseDto> getAllCredentials(
- @RequestParam(required = false) String clusterId) {
- return slurmClusterCredentialService.getAllCredentials(clusterId);
- }
-
- /** The caller's own bindings. Optionally scoped to {@code clusterId}. */
- @GetMapping("/me")
- public List<SlurmClusterCredentialResponseDto> getMyCredentials(
- @RequestParam(required = false) String clusterId) {
- return slurmClusterCredentialService.getMyCredentials(clusterId);
- }
-
- @GetMapping("/{id}")
- public SlurmClusterCredentialResponseDto getCredential(@PathVariable String id) {
- return slurmClusterCredentialService.getCredential(id);
- }
-
- @PostMapping
- @ResponseStatus(HttpStatus.CREATED)
- public SlurmClusterCredentialResponseDto createCredential(
- @Valid @RequestBody SlurmClusterCredentialRequestDto request) {
- return slurmClusterCredentialService.createCredential(request);
- }
-
- @PutMapping("/{id}")
- public SlurmClusterCredentialResponseDto updateCredential(
- @PathVariable String id, @Valid @RequestBody SlurmClusterCredentialRequestDto request) {
- return slurmClusterCredentialService.updateCredential(id, request);
- }
-
- @DeleteMapping("/{id}")
- @ResponseStatus(HttpStatus.NO_CONTENT)
- public void deleteCredential(@PathVariable String id) {
- slurmClusterCredentialService.deleteCredential(id);
- }
-}
diff --git a/src/main/java/org/apache/airavata/api/SlurmPartitionController.java b/src/main/java/org/apache/airavata/api/SlurmPartitionController.java
deleted file mode 100644
index 87e27a5471..0000000000
--- a/src/main/java/org/apache/airavata/api/SlurmPartitionController.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.apache.airavata.api;
-
-import jakarta.validation.Valid;
-import java.util.List;
-import org.apache.airavata.compute.dto.SlurmPartitionRequestDto;
-import org.apache.airavata.compute.dto.SlurmPartitionResponseDto;
-import org.apache.airavata.compute.service.SlurmPartitionService;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestController;
-
-/** Partitions are a sub-resource of their cluster; every path is scoped by cluster id. */
-@RestController
-@RequestMapping("/api/v1/slurm-clusters/{clusterId}/partitions")
-public class SlurmPartitionController {
-
- private final SlurmPartitionService slurmPartitionService;
-
- public SlurmPartitionController(SlurmPartitionService slurmPartitionService) {
- this.slurmPartitionService = slurmPartitionService;
- }
-
- @GetMapping
- public List<SlurmPartitionResponseDto> getPartitions(@PathVariable String clusterId) {
- return slurmPartitionService.getPartitions(clusterId);
- }
-
- @GetMapping("/{partitionId}")
- public SlurmPartitionResponseDto getPartition(@PathVariable String clusterId, @PathVariable String partitionId) {
- return slurmPartitionService.getPartition(clusterId, partitionId);
- }
-
- @PostMapping
- @ResponseStatus(HttpStatus.CREATED)
- public SlurmPartitionResponseDto createPartition(
- @PathVariable String clusterId, @Valid @RequestBody SlurmPartitionRequestDto request) {
- return slurmPartitionService.createPartition(clusterId, request);
- }
-
- @PutMapping("/{partitionId}")
- public SlurmPartitionResponseDto updatePartition(
- @PathVariable String clusterId,
- @PathVariable String partitionId,
- @Valid @RequestBody SlurmPartitionRequestDto request) {
- return slurmPartitionService.updatePartition(clusterId, partitionId, request);
- }
-
- @DeleteMapping("/{partitionId}")
- @ResponseStatus(HttpStatus.NO_CONTENT)
- public void deletePartition(@PathVariable String clusterId, @PathVariable String partitionId) {
- slurmPartitionService.deletePartition(clusterId, partitionId);
- }
-}
diff --git a/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java b/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java
index 7060283806..6ffa6d80d9 100644
--- a/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java
+++ b/src/main/java/org/apache/airavata/application/model/deployment/BatchApplicationDeploymentEntity.java
@@ -1,7 +1,7 @@
package org.apache.airavata.application.model.deployment;
import org.apache.airavata.application.model.template.ApplicationTemplateEntity;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
+import org.apache.airavata.compute.model.ClusterEntity;
import org.apache.airavata.credentials.model.SSHUserCredential;
import jakarta.persistence.CascadeType;
@@ -25,7 +25,7 @@ public class BatchApplicationDeploymentEntity {
@ManyToOne
@JoinColumn(name = "cluster_id", foreignKey = @ForeignKey(name = "fk_dep_slurm_cluster"))
- private SlurmClusterEntity slurmCluster;
+ private ClusterEntity slurmCluster;
@ManyToOne
@JoinColumn(name = "template_id", foreignKey = @ForeignKey(name = "fk_dep_app_template"))
@@ -70,11 +70,11 @@ public class BatchApplicationDeploymentEntity {
this.deploymentId = deploymentId;
}
- public SlurmClusterEntity getSlurmCluster() {
+ public ClusterEntity getSlurmCluster() {
return slurmCluster;
}
- public void setSlurmCluster(SlurmClusterEntity slurmCluster) {
+ public void setSlurmCluster(ClusterEntity slurmCluster) {
this.slurmCluster = slurmCluster;
}
diff --git a/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java b/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java
index a20bc9449f..f7824d3f9e 100644
--- a/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java
+++ b/src/main/java/org/apache/airavata/application/model/deployment/BatchJobConfigs.java
@@ -9,7 +9,7 @@ import jakarta.persistence.Id;
/**
* Batch-scheduler resource request for a {@link BatchApplicationDeploymentEntity}. Owned
* by its deployment — created, replaced and deleted with it — rather than a shareable
- * aggregate like {@code ApplicationTemplateEntity} or {@code SlurmClusterEntity}.
+ * aggregate like {@code ApplicationTemplateEntity} or {@code ClusterEntity}.
*/
@Entity
public class BatchJobConfigs {
diff --git a/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java b/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java
index 0767d46820..e43b647aca 100644
--- a/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java
+++ b/src/main/java/org/apache/airavata/application/service/BatchApplicationDeploymentService.java
@@ -8,8 +8,8 @@ import org.apache.airavata.application.model.deployment.BatchApplicationDeployme
import org.apache.airavata.application.model.template.ApplicationTemplateEntity;
import org.apache.airavata.application.repository.ApplicationTemplateRepository;
import org.apache.airavata.application.repository.BatchApplicationDeploymentRepository;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.repository.ClusterRepository;
import org.apache.airavata.credentials.model.SSHUserCredential;
import org.apache.airavata.credentials.repository.SSHUserCredentialRepository;
import org.springframework.http.HttpStatus;
@@ -24,14 +24,14 @@ public class BatchApplicationDeploymentService {
private final BatchApplicationDeploymentRepository deploymentRepository;
private final ApplicationTemplateRepository templateRepository;
- private final SlurmClusterRepository clusterRepository;
+ private final ClusterRepository clusterRepository;
private final SSHUserCredentialRepository credentialRepository;
private final BatchApplicationDeploymentMapper mapper;
public BatchApplicationDeploymentService(
BatchApplicationDeploymentRepository deploymentRepository,
ApplicationTemplateRepository templateRepository,
- SlurmClusterRepository clusterRepository,
+ ClusterRepository clusterRepository,
SSHUserCredentialRepository credentialRepository,
BatchApplicationDeploymentMapper mapper) {
this.deploymentRepository = deploymentRepository;
@@ -104,7 +104,7 @@ public class BatchApplicationDeploymentService {
* The cluster reference is optional — the column is nullable, so an absent id leaves
* the deployment unattached rather than failing. A supplied id must resolve.
*/
- private SlurmClusterEntity resolveCluster(String clusterId) {
+ private ClusterEntity resolveCluster(String clusterId) {
if (clusterId == null || clusterId.isBlank()) {
return null;
}
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialRequestDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialRequestDto.java
similarity index 95%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialRequestDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterCredentialRequestDto.java
index 72f64542fd..989c21c1ca 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialRequestDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialRequestDto.java
@@ -9,7 +9,7 @@ import jakarta.validation.constraints.NotBlank;
* token, never from client input, so a caller cannot bind a credential on another user's
* behalf.
*/
-public class SlurmClusterCredentialRequestDto {
+public class ClusterCredentialRequestDto {
@NotBlank(message = "Cluster id cannot be blank")
private String clusterId;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialResponseDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialResponseDto.java
similarity index 68%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialResponseDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterCredentialResponseDto.java
index 726936549f..d76eae3b30 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterCredentialResponseDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterCredentialResponseDto.java
@@ -1,19 +1,19 @@
package org.apache.airavata.compute.dto;
/** Read view of a per-user SSH credential binding on a Slurm cluster. */
-public class SlurmClusterCredentialResponseDto {
+public class ClusterCredentialResponseDto {
- private String slurmClusterCredentialId;
+ private String clusterCredentialId;
private String clusterId;
private String sshCredentialId;
private String userId;
- public String getSlurmClusterCredentialId() {
- return slurmClusterCredentialId;
+ public String getClusterCredentialId() {
+ return clusterCredentialId;
}
- public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
- this.slurmClusterCredentialId = slurmClusterCredentialId;
+ public void setClusterCredentialId(String clusterCredentialId) {
+ this.clusterCredentialId = clusterCredentialId;
}
public String getClusterId() {
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionRequestDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionRequestDto.java
similarity index 98%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmPartitionRequestDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterPartitionRequestDto.java
index bf304b5a15..cc131d25fa 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionRequestDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionRequestDto.java
@@ -3,7 +3,7 @@ package org.apache.airavata.compute.dto;
import jakarta.validation.constraints.NotBlank;
/** Create/update payload for a partition of a Slurm cluster. */
-public class SlurmPartitionRequestDto {
+public class ClusterPartitionRequestDto {
@NotBlank(message = "Partition name cannot be blank")
private String name;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionResponseDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionResponseDto.java
similarity index 98%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmPartitionResponseDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterPartitionResponseDto.java
index eeb81197b8..93f9ef5418 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmPartitionResponseDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterPartitionResponseDto.java
@@ -1,7 +1,7 @@
package org.apache.airavata.compute.dto;
/** Read view of a partition; the owning cluster is referenced by id only. */
-public class SlurmPartitionResponseDto {
+public class ClusterPartitionResponseDto {
private String partitionId;
private String clusterId;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterRequestDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterRequestDto.java
similarity index 90%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterRequestDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterRequestDto.java
index 55bb969de4..8db49b7d50 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterRequestDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterRequestDto.java
@@ -4,10 +4,10 @@ import jakarta.validation.constraints.NotBlank;
/**
* Create/update payload for a Slurm cluster. Partitions are not accepted here — they are
- * managed through {@code /api/v1/slurm-clusters/{clusterId}/partitions} so that updating
+ * managed through {@code /api/v1/clusters/{clusterId}/partitions} so that updating
* a cluster cannot silently drop them.
*/
-public class SlurmClusterRequestDto {
+public class ClusterRequestDto {
@NotBlank(message = "Cluster name cannot be blank")
private String clusterName;
diff --git a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterResponseDto.java b/src/main/java/org/apache/airavata/compute/dto/ClusterResponseDto.java
similarity index 84%
rename from src/main/java/org/apache/airavata/compute/dto/SlurmClusterResponseDto.java
rename to src/main/java/org/apache/airavata/compute/dto/ClusterResponseDto.java
index 3a1834ea8e..6a27f7d3cb 100644
--- a/src/main/java/org/apache/airavata/compute/dto/SlurmClusterResponseDto.java
+++ b/src/main/java/org/apache/airavata/compute/dto/ClusterResponseDto.java
@@ -3,14 +3,14 @@ package org.apache.airavata.compute.dto;
import java.util.List;
/** Read view of a Slurm cluster, including its partitions. */
-public class SlurmClusterResponseDto {
+public class ClusterResponseDto {
private String clusterId;
private String clusterName;
private String clusterDescription;
private String hostName;
private String slurmHome;
- private List<SlurmPartitionResponseDto> partitions;
+ private List<ClusterPartitionResponseDto> partitions;
public String getClusterId() {
return clusterId;
@@ -52,11 +52,11 @@ public class SlurmClusterResponseDto {
this.slurmHome = slurmHome;
}
- public List<SlurmPartitionResponseDto> getPartitions() {
+ public List<ClusterPartitionResponseDto> getPartitions() {
return partitions;
}
- public void setPartitions(List<SlurmPartitionResponseDto> partitions) {
+ public void setPartitions(List<ClusterPartitionResponseDto> partitions) {
this.partitions = partitions;
}
}
diff --git a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterCredentialMapper.java b/src/main/java/org/apache/airavata/compute/mapper/ClusterCredentialMapper.java
similarity index 61%
rename from src/main/java/org/apache/airavata/compute/mapper/SlurmClusterCredentialMapper.java
rename to src/main/java/org/apache/airavata/compute/mapper/ClusterCredentialMapper.java
index 8aa913f4e6..df9d1565a3 100644
--- a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterCredentialMapper.java
+++ b/src/main/java/org/apache/airavata/compute/mapper/ClusterCredentialMapper.java
@@ -1,7 +1,7 @@
package org.apache.airavata.compute.mapper;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialResponseDto;
-import org.apache.airavata.compute.model.SlurmClusterCredentialEntity;
+import org.apache.airavata.compute.dto.ClusterCredentialResponseDto;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
@@ -10,16 +10,16 @@ import org.mapstruct.ReportingPolicy;
* Entity/DTO conversion for Slurm cluster credential bindings.
*
* <p>There is no {@code toEntity}/{@code updateEntity} here: every field on
- * {@link SlurmClusterCredentialEntity} is an association (cluster, credential, user) and
- * every one of them is resolved by {@code SlurmClusterCredentialService} — from the
+ * {@link ClusterCredentialEntity} is an association (cluster, credential, user) and
+ * every one of them is resolved by {@code ClusterCredentialService} — from the
* request DTO's ids, or from the caller's access token — so there is nothing left for a
* mapper to write onto the entity.
*/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
-public interface SlurmClusterCredentialMapper {
+public interface ClusterCredentialMapper {
@Mapping(target = "clusterId", source = "slurmCluster.clusterId")
@Mapping(target = "sshCredentialId", source = "sshUserCredential.sshCredentialId")
@Mapping(target = "userId", source = "user.userId")
- SlurmClusterCredentialResponseDto toResponseDto(SlurmClusterCredentialEntity entity);
+ ClusterCredentialResponseDto toResponseDto(ClusterCredentialEntity entity);
}
diff --git a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterMapper.java b/src/main/java/org/apache/airavata/compute/mapper/ClusterMapper.java
similarity index 57%
rename from src/main/java/org/apache/airavata/compute/mapper/SlurmClusterMapper.java
rename to src/main/java/org/apache/airavata/compute/mapper/ClusterMapper.java
index 15d2d441e9..149f2dac8e 100644
--- a/src/main/java/org/apache/airavata/compute/mapper/SlurmClusterMapper.java
+++ b/src/main/java/org/apache/airavata/compute/mapper/ClusterMapper.java
@@ -1,8 +1,8 @@
package org.apache.airavata.compute.mapper;
-import org.apache.airavata.compute.dto.SlurmClusterRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterResponseDto;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
+import org.apache.airavata.compute.dto.ClusterRequestDto;
+import org.apache.airavata.compute.dto.ClusterResponseDto;
+import org.apache.airavata.compute.model.ClusterEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
@@ -14,17 +14,17 @@ import org.mapstruct.ReportingPolicy;
*/
@Mapper(
componentModel = "spring",
- uses = SlurmPartitionMapper.class,
+ uses = ClusterPartitionMapper.class,
unmappedTargetPolicy = ReportingPolicy.IGNORE)
-public interface SlurmClusterMapper {
+public interface ClusterMapper {
- SlurmClusterResponseDto toResponseDto(SlurmClusterEntity entity);
+ ClusterResponseDto toResponseDto(ClusterEntity entity);
@Mapping(target = "clusterId", ignore = true)
@Mapping(target = "partitions", ignore = true)
- SlurmClusterEntity toEntity(SlurmClusterRequestDto dto);
+ ClusterEntity toEntity(ClusterRequestDto dto);
@Mapping(target = "clusterId", ignore = true)
@Mapping(target = "partitions", ignore = true)
- void updateEntity(SlurmClusterRequestDto dto, @MappingTarget SlurmClusterEntity entity);
+ void updateEntity(ClusterRequestDto dto, @MappingTarget ClusterEntity entity);
}
diff --git a/src/main/java/org/apache/airavata/compute/mapper/SlurmPartitionMapper.java b/src/main/java/org/apache/airavata/compute/mapper/ClusterPartitionMapper.java
similarity index 59%
rename from src/main/java/org/apache/airavata/compute/mapper/SlurmPartitionMapper.java
rename to src/main/java/org/apache/airavata/compute/mapper/ClusterPartitionMapper.java
index 97f4968f1e..8ef5458db0 100644
--- a/src/main/java/org/apache/airavata/compute/mapper/SlurmPartitionMapper.java
+++ b/src/main/java/org/apache/airavata/compute/mapper/ClusterPartitionMapper.java
@@ -1,8 +1,8 @@
package org.apache.airavata.compute.mapper;
-import org.apache.airavata.compute.dto.SlurmPartitionRequestDto;
-import org.apache.airavata.compute.dto.SlurmPartitionResponseDto;
-import org.apache.airavata.compute.model.SlurmPartitionEntity;
+import org.apache.airavata.compute.dto.ClusterPartitionRequestDto;
+import org.apache.airavata.compute.dto.ClusterPartitionResponseDto;
+import org.apache.airavata.compute.model.ClusterPartitionEntity;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
@@ -13,16 +13,16 @@ import org.mapstruct.ReportingPolicy;
* service from the path, so it is never mapped off the request body.
*/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
-public interface SlurmPartitionMapper {
+public interface ClusterPartitionMapper {
@Mapping(target = "clusterId", source = "slurmCluster.clusterId")
- SlurmPartitionResponseDto toResponseDto(SlurmPartitionEntity entity);
+ ClusterPartitionResponseDto toResponseDto(ClusterPartitionEntity entity);
@Mapping(target = "partitionId", ignore = true)
@Mapping(target = "slurmCluster", ignore = true)
- SlurmPartitionEntity toEntity(SlurmPartitionRequestDto dto);
+ ClusterPartitionEntity toEntity(ClusterPartitionRequestDto dto);
@Mapping(target = "partitionId", ignore = true)
@Mapping(target = "slurmCluster", ignore = true)
- void updateEntity(SlurmPartitionRequestDto dto, @MappingTarget SlurmPartitionEntity entity);
+ void updateEntity(ClusterPartitionRequestDto dto, @MappingTarget ClusterPartitionEntity entity);
}
diff --git a/src/main/java/org/apache/airavata/compute/model/SlurmClusterCredentialEntity.java b/src/main/java/org/apache/airavata/compute/model/ClusterCredentialEntity.java
similarity index 74%
rename from src/main/java/org/apache/airavata/compute/model/SlurmClusterCredentialEntity.java
rename to src/main/java/org/apache/airavata/compute/model/ClusterCredentialEntity.java
index c954636d77..3cc9b61001 100644
--- a/src/main/java/org/apache/airavata/compute/model/SlurmClusterCredentialEntity.java
+++ b/src/main/java/org/apache/airavata/compute/model/ClusterCredentialEntity.java
@@ -12,15 +12,15 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@Entity
-public class SlurmClusterCredentialEntity {
+public class ClusterCredentialEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- private String slurmClusterCredentialId;
+ private String clusterCredentialId;
@ManyToOne
@JoinColumn(name = "cluster_id", foreignKey = @ForeignKey(name = "fk_cluster_credential_cluster"))
- private SlurmClusterEntity slurmCluster;
+ private ClusterEntity slurmCluster;
@ManyToOne
@JoinColumn(name = "ssh_credential_id", foreignKey = @ForeignKey(name = "fk_cluster_credential_ssh_credential"))
@@ -30,19 +30,19 @@ public class SlurmClusterCredentialEntity {
@JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_cluster_credential_user"))
private UserEntity user;
- public String getSlurmClusterCredentialId() {
- return slurmClusterCredentialId;
+ public String getClusterCredentialId() {
+ return clusterCredentialId;
}
- public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
- this.slurmClusterCredentialId = slurmClusterCredentialId;
+ public void setClusterCredentialId(String clusterCredentialId) {
+ this.clusterCredentialId = clusterCredentialId;
}
- public SlurmClusterEntity getSlurmCluster() {
+ public ClusterEntity getSlurmCluster() {
return slurmCluster;
}
- public void setSlurmCluster(SlurmClusterEntity slurmCluster) {
+ public void setSlurmCluster(ClusterEntity slurmCluster) {
this.slurmCluster = slurmCluster;
}
diff --git a/src/main/java/org/apache/airavata/compute/model/SlurmClusterEntity.java b/src/main/java/org/apache/airavata/compute/model/ClusterEntity.java
similarity index 88%
rename from src/main/java/org/apache/airavata/compute/model/SlurmClusterEntity.java
rename to src/main/java/org/apache/airavata/compute/model/ClusterEntity.java
index 5bd33ea688..9f0d49b55a 100644
--- a/src/main/java/org/apache/airavata/compute/model/SlurmClusterEntity.java
+++ b/src/main/java/org/apache/airavata/compute/model/ClusterEntity.java
@@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.List;
@Entity
-public class SlurmClusterEntity {
+public class ClusterEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@@ -29,7 +29,7 @@ public class SlurmClusterEntity {
// Partitions are owned by the cluster: they are created, replaced and deleted
// with it, and have no meaning outside of it.
@OneToMany(mappedBy = "slurmCluster", cascade = CascadeType.ALL, orphanRemoval = true)
- private List<SlurmPartitionEntity> partitions = new ArrayList<>();
+ private List<ClusterPartitionEntity> partitions = new ArrayList<>();
public String getClusterId() {
return clusterId;
@@ -71,11 +71,11 @@ public class SlurmClusterEntity {
this.slurmHome = slurmHome;
}
- public List<SlurmPartitionEntity> getPartitions() {
+ public List<ClusterPartitionEntity> getPartitions() {
return partitions;
}
- public void setPartitions(List<SlurmPartitionEntity> partitions) {
+ public void setPartitions(List<ClusterPartitionEntity> partitions) {
this.partitions = partitions;
}
}
diff --git a/src/main/java/org/apache/airavata/compute/model/SlurmPartitionEntity.java b/src/main/java/org/apache/airavata/compute/model/ClusterPartitionEntity.java
similarity index 95%
rename from src/main/java/org/apache/airavata/compute/model/SlurmPartitionEntity.java
rename to src/main/java/org/apache/airavata/compute/model/ClusterPartitionEntity.java
index 3987f03ba1..f86893e42a 100644
--- a/src/main/java/org/apache/airavata/compute/model/SlurmPartitionEntity.java
+++ b/src/main/java/org/apache/airavata/compute/model/ClusterPartitionEntity.java
@@ -10,7 +10,7 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@Entity
-public class SlurmPartitionEntity {
+public class ClusterPartitionEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@@ -18,7 +18,7 @@ public class SlurmPartitionEntity {
@ManyToOne
@JoinColumn(name = "cluster_id", foreignKey = @ForeignKey(name = "fk_partition_cluster"))
- private SlurmClusterEntity slurmCluster;
+ private ClusterEntity slurmCluster;
@Column(nullable = false)
private String name;
@@ -74,11 +74,11 @@ public class SlurmPartitionEntity {
this.partitionId = partitionId;
}
- public SlurmClusterEntity getSlurmCluster() {
+ public ClusterEntity getSlurmCluster() {
return slurmCluster;
}
- public void setSlurmCluster(SlurmClusterEntity slurmCluster) {
+ public void setSlurmCluster(ClusterEntity slurmCluster) {
this.slurmCluster = slurmCluster;
}
diff --git a/src/main/java/org/apache/airavata/compute/repository/ClusterCredentialRepository.java b/src/main/java/org/apache/airavata/compute/repository/ClusterCredentialRepository.java
new file mode 100644
index 0000000000..141c841814
--- /dev/null
+++ b/src/main/java/org/apache/airavata/compute/repository/ClusterCredentialRepository.java
@@ -0,0 +1,16 @@
+package org.apache.airavata.compute.repository;
+
+import java.util.List;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.springframework.data.repository.ListCrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ClusterCredentialRepository extends ListCrudRepository<ClusterCredentialEntity, String> {
+
+ List<ClusterCredentialEntity> findBySlurmCluster_ClusterId(String clusterId);
+
+ List<ClusterCredentialEntity> findByUser_UserId(String userId);
+
+ List<ClusterCredentialEntity> findByUser_UserIdAndSlurmCluster_ClusterId(String userId, String clusterId);
+}
diff --git a/src/main/java/org/apache/airavata/compute/repository/SlurmPartitionRepository.java b/src/main/java/org/apache/airavata/compute/repository/ClusterPartitionRepository.java
similarity index 52%
rename from src/main/java/org/apache/airavata/compute/repository/SlurmPartitionRepository.java
rename to src/main/java/org/apache/airavata/compute/repository/ClusterPartitionRepository.java
index 4d6d771075..dbdb4e9dd8 100644
--- a/src/main/java/org/apache/airavata/compute/repository/SlurmPartitionRepository.java
+++ b/src/main/java/org/apache/airavata/compute/repository/ClusterPartitionRepository.java
@@ -2,18 +2,18 @@ package org.apache.airavata.compute.repository;
import java.util.List;
import java.util.Optional;
-import org.apache.airavata.compute.model.SlurmPartitionEntity;
+import org.apache.airavata.compute.model.ClusterPartitionEntity;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.stereotype.Repository;
@Repository
-public interface SlurmPartitionRepository extends ListCrudRepository<SlurmPartitionEntity, String> {
+public interface ClusterPartitionRepository extends ListCrudRepository<ClusterPartitionEntity, String> {
- List<SlurmPartitionEntity> findBySlurmCluster_ClusterId(String clusterId);
+ List<ClusterPartitionEntity> findBySlurmCluster_ClusterId(String clusterId);
/**
* Scopes a partition lookup to its cluster so a partition id from one cluster cannot
* be read or mutated through another cluster's sub-resource path.
*/
- Optional<SlurmPartitionEntity> findByPartitionIdAndSlurmCluster_ClusterId(String partitionId, String clusterId);
+ Optional<ClusterPartitionEntity> findByPartitionIdAndSlurmCluster_ClusterId(String partitionId, String clusterId);
}
diff --git a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterRepository.java b/src/main/java/org/apache/airavata/compute/repository/ClusterRepository.java
similarity index 59%
rename from src/main/java/org/apache/airavata/compute/repository/SlurmClusterRepository.java
rename to src/main/java/org/apache/airavata/compute/repository/ClusterRepository.java
index f551ce6dc6..fcd114c780 100644
--- a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterRepository.java
+++ b/src/main/java/org/apache/airavata/compute/repository/ClusterRepository.java
@@ -1,11 +1,11 @@
package org.apache.airavata.compute.repository;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
+import org.apache.airavata.compute.model.ClusterEntity;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.stereotype.Repository;
@Repository
-public interface SlurmClusterRepository extends ListCrudRepository<SlurmClusterEntity, String> {
+public interface ClusterRepository extends ListCrudRepository<ClusterEntity, String> {
boolean existsByClusterName(String clusterName);
}
diff --git a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterCredentialRepository.java b/src/main/java/org/apache/airavata/compute/repository/SlurmClusterCredentialRepository.java
deleted file mode 100644
index 0e4abe1de3..0000000000
--- a/src/main/java/org/apache/airavata/compute/repository/SlurmClusterCredentialRepository.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.apache.airavata.compute.repository;
-
-import java.util.List;
-import org.apache.airavata.compute.model.SlurmClusterCredentialEntity;
-import org.springframework.data.repository.ListCrudRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface SlurmClusterCredentialRepository extends ListCrudRepository<SlurmClusterCredentialEntity, String> {
-
- List<SlurmClusterCredentialEntity> findBySlurmCluster_ClusterId(String clusterId);
-
- List<SlurmClusterCredentialEntity> findByUser_UserId(String userId);
-
- List<SlurmClusterCredentialEntity> findByUser_UserIdAndSlurmCluster_ClusterId(String userId, String clusterId);
-}
diff --git a/src/main/java/org/apache/airavata/compute/service/SlurmClusterCredentialService.java b/src/main/java/org/apache/airavata/compute/service/ClusterCredentialService.java
similarity index 74%
rename from src/main/java/org/apache/airavata/compute/service/SlurmClusterCredentialService.java
rename to src/main/java/org/apache/airavata/compute/service/ClusterCredentialService.java
index 4ee3b16e0f..bd628db508 100644
--- a/src/main/java/org/apache/airavata/compute/service/SlurmClusterCredentialService.java
+++ b/src/main/java/org/apache/airavata/compute/service/ClusterCredentialService.java
@@ -1,13 +1,13 @@
package org.apache.airavata.compute.service;
import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterCredentialResponseDto;
-import org.apache.airavata.compute.mapper.SlurmClusterCredentialMapper;
-import org.apache.airavata.compute.model.SlurmClusterCredentialEntity;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.repository.SlurmClusterCredentialRepository;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
+import org.apache.airavata.compute.dto.ClusterCredentialRequestDto;
+import org.apache.airavata.compute.dto.ClusterCredentialResponseDto;
+import org.apache.airavata.compute.mapper.ClusterCredentialMapper;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.repository.ClusterCredentialRepository;
+import org.apache.airavata.compute.repository.ClusterRepository;
import org.apache.airavata.credentials.model.SSHUserCredential;
import org.apache.airavata.credentials.repository.SSHUserCredentialRepository;
import org.apache.airavata.iam.model.UserEntity;
@@ -32,20 +32,20 @@ import org.springframework.web.server.ResponseStatusException;
* organization-level resources those other services expose.
*/
@Service
-public class SlurmClusterCredentialService {
+public class ClusterCredentialService {
- private final SlurmClusterCredentialRepository credentialBindingRepository;
- private final SlurmClusterRepository clusterRepository;
+ private final ClusterCredentialRepository credentialBindingRepository;
+ private final ClusterRepository clusterRepository;
private final SSHUserCredentialRepository credentialRepository;
private final UserRepository userRepository;
- private final SlurmClusterCredentialMapper mapper;
+ private final ClusterCredentialMapper mapper;
- public SlurmClusterCredentialService(
- SlurmClusterCredentialRepository credentialBindingRepository,
- SlurmClusterRepository clusterRepository,
+ public ClusterCredentialService(
+ ClusterCredentialRepository credentialBindingRepository,
+ ClusterRepository clusterRepository,
SSHUserCredentialRepository credentialRepository,
UserRepository userRepository,
- SlurmClusterCredentialMapper mapper) {
+ ClusterCredentialMapper mapper) {
this.credentialBindingRepository = credentialBindingRepository;
this.clusterRepository = clusterRepository;
this.credentialRepository = credentialRepository;
@@ -56,8 +56,8 @@ public class SlurmClusterCredentialService {
/** Lists every binding across every user, optionally scoped to one cluster. */
@PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
@Transactional(readOnly = true)
- public List<SlurmClusterCredentialResponseDto> getAllCredentials(String clusterId) {
- List<SlurmClusterCredentialEntity> entities = clusterId == null
+ public List<ClusterCredentialResponseDto> getAllCredentials(String clusterId) {
+ List<ClusterCredentialEntity> entities = clusterId == null
? credentialBindingRepository.findAll()
: credentialBindingRepository.findBySlurmCluster_ClusterId(clusterId);
return entities.stream().map(mapper::toResponseDto).toList();
@@ -66,17 +66,17 @@ public class SlurmClusterCredentialService {
/** Lists the caller's own bindings, optionally scoped to one cluster. */
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
- public List<SlurmClusterCredentialResponseDto> getMyCredentials(String clusterId) {
+ public List<ClusterCredentialResponseDto> getMyCredentials(String clusterId) {
String userId = resolveCurrentUser().getUserId();
- List<SlurmClusterCredentialEntity> entities = clusterId == null
+ List<ClusterCredentialEntity> entities = clusterId == null
? credentialBindingRepository.findByUser_UserId(userId)
: credentialBindingRepository.findByUser_UserIdAndSlurmCluster_ClusterId(userId, clusterId);
return entities.stream().map(mapper::toResponseDto).toList();
}
@Transactional(readOnly = true)
- public SlurmClusterCredentialResponseDto getCredential(String id) {
- SlurmClusterCredentialEntity entity = findOrThrow(id);
+ public ClusterCredentialResponseDto getCredential(String id) {
+ ClusterCredentialEntity entity = findOrThrow(id);
requireSelfOrAdmin(entity);
return mapper.toResponseDto(entity);
}
@@ -84,8 +84,8 @@ public class SlurmClusterCredentialService {
/** Any authenticated caller may bind a credential — this is a self-service setting. */
@PreAuthorize("isAuthenticated()")
@Transactional
- public SlurmClusterCredentialResponseDto createCredential(SlurmClusterCredentialRequestDto request) {
- SlurmClusterCredentialEntity entity = new SlurmClusterCredentialEntity();
+ public ClusterCredentialResponseDto createCredential(ClusterCredentialRequestDto request) {
+ ClusterCredentialEntity entity = new ClusterCredentialEntity();
entity.setSlurmCluster(resolveCluster(request.getClusterId()));
entity.setSshUserCredential(resolveCredential(request.getSshCredentialId()));
entity.setUser(resolveCurrentUser());
@@ -94,8 +94,8 @@ public class SlurmClusterCredentialService {
/** Ownership is immutable — only the cluster/credential references can change. */
@Transactional
- public SlurmClusterCredentialResponseDto updateCredential(String id, SlurmClusterCredentialRequestDto request) {
- SlurmClusterCredentialEntity entity = findOrThrow(id);
+ public ClusterCredentialResponseDto updateCredential(String id, ClusterCredentialRequestDto request) {
+ ClusterCredentialEntity entity = findOrThrow(id);
requireSelfOrAdmin(entity);
entity.setSlurmCluster(resolveCluster(request.getClusterId()));
entity.setSshUserCredential(resolveCredential(request.getSshCredentialId()));
@@ -104,19 +104,19 @@ public class SlurmClusterCredentialService {
@Transactional
public void deleteCredential(String id) {
- SlurmClusterCredentialEntity entity = findOrThrow(id);
+ ClusterCredentialEntity entity = findOrThrow(id);
requireSelfOrAdmin(entity);
credentialBindingRepository.delete(entity);
}
- private SlurmClusterCredentialEntity findOrThrow(String id) {
+ private ClusterCredentialEntity findOrThrow(String id) {
return credentialBindingRepository
.findById(id)
.orElseThrow(() ->
new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster credential binding not found: " + id));
}
- private SlurmClusterEntity resolveCluster(String clusterId) {
+ private ClusterEntity resolveCluster(String clusterId) {
return clusterRepository
.findById(clusterId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster not found: " + clusterId));
@@ -144,7 +144,7 @@ public class SlurmClusterCredentialService {
HttpStatus.NOT_FOUND, "No user record found for authenticated principal: " + username));
}
- private void requireSelfOrAdmin(SlurmClusterCredentialEntity entity) {
+ private void requireSelfOrAdmin(ClusterCredentialEntity entity) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
boolean isSelf = entity.getUser() != null && authentication.getName().equals(entity.getUser().getUserId());
boolean isAdmin = authentication.getAuthorities().stream()
diff --git a/src/main/java/org/apache/airavata/compute/service/SlurmPartitionService.java b/src/main/java/org/apache/airavata/compute/service/ClusterPartitionService.java
similarity index 59%
rename from src/main/java/org/apache/airavata/compute/service/SlurmPartitionService.java
rename to src/main/java/org/apache/airavata/compute/service/ClusterPartitionService.java
index bbc1c40df1..83a027d6a0 100644
--- a/src/main/java/org/apache/airavata/compute/service/SlurmPartitionService.java
+++ b/src/main/java/org/apache/airavata/compute/service/ClusterPartitionService.java
@@ -1,13 +1,13 @@
package org.apache.airavata.compute.service;
import java.util.List;
-import org.apache.airavata.compute.dto.SlurmPartitionRequestDto;
-import org.apache.airavata.compute.dto.SlurmPartitionResponseDto;
-import org.apache.airavata.compute.mapper.SlurmPartitionMapper;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.model.SlurmPartitionEntity;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
-import org.apache.airavata.compute.repository.SlurmPartitionRepository;
+import org.apache.airavata.compute.dto.ClusterPartitionRequestDto;
+import org.apache.airavata.compute.dto.ClusterPartitionResponseDto;
+import org.apache.airavata.compute.mapper.ClusterPartitionMapper;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.model.ClusterPartitionEntity;
+import org.apache.airavata.compute.repository.ClusterPartitionRepository;
+import org.apache.airavata.compute.repository.ClusterRepository;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@@ -22,28 +22,28 @@ import org.springframework.web.server.ResponseStatusException;
* an accidental cross-cluster edit.
*
* <p>Partitions are persisted through their own repository rather than by mutating
- * {@link SlurmClusterEntity#getPartitions()}: the association is orphan-removing, so
+ * {@link ClusterEntity#getPartitions()}: the association is orphan-removing, so
* touching that collection here would risk deleting rows this service never intended
* to remove.
*/
@Service
-public class SlurmPartitionService {
+public class ClusterPartitionService {
- private final SlurmPartitionRepository partitionRepository;
- private final SlurmClusterRepository clusterRepository;
- private final SlurmPartitionMapper mapper;
+ private final ClusterPartitionRepository partitionRepository;
+ private final ClusterRepository clusterRepository;
+ private final ClusterPartitionMapper mapper;
- public SlurmPartitionService(
- SlurmPartitionRepository partitionRepository,
- SlurmClusterRepository clusterRepository,
- SlurmPartitionMapper mapper) {
+ public ClusterPartitionService(
+ ClusterPartitionRepository partitionRepository,
+ ClusterRepository clusterRepository,
+ ClusterPartitionMapper mapper) {
this.partitionRepository = partitionRepository;
this.clusterRepository = clusterRepository;
this.mapper = mapper;
}
@Transactional(readOnly = true)
- public List<SlurmPartitionResponseDto> getPartitions(String clusterId) {
+ public List<ClusterPartitionResponseDto> getPartitions(String clusterId) {
requireCluster(clusterId);
return partitionRepository.findBySlurmCluster_ClusterId(clusterId).stream()
.map(mapper::toResponseDto)
@@ -51,23 +51,23 @@ public class SlurmPartitionService {
}
@Transactional(readOnly = true)
- public SlurmPartitionResponseDto getPartition(String clusterId, String partitionId) {
+ public ClusterPartitionResponseDto getPartition(String clusterId, String partitionId) {
return mapper.toResponseDto(findOrThrow(clusterId, partitionId));
}
@PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
@Transactional
- public SlurmPartitionResponseDto createPartition(String clusterId, SlurmPartitionRequestDto request) {
- SlurmPartitionEntity entity = mapper.toEntity(request);
+ public ClusterPartitionResponseDto createPartition(String clusterId, ClusterPartitionRequestDto request) {
+ ClusterPartitionEntity entity = mapper.toEntity(request);
entity.setSlurmCluster(requireCluster(clusterId));
return mapper.toResponseDto(partitionRepository.save(entity));
}
@PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
@Transactional
- public SlurmPartitionResponseDto updatePartition(
- String clusterId, String partitionId, SlurmPartitionRequestDto request) {
- SlurmPartitionEntity entity = findOrThrow(clusterId, partitionId);
+ public ClusterPartitionResponseDto updatePartition(
+ String clusterId, String partitionId, ClusterPartitionRequestDto request) {
+ ClusterPartitionEntity entity = findOrThrow(clusterId, partitionId);
mapper.updateEntity(request, entity);
return mapper.toResponseDto(partitionRepository.save(entity));
}
@@ -78,13 +78,13 @@ public class SlurmPartitionService {
partitionRepository.delete(findOrThrow(clusterId, partitionId));
}
- private SlurmClusterEntity requireCluster(String clusterId) {
+ private ClusterEntity requireCluster(String clusterId) {
return clusterRepository
.findById(clusterId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster not found: " + clusterId));
}
- private SlurmPartitionEntity findOrThrow(String clusterId, String partitionId) {
+ private ClusterPartitionEntity findOrThrow(String clusterId, String partitionId) {
return partitionRepository
.findByPartitionIdAndSlurmCluster_ClusterId(partitionId, clusterId)
.orElseThrow(() -> new ResponseStatusException(
diff --git a/src/main/java/org/apache/airavata/compute/service/SlurmClusterService.java b/src/main/java/org/apache/airavata/compute/service/ClusterService.java
similarity index 62%
rename from src/main/java/org/apache/airavata/compute/service/SlurmClusterService.java
rename to src/main/java/org/apache/airavata/compute/service/ClusterService.java
index 34c1eaeb67..c77d13aea7 100644
--- a/src/main/java/org/apache/airavata/compute/service/SlurmClusterService.java
+++ b/src/main/java/org/apache/airavata/compute/service/ClusterService.java
@@ -1,11 +1,11 @@
package org.apache.airavata.compute.service;
import java.util.List;
-import org.apache.airavata.compute.dto.SlurmClusterRequestDto;
-import org.apache.airavata.compute.dto.SlurmClusterResponseDto;
-import org.apache.airavata.compute.mapper.SlurmClusterMapper;
-import org.apache.airavata.compute.model.SlurmClusterEntity;
-import org.apache.airavata.compute.repository.SlurmClusterRepository;
+import org.apache.airavata.compute.dto.ClusterRequestDto;
+import org.apache.airavata.compute.dto.ClusterResponseDto;
+import org.apache.airavata.compute.mapper.ClusterMapper;
+import org.apache.airavata.compute.model.ClusterEntity;
+import org.apache.airavata.compute.repository.ClusterRepository;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@@ -22,37 +22,37 @@ import org.springframework.web.server.ResponseStatusException;
* <p>Deleting a cluster cascades to its partitions, which are owned by it.
*/
@Service
-public class SlurmClusterService {
+public class ClusterService {
- private final SlurmClusterRepository clusterRepository;
- private final SlurmClusterMapper mapper;
+ private final ClusterRepository clusterRepository;
+ private final ClusterMapper mapper;
- public SlurmClusterService(SlurmClusterRepository clusterRepository, SlurmClusterMapper mapper) {
+ public ClusterService(ClusterRepository clusterRepository, ClusterMapper mapper) {
this.clusterRepository = clusterRepository;
this.mapper = mapper;
}
@Transactional(readOnly = true)
- public List<SlurmClusterResponseDto> getAllClusters() {
+ public List<ClusterResponseDto> getAllClusters() {
return clusterRepository.findAll().stream().map(mapper::toResponseDto).toList();
}
@Transactional(readOnly = true)
- public SlurmClusterResponseDto getCluster(String clusterId) {
+ public ClusterResponseDto getCluster(String clusterId) {
return mapper.toResponseDto(findOrThrow(clusterId));
}
@PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
@Transactional
- public SlurmClusterResponseDto createCluster(SlurmClusterRequestDto request) {
- SlurmClusterEntity entity = mapper.toEntity(request);
+ public ClusterResponseDto createCluster(ClusterRequestDto request) {
+ ClusterEntity entity = mapper.toEntity(request);
return mapper.toResponseDto(clusterRepository.save(entity));
}
@PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
@Transactional
- public SlurmClusterResponseDto updateCluster(String clusterId, SlurmClusterRequestDto request) {
- SlurmClusterEntity entity = findOrThrow(clusterId);
+ public ClusterResponseDto updateCluster(String clusterId, ClusterRequestDto request) {
+ ClusterEntity entity = findOrThrow(clusterId);
mapper.updateEntity(request, entity);
return mapper.toResponseDto(clusterRepository.save(entity));
}
@@ -63,7 +63,7 @@ public class SlurmClusterService {
clusterRepository.delete(findOrThrow(clusterId));
}
- private SlurmClusterEntity findOrThrow(String clusterId) {
+ private ClusterEntity findOrThrow(String clusterId) {
return clusterRepository
.findById(clusterId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Cluster not found: " + clusterId));
diff --git a/src/main/java/org/apache/airavata/data/dto/SCPDataRequestDto.java b/src/main/java/org/apache/airavata/data/dto/SCPDataRequestDto.java
new file mode 100644
index 0000000000..f9b5e036a8
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/dto/SCPDataRequestDto.java
@@ -0,0 +1,68 @@
+package org.apache.airavata.data.dto;
+
+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * Create/update payload for an SCP data registration.
+ *
+ * <p>There is no {@code ownerId} field: ownership is derived from the caller's access
+ * token, never from client input, so a caller cannot register data on another user's
+ * behalf. There is no {@code provisionStatus} field either: that is lifecycle state
+ * managed by {@code SCPDataService}, not something a client sets directly.
+ */
+public class SCPDataRequestDto {
+
+ @NotBlank(message = "Data name cannot be blank")
+ private String dataName;
+
+ private String dataDescription;
+
+ @NotBlank(message = "isFile cannot be blank")
+ private String isFile;
+
+ @NotBlank(message = "Path cannot be blank")
+ private String path;
+
+ @NotBlank(message = "Slurm cluster credential id cannot be blank")
+ private String slurmClusterCredentialId;
+
+ public String getDataName() {
+ return dataName;
+ }
+
+ public void setDataName(String dataName) {
+ this.dataName = dataName;
+ }
+
+ public String getDataDescription() {
+ return dataDescription;
+ }
+
+ public void setDataDescription(String dataDescription) {
+ this.dataDescription = dataDescription;
+ }
+
+ public String getIsFile() {
+ return isFile;
+ }
+
+ public void setIsFile(String isFile) {
+ this.isFile = isFile;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getSlurmClusterCredentialId() {
+ return slurmClusterCredentialId;
+ }
+
+ public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
+ this.slurmClusterCredentialId = slurmClusterCredentialId;
+ }
+}
diff --git a/src/main/java/org/apache/airavata/data/dto/SCPDataResponseDto.java b/src/main/java/org/apache/airavata/data/dto/SCPDataResponseDto.java
new file mode 100644
index 0000000000..0024b43888
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/dto/SCPDataResponseDto.java
@@ -0,0 +1,80 @@
+package org.apache.airavata.data.dto;
+
+import org.apache.airavata.data.model.DataProvisionStatus;
+
+/** Read view of an SCP data registration. */
+public class SCPDataResponseDto {
+
+ private String dataId;
+ private String dataName;
+ private String dataDescription;
+ private String isFile;
+ private String path;
+ private String slurmClusterCredentialId;
+ private DataProvisionStatus provisionStatus;
+ private String ownerId;
+
+ public String getDataId() {
+ return dataId;
+ }
+
+ public void setDataId(String dataId) {
+ this.dataId = dataId;
+ }
+
+ public String getDataName() {
+ return dataName;
+ }
+
+ public void setDataName(String dataName) {
+ this.dataName = dataName;
+ }
+
+ public String getDataDescription() {
+ return dataDescription;
+ }
+
+ public void setDataDescription(String dataDescription) {
+ this.dataDescription = dataDescription;
+ }
+
+ public String getIsFile() {
+ return isFile;
+ }
+
+ public void setIsFile(String isFile) {
+ this.isFile = isFile;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getSlurmClusterCredentialId() {
+ return slurmClusterCredentialId;
+ }
+
+ public void setSlurmClusterCredentialId(String slurmClusterCredentialId) {
+ this.slurmClusterCredentialId = slurmClusterCredentialId;
+ }
+
+ public DataProvisionStatus getProvisionStatus() {
+ return provisionStatus;
+ }
+
+ public void setProvisionStatus(DataProvisionStatus provisionStatus) {
+ this.provisionStatus = provisionStatus;
+ }
+
+ public String getOwnerId() {
+ return ownerId;
+ }
+
+ public void setOwnerId(String ownerId) {
+ this.ownerId = ownerId;
+ }
+}
diff --git a/src/main/java/org/apache/airavata/data/mapper/SCPDataMapper.java b/src/main/java/org/apache/airavata/data/mapper/SCPDataMapper.java
new file mode 100644
index 0000000000..47a849fb22
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/mapper/SCPDataMapper.java
@@ -0,0 +1,37 @@
+package org.apache.airavata.data.mapper;
+
+import org.apache.airavata.data.dto.SCPDataRequestDto;
+import org.apache.airavata.data.dto.SCPDataResponseDto;
+import org.apache.airavata.data.model.SCPDataEntity;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.ReportingPolicy;
+
+/**
+ * Entity/DTO conversion for SCP data registrations.
+ *
+ * <p>The Slurm cluster credential and the owner are associations resolved by
+ * {@code SCPDataService} from the request DTO's id and the caller's access token, so
+ * neither is ever mapped straight off the request. {@code provisionStatus} is lifecycle
+ * state the service manages directly, so it is ignored here too.
+ */
+@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface SCPDataMapper {
+
+ @Mapping(target = "slurmClusterCredentialId", source = "slurmClusterCredential.clusterCredentialId")
+ @Mapping(target = "ownerId", source = "owner.userId")
+ SCPDataResponseDto toResponseDto(SCPDataEntity entity);
+
+ @Mapping(target = "dataId", ignore = true)
+ @Mapping(target = "slurmClusterCredential", ignore = true)
+ @Mapping(target = "owner", ignore = true)
+ @Mapping(target = "provisionStatus", ignore = true)
+ SCPDataEntity toEntity(SCPDataRequestDto dto);
+
+ @Mapping(target = "dataId", ignore = true)
+ @Mapping(target = "slurmClusterCredential", ignore = true)
+ @Mapping(target = "owner", ignore = true)
+ @Mapping(target = "provisionStatus", ignore = true)
+ void updateEntity(SCPDataRequestDto dto, @MappingTarget SCPDataEntity entity);
+}
diff --git a/src/main/java/org/apache/airavata/data/model/DataProvisionStatus.java b/src/main/java/org/apache/airavata/data/model/DataProvisionStatus.java
new file mode 100644
index 0000000000..249cae9e0d
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/model/DataProvisionStatus.java
@@ -0,0 +1,10 @@
+package org.apache.airavata.data.model;
+
+public enum DataProvisionStatus {
+ REGISTERD,
+ PROVISIONING,
+ PROVISIONED,
+ DEPROVISIONING,
+ DEPROVISIONED,
+ FAILED
+}
diff --git a/src/main/java/org/apache/airavata/data/model/SCPDataEntity.java b/src/main/java/org/apache/airavata/data/model/SCPDataEntity.java
new file mode 100644
index 0000000000..0be97ab0db
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/model/SCPDataEntity.java
@@ -0,0 +1,102 @@
+package org.apache.airavata.data.model;
+
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.apache.airavata.iam.model.UserEntity;
+
+import jakarta.persistence.Entity;
+
+@Entity
+public class SCPDataEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ private String dataId;
+
+ private String dataName;
+ private String dataDescription;
+ private String isFile;
+ private String path;
+
+ @ManyToOne
+ @JoinColumn(
+ name = "slurm_cluster_credential_id",
+ foreignKey = @ForeignKey(name = "fk_scp_data_slurm_cluster_credential"))
+ private ClusterCredentialEntity slurmClusterCredential;
+
+ private DataProvisionStatus provisionStatus;
+
+ @ManyToOne
+ @JoinColumn(name = "user_id", foreignKey = @ForeignKey(name = "fk_scp_data_user"))
+ private UserEntity owner;
+
+ public ClusterCredentialEntity getSlurmClusterCredential() {
+ return slurmClusterCredential;
+ }
+
+ public void setSlurmClusterCredential(ClusterCredentialEntity slurmClusterCredential) {
+ this.slurmClusterCredential = slurmClusterCredential;
+ }
+
+ public UserEntity getOwner() {
+ return owner;
+ }
+
+ public void setOwner(UserEntity owner) {
+ this.owner = owner;
+ }
+
+ public String getDataId() {
+ return dataId;
+ }
+
+ public void setDataId(String dataId) {
+ this.dataId = dataId;
+ }
+
+ public String getDataName() {
+ return dataName;
+ }
+
+ public void setDataName(String dataName) {
+ this.dataName = dataName;
+ }
+
+ public String getDataDescription() {
+ return dataDescription;
+ }
+
+ public void setDataDescription(String dataDescription) {
+ this.dataDescription = dataDescription;
+ }
+
+ public String getIsFile() {
+ return isFile;
+ }
+
+ public void setIsFile(String isFile) {
+ this.isFile = isFile;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public DataProvisionStatus getProvisionStatus() {
+ return provisionStatus;
+ }
+
+ public void setProvisionStatus(DataProvisionStatus provisionStatus) {
+ this.provisionStatus = provisionStatus;
+ }
+}
diff --git a/src/main/java/org/apache/airavata/data/repository/SCPDataRepository.java b/src/main/java/org/apache/airavata/data/repository/SCPDataRepository.java
new file mode 100644
index 0000000000..10ce4d8e50
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/repository/SCPDataRepository.java
@@ -0,0 +1,12 @@
+package org.apache.airavata.data.repository;
+
+import java.util.List;
+import org.apache.airavata.data.model.SCPDataEntity;
+import org.springframework.data.repository.ListCrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface SCPDataRepository extends ListCrudRepository<SCPDataEntity, String> {
+
+ List<SCPDataEntity> findByOwner_UserId(String userId);
+}
diff --git a/src/main/java/org/apache/airavata/data/service/SCPDataService.java b/src/main/java/org/apache/airavata/data/service/SCPDataService.java
new file mode 100644
index 0000000000..a36969129a
--- /dev/null
+++ b/src/main/java/org/apache/airavata/data/service/SCPDataService.java
@@ -0,0 +1,138 @@
+package org.apache.airavata.data.service;
+
+import java.util.List;
+import org.apache.airavata.compute.model.ClusterCredentialEntity;
+import org.apache.airavata.compute.repository.ClusterCredentialRepository;
+import org.apache.airavata.data.dto.SCPDataRequestDto;
+import org.apache.airavata.data.dto.SCPDataResponseDto;
+import org.apache.airavata.data.mapper.SCPDataMapper;
+import org.apache.airavata.data.model.DataProvisionStatus;
+import org.apache.airavata.data.model.SCPDataEntity;
+import org.apache.airavata.data.repository.SCPDataRepository;
+import org.apache.airavata.iam.model.UserEntity;
+import org.apache.airavata.iam.repository.UserRepository;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.server.ResponseStatusException;
+
+/**
+ * CRUD for SCP data registrations.
+ *
+ * <p>Ownership is never taken from client input: {@code createData} derives the owning
+ * user from the caller's access token. Single-record reads and all writes are restricted
+ * to the owning user or an admin, matching the model used by
+ * {@code ClusterCredentialService} — a data registration is a per-user resource, not
+ * a shared, organization-level one.
+ */
+@Service
+public class SCPDataService {
+
+ private final SCPDataRepository dataRepository;
+ private final ClusterCredentialRepository credentialRepository;
+ private final UserRepository userRepository;
+ private final SCPDataMapper mapper;
+
+ public SCPDataService(
+ SCPDataRepository dataRepository,
+ ClusterCredentialRepository credentialRepository,
+ UserRepository userRepository,
+ SCPDataMapper mapper) {
+ this.dataRepository = dataRepository;
+ this.credentialRepository = credentialRepository;
+ this.userRepository = userRepository;
+ this.mapper = mapper;
+ }
+
+ /** Lists every data registration across every user. */
+ @PreAuthorize("hasAnyAuthority('ADMIN', 'SUPER_ADMIN')")
+ @Transactional(readOnly = true)
+ public List<SCPDataResponseDto> getAllData() {
+ return dataRepository.findAll().stream().map(mapper::toResponseDto).toList();
+ }
+
+ /** Lists the caller's own data registrations. */
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
+ public List<SCPDataResponseDto> getMyData() {
+ String userId = resolveCurrentUser().getUserId();
+ return dataRepository.findByOwner_UserId(userId).stream().map(mapper::toResponseDto).toList();
+ }
+
+ @Transactional(readOnly = true)
+ public SCPDataResponseDto getData(String id) {
+ SCPDataEntity entity = findOrThrow(id);
+ requireSelfOrAdmin(entity);
+ return mapper.toResponseDto(entity);
+ }
+
+ /** Any authenticated caller may register data — this is a self-service action. */
+ @PreAuthorize("isAuthenticated()")
+ @Transactional
+ public SCPDataResponseDto createData(SCPDataRequestDto request) {
+ SCPDataEntity entity = mapper.toEntity(request);
+ entity.setSlurmClusterCredential(resolveCredential(request.getSlurmClusterCredentialId()));
+ entity.setOwner(resolveCurrentUser());
+ entity.setProvisionStatus(DataProvisionStatus.REGISTERD);
+ return mapper.toResponseDto(dataRepository.save(entity));
+ }
+
+ /** Ownership is immutable — only the descriptive fields and credential can change. */
+ @Transactional
+ public SCPDataResponseDto updateData(String id, SCPDataRequestDto request) {
+ SCPDataEntity entity = findOrThrow(id);
+ requireSelfOrAdmin(entity);
+ mapper.updateEntity(request, entity);
+ entity.setSlurmClusterCredential(resolveCredential(request.getSlurmClusterCredentialId()));
+ return mapper.toResponseDto(dataRepository.save(entity));
+ }
+
+ @Transactional
+ public void deleteData(String id) {
+ SCPDataEntity entity = findOrThrow(id);
+ requireSelfOrAdmin(entity);
+ dataRepository.delete(entity);
+ }
+
+ private SCPDataEntity findOrThrow(String id) {
+ return dataRepository
+ .findById(id)
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "SCP data not found: " + id));
+ }
+
+ private ClusterCredentialEntity resolveCredential(String credentialId) {
+ return credentialRepository
+ .findById(credentialId)
+ .orElseThrow(() -> new ResponseStatusException(
+ HttpStatus.NOT_FOUND, "Slurm cluster credential not found: " + credentialId));
+ }
+
+ /**
+ * Resolves the caller's {@link UserEntity} from the principal name that
+ * {@code UserRoleOpaqueTokenIntrospector} put on the security context — the same
+ * identifier used as {@code UserEntity.userId} (see {@code UserService.getUserById}'s
+ * "isSelf" check for the other place this equivalence is relied on).
+ */
+ private UserEntity resolveCurrentUser() {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ String username = authentication.getName();
+ return userRepository
+ .findById(username)
+ .orElseThrow(() -> new ResponseStatusException(
+ HttpStatus.NOT_FOUND, "No user record found for authenticated principal: " + username));
+ }
+
+ private void requireSelfOrAdmin(SCPDataEntity entity) {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ boolean isSelf = entity.getOwner() != null && authentication.getName().equals(entity.getOwner().getUserId());
+ boolean isAdmin = authentication.getAuthorities().stream()
+ .anyMatch(auth -> auth.getAuthority().equals("ADMIN") || auth.getAuthority().equals("SUPER_ADMIN"));
+ if (!isSelf && !isAdmin) {
+ throw new AccessDeniedException("Access denied: you may only access your own SCP data");
+ }
+ }
+}