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 2025/11/11 21:20:19 UTC
(airavata) branch storage-directory-size-api created (now 1782c7ff33)
This is an automated email from the ASF dual-hosted git repository.
dimuthuupe pushed a change to branch storage-directory-size-api
in repository https://gitbox.apache.org/repos/asf/airavata.git
at 1782c7ff33 Adding storage directory size listing api to python sdk
This branch includes the following new commits:
new 8a0469eb96 Enabling storage directory size listing api
new 1782c7ff33 Adding storage directory size listing api to python sdk
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(airavata) 01/02: Enabling storage directory size listing api
Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dimuthuupe pushed a commit to branch storage-directory-size-api
in repository https://gitbox.apache.org/repos/asf/airavata.git
commit 8a0469eb961611482d61ee1831c201877a58ebbe
Author: DImuthuUpe <di...@gmail.com>
AuthorDate: Tue Nov 11 16:16:21 2025 -0500
Enabling storage directory size listing api
---
.../apache/airavata/agents/api/AgentAdaptor.java | 4 ++
.../api/server/handler/AiravataServerHandler.java | 76 ++++++++++++++++++++++
.../airavata/helix/adaptor/SSHJAgentAdaptor.java | 49 ++++++++++++++
.../airavata/helix/agent/ssh/SshAgentAdaptor.java | 7 ++
.../airavata-apis/airavata_api.thrift | 52 ++++++++++-----
.../data-models/storage_resource_model.thrift | 11 ++++
6 files changed, 181 insertions(+), 18 deletions(-)
diff --git a/airavata-api/src/main/java/org/apache/airavata/agents/api/AgentAdaptor.java b/airavata-api/src/main/java/org/apache/airavata/agents/api/AgentAdaptor.java
index 245cad8c69..fd2e5d79b4 100644
--- a/airavata-api/src/main/java/org/apache/airavata/agents/api/AgentAdaptor.java
+++ b/airavata-api/src/main/java/org/apache/airavata/agents/api/AgentAdaptor.java
@@ -22,6 +22,8 @@ package org.apache.airavata.agents.api;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
+
+import org.apache.airavata.model.appcatalog.storageresource.StorageDirectoryInfo;
import org.apache.airavata.model.appcatalog.storageresource.StorageVolumeInfo;
/**
@@ -59,4 +61,6 @@ public interface AgentAdaptor {
FileMetadata getFileMetadata(String remoteFile) throws AgentException;
StorageVolumeInfo getStorageVolumeInfo(String location) throws AgentException;
+
+ StorageDirectoryInfo getStorageDirectoryInfo(String location) throws AgentException;
}
diff --git a/airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java b/airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
index c8a89566b3..4da1eb7494 100644
--- a/airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
+++ b/airavata-api/src/main/java/org/apache/airavata/api/server/handler/AiravataServerHandler.java
@@ -59,6 +59,7 @@ import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeRes
import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupResourceProfile;
import org.apache.airavata.model.appcatalog.parser.Parser;
import org.apache.airavata.model.appcatalog.parser.ParsingTemplate;
+import org.apache.airavata.model.appcatalog.storageresource.StorageDirectoryInfo;
import org.apache.airavata.model.appcatalog.storageresource.StorageResourceDescription;
import org.apache.airavata.model.appcatalog.storageresource.StorageVolumeInfo;
import org.apache.airavata.model.appcatalog.userresourceprofile.UserComputeResourcePreference;
@@ -3919,6 +3920,81 @@ public class AiravataServerHandler implements Airavata.Iface {
}
}
+ @Override
+ @SecurityCheck
+ public StorageDirectoryInfo getStorageDirectoryInfo(AuthzToken authzToken, String resourceId, String location)
+ throws TException {
+ String gatewayId = authzToken.getClaimsMap().get(Constants.GATEWAY_ID);
+ String userId = authzToken.getClaimsMap().get(Constants.USER_NAME);
+ RegistryService.Client regClient = registryClientPool.getResource();
+ StorageInfoContext context;
+
+ try {
+ Optional<ComputeResourceDescription> computeResourceOp = Optional.empty();
+ try {
+ ComputeResourceDescription computeResource = regClient.getComputeResource(resourceId);
+ if (computeResource != null) {
+ computeResourceOp = Optional.of(computeResource);
+ }
+ } catch (TApplicationException e) {
+ // TApplicationException with "unknown result" means resource not found (null return for non-nullable
+ // type)
+ logger.debug("Compute resource {} not found (TApplicationException): {}", resourceId, e.getMessage());
+ }
+
+ Optional<StorageResourceDescription> storageResourceOp = Optional.empty();
+ if (computeResourceOp.isEmpty()) {
+ try {
+ StorageResourceDescription storageResource = regClient.getStorageResource(resourceId);
+ if (storageResource != null) {
+ storageResourceOp = Optional.of(storageResource);
+ }
+ } catch (TApplicationException e) {
+ // TApplicationException with "unknown result" means resource not found (null return for
+ // non-nullable type)
+ logger.debug(
+ "Storage resource {} not found (TApplicationException): {}", resourceId, e.getMessage());
+ }
+ }
+
+ if (computeResourceOp.isEmpty() && storageResourceOp.isEmpty()) {
+ logger.error(
+ "Resource with ID {} not found as either compute resource or storage resource", resourceId);
+ throw new InvalidRequestException("Resource with ID '" + resourceId
+ + "' not found as either compute resource or storage resource");
+ }
+
+ if (computeResourceOp.isPresent()) {
+ logger.debug("Found compute resource with ID {}. Resolving login username and credentials", resourceId);
+ context = resolveComputeStorageInfoContext(authzToken, gatewayId, userId, resourceId);
+ } else {
+ logger.debug("Found storage resource with ID {}. Resolving login username and credentials", resourceId);
+ context = resolveStorageStorageInfoContext(authzToken, gatewayId, userId, resourceId);
+ }
+
+ registryClientPool.returnResource(regClient);
+ regClient = null;
+
+ return context.adaptor.getStorageDirectoryInfo(location);
+
+ } catch (InvalidRequestException | AiravataClientException e) {
+ if (regClient != null) {
+ registryClientPool.returnResource(regClient);
+ }
+ logger.error("Error while retrieving storage resource.", e);
+ throw e;
+
+ } catch (Exception e) {
+ logger.error("Error while retrieving storage volume info for resource {}", resourceId, e);
+ registryClientPool.returnBrokenResource(regClient);
+
+ AiravataSystemException exception = new AiravataSystemException();
+ exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
+ exception.setMessage("Error while retrieving storage volume info. More info: " + e.getMessage());
+ throw exception;
+ }
+ }
+
/**
* Add a Local Job Submission details to a compute resource
* App catalog will return a jobSubmissionInterfaceId which will be added to the jobSubmissionInterfaces.
diff --git a/airavata-api/src/main/java/org/apache/airavata/helix/adaptor/SSHJAgentAdaptor.java b/airavata-api/src/main/java/org/apache/airavata/helix/adaptor/SSHJAgentAdaptor.java
index 9e9caaefc1..2845afb1ef 100644
--- a/airavata-api/src/main/java/org/apache/airavata/helix/adaptor/SSHJAgentAdaptor.java
+++ b/airavata-api/src/main/java/org/apache/airavata/helix/adaptor/SSHJAgentAdaptor.java
@@ -51,6 +51,7 @@ import org.apache.airavata.model.appcatalog.computeresource.ComputeResourceDescr
import org.apache.airavata.model.appcatalog.computeresource.JobSubmissionInterface;
import org.apache.airavata.model.appcatalog.computeresource.JobSubmissionProtocol;
import org.apache.airavata.model.appcatalog.computeresource.SSHJobSubmission;
+import org.apache.airavata.model.appcatalog.storageresource.StorageDirectoryInfo;
import org.apache.airavata.model.appcatalog.storageresource.StorageVolumeInfo;
import org.apache.airavata.model.credential.store.SSHCredential;
import org.slf4j.Logger;
@@ -645,6 +646,54 @@ public class SSHJAgentAdaptor implements AgentAdaptor {
}
}
+ @Override
+ public StorageDirectoryInfo getStorageDirectoryInfo(String location) throws AgentException {
+ try {
+ String targetLocation = location;
+ if (targetLocation == null || targetLocation.trim().isEmpty()) {
+ CommandOutput homeOutput = executeCommand("echo $HOME", null);
+
+ if (homeOutput.getExitCode() != 0
+ || homeOutput.getStdOut() == null
+ || homeOutput.getStdOut().trim().isEmpty()) {
+ logger.error("Failed to determine user's home directory: {}", homeOutput.getStdError());
+ throw new AgentException("Failed to determine user's home directory: " + homeOutput.getStdError());
+ }
+ targetLocation = homeOutput.getStdOut().trim();
+ }
+
+ // Escape location to prevent command injection and handle spaces
+ String escapedLocation = targetLocation.replace("'", "'\"'\"'");
+ String duKBytesCommand = "du -sk '" + escapedLocation + "'";
+
+ CommandOutput duKBytesOutput = executeCommand(duKBytesCommand, null);
+
+ if (duKBytesOutput.getExitCode() != 0) {
+ logger.error(
+ "Failed to execute du -sk command for location {}: {}",
+ targetLocation,
+ duKBytesOutput.getStdError());
+ throw new AgentException("Failed to execute du -sk command for location " + targetLocation + ": "
+ + duKBytesOutput.getStdError());
+ }
+
+ String outputKbStr = duKBytesOutput.getStdOut().trim();
+ logger.info("OutputKbStr: for du -ku {} is {}", location, outputKbStr);
+ String numberOfKBytesStr = outputKbStr.split(" ")[0];
+
+ long numberOfKBytes = Long.parseLong(numberOfKBytesStr);
+
+ StorageDirectoryInfo storageDirectoryInfo = new StorageDirectoryInfo();
+ storageDirectoryInfo.setTotalSizeBytes(numberOfKBytes * 1024);
+ storageDirectoryInfo.setTotalSize(numberOfKBytes + "kb");
+ return storageDirectoryInfo;
+
+ } catch (Exception e) {
+ logger.error("Error while retrieving storage directory info for location " + location, e);
+ throw new AgentException("Error while retrieving storage directory info for location " + location, e);
+ }
+ }
+
private StorageVolumeInfo parseDfOutput(String dfHumanOutput, String dfBytesOutput, String targetLocation)
throws AgentException {
try {
diff --git a/airavata-api/src/main/java/org/apache/airavata/helix/agent/ssh/SshAgentAdaptor.java b/airavata-api/src/main/java/org/apache/airavata/helix/agent/ssh/SshAgentAdaptor.java
index 40096595b2..8ee4237fd7 100644
--- a/airavata-api/src/main/java/org/apache/airavata/helix/agent/ssh/SshAgentAdaptor.java
+++ b/airavata-api/src/main/java/org/apache/airavata/helix/agent/ssh/SshAgentAdaptor.java
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.UUID;
import org.apache.airavata.agents.api.*;
import org.apache.airavata.model.appcatalog.computeresource.*;
+import org.apache.airavata.model.appcatalog.storageresource.StorageDirectoryInfo;
import org.apache.airavata.model.appcatalog.storageresource.StorageVolumeInfo;
import org.apache.airavata.model.credential.store.SSHCredential;
import org.slf4j.Logger;
@@ -547,6 +548,12 @@ public class SshAgentAdaptor implements AgentAdaptor {
"Operation not supported by SshAgentAdaptor. Use SSHJAgentAdaptor instead.");
}
+ @Override
+ public StorageDirectoryInfo getStorageDirectoryInfo(String location) throws AgentException {
+ throw new UnsupportedOperationException(
+ "Operation not supported by SshAgentAdaptor. Use SSHJAgentAdaptor instead.");
+ }
+
private static class DefaultUserInfo implements UserInfo, UIKeyboardInteractive {
private String userName;
diff --git a/thrift-interface-descriptions/airavata-apis/airavata_api.thrift b/thrift-interface-descriptions/airavata-apis/airavata_api.thrift
index c5a95d325d..964a55ceb5 100644
--- a/thrift-interface-descriptions/airavata-apis/airavata_api.thrift
+++ b/thrift-interface-descriptions/airavata-apis/airavata_api.thrift
@@ -20,7 +20,7 @@
/**
* Application Programming Interface definition for Apache Airavata Services.
- * this parent thrift file is contains all service interfaces. The data models are
+ * this parent thrift file is contains all service interfaces. The data models are
* described in respective thrift files.
*/
@@ -102,7 +102,7 @@ service Airavata extends base_api.BaseAPI {
*
* @param gateway
* The gateway data model.
- *
+ *
* @return gatewayId
* Th unique identifier of the newly registered gateway.
*
@@ -673,13 +673,13 @@ service Airavata extends base_api.BaseAPI {
*
* @throws org.apache.airavata.model.error.InvalidRequestException
* For any incorrect forming of the request itself.
- *
+ *
* @throws org.apache.airavata.model.error.ExperimentNotFoundException
* If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
- *
+ *
* @throws org.apache.airavata.model.error.AiravataClientException
* The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
- *
+ *
* UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
* step, then Airavata Registry will not have a provenance area setup. The client has to follow
* gateway registration steps and retry this request.
@@ -811,13 +811,13 @@ service Airavata extends base_api.BaseAPI {
*
* @throws org.apache.airavata.model.error.InvalidRequestException
* For any incorrect forming of the request itself.
- *
+ *
* @throws org.apache.airavata.model.error.ExperimentNotFoundException
* If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
- *
+ *
* @throws org.apache.airavata.model.error.AiravataClientException
* The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
- *
+ *
* UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
* step, then Airavata Registry will not have a provenance area setup. The client has to follow
* gateway registration steps and retry this request.
@@ -888,13 +888,13 @@ service Airavata extends base_api.BaseAPI {
*
* @throws org.apache.airavata.model.error.InvalidRequestException
* For any incorrect forming of the request itself.
- *
+ *
* @throws org.apache.airavata.model.error.ExperimentNotFoundException
* If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
- *
+ *
* @throws org.apache.airavata.model.error.AiravataClientException
* The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
- *
+ *
* UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
* step, then Airavata Registry will not have a provenance area setup. The client has to follow
* gateway registration steps and retry this request.
@@ -1076,7 +1076,7 @@ service Airavata extends base_api.BaseAPI {
*
* Clone an Existing Experiment
* Existing specified experiment is cloned and a new name is provided. A copy of the experiment configuration is made and is persisted with new metadata.
- * The client has to subsequently update this configuration if needed and launch the cloned experiment.
+ * The client has to subsequently update this configuration if needed and launch the cloned experiment.
*
* @param newExperimentName
* experiment name that should be used in the cloned experiment
@@ -1094,13 +1094,13 @@ service Airavata extends base_api.BaseAPI {
*
* @throws org.apache.airavata.model.error.InvalidRequestException
* For any incorrect forming of the request itself.
- *
+ *
* @throws org.apache.airavata.model.error.ExperimentNotFoundException
* If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
- *
+ *
* @throws org.apache.airavata.model.error.AiravataClientException
* The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
- *
+ *
* UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
* step, then Airavata Registry will not have a provenance area setup. The client has to follow
* gateway registration steps and retry this request.
@@ -1196,13 +1196,13 @@ service Airavata extends base_api.BaseAPI {
*
* @throws org.apache.airavata.model.error.InvalidRequestException
* For any incorrect forming of the request itself.
- *
+ *
* @throws org.apache.airavata.model.error.ExperimentNotFoundException
* If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
- *
+ *
* @throws org.apache.airavata.model.error.AiravataClientException
* The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
- *
+ *
* UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
* step, then Airavata Registry will not have a provenance area setup. The client has to follow
* gateway registration steps and retry this request.
@@ -3627,6 +3627,22 @@ service Airavata extends base_api.BaseAPI {
3: airavata_errors.AiravataSystemException ase,
4: airavata_errors.AuthorizationException ae)
+/**
+ * Get storage directory information for a compute or storage resource.
+ *
+ * @param authzToken
+ * @param resourceId Can be either a compute resource ID or storage resource ID
+ * @param location Optional path/mount point. If null/empty, defaults to user's home directory ($HOME)
+ * @return StorageDirectoryInfo containing directory size information
+ */
+ storage_resource_model.StorageDirectoryInfo getStorageDirectoryInfo(1: required security_model.AuthzToken authzToken,
+ 2: required string resourceId,
+ 3: optional string location)
+ throws (1: airavata_errors.InvalidRequestException ire,
+ 2: airavata_errors.AiravataClientException ace,
+ 3: airavata_errors.AiravataSystemException ase,
+ 4: airavata_errors.AuthorizationException ae)
+
//
//End of API
}
diff --git a/thrift-interface-descriptions/data-models/storage_resource_model.thrift b/thrift-interface-descriptions/data-models/storage_resource_model.thrift
index 8b41079379..9d6fa4d70e 100644
--- a/thrift-interface-descriptions/data-models/storage_resource_model.thrift
+++ b/thrift-interface-descriptions/data-models/storage_resource_model.thrift
@@ -79,3 +79,14 @@ struct StorageVolumeInfo {
8: required string mountPoint,
9: optional string filesystemType,
}
+
+/**
+ * Provides Directory Size Information of a given storage
+ *
+ * totalSize: Total size in human-readable format (e.g., "100G", "500M")
+ * totalSizeBytes: Total size in bytes
+ */
+struct StorageDirectoryInfo {
+ 1: required string totalSize,
+ 2: required i64 totalSizeBytes,
+}
(airavata) 02/02: Adding storage directory size listing api to python sdk
Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
dimuthuupe pushed a commit to branch storage-directory-size-api
in repository https://gitbox.apache.org/repos/asf/airavata.git
commit 1782c7ff33a2ce0770fa5804fe4175b1e6d46dab
Author: DImuthuUpe <di...@gmail.com>
AuthorDate: Tue Nov 11 16:20:06 2025 -0500
Adding storage directory size listing api to python sdk
---
.../airavata/api/Airavata-remote | 7 +
.../airavata-python-sdk/airavata/api/Airavata.py | 325 ++++++++++++++++++++-
.../airavata-python-sdk/airavata/model/__init__.py | 1 -
.../model/appcatalog/storageresource/ttypes.py | 85 ++++++
4 files changed, 409 insertions(+), 9 deletions(-)
diff --git a/dev-tools/airavata-python-sdk/airavata/api/Airavata-remote b/dev-tools/airavata-python-sdk/airavata/api/Airavata-remote
index 173421d374..644d582be5 100755
--- a/dev-tools/airavata-python-sdk/airavata/api/Airavata-remote
+++ b/dev-tools/airavata-python-sdk/airavata/api/Airavata-remote
@@ -218,6 +218,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print(' bool removeParsingTemplate(AuthzToken authzToken, string templateId, string gatewayId)')
print(' listAllParsingTemplates(AuthzToken authzToken, string gatewayId)')
print(' StorageVolumeInfo getResourceStorageInfo(AuthzToken authzToken, string resourceId, string location)')
+ print(' StorageDirectoryInfo getStorageDirectoryInfo(AuthzToken authzToken, string resourceId, string location)')
print(' string getAPIVersion()')
print('')
sys.exit(0)
@@ -1462,6 +1463,12 @@ elif cmd == 'getResourceStorageInfo':
sys.exit(1)
pp.pprint(client.getResourceStorageInfo(eval(args[0]), args[1], args[2],))
+elif cmd == 'getStorageDirectoryInfo':
+ if len(args) != 3:
+ print('getStorageDirectoryInfo requires 3 args')
+ sys.exit(1)
+ pp.pprint(client.getStorageDirectoryInfo(eval(args[0]), args[1], args[2],))
+
elif cmd == 'getAPIVersion':
if len(args) != 0:
print('getAPIVersion requires 0 args')
diff --git a/dev-tools/airavata-python-sdk/airavata/api/Airavata.py b/dev-tools/airavata-python-sdk/airavata/api/Airavata.py
index f027db0933..89f1702a07 100644
--- a/dev-tools/airavata-python-sdk/airavata/api/Airavata.py
+++ b/dev-tools/airavata-python-sdk/airavata/api/Airavata.py
@@ -826,7 +826,7 @@ class Iface(airavata.base.api.BaseAPI.Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -914,7 +914,7 @@ class Iface(airavata.base.api.BaseAPI.Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -1127,7 +1127,7 @@ class Iface(airavata.base.api.BaseAPI.Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -1228,7 +1228,7 @@ class Iface(airavata.base.api.BaseAPI.Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -3859,6 +3859,23 @@ class Iface(airavata.base.api.BaseAPI.Iface):
"""
pass
+ def getStorageDirectoryInfo(self, authzToken: airavata.model.security.ttypes.AuthzToken, resourceId: str, location: str) -> airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo:
+ """
+ Get storage directory information for a compute or storage resource.
+
+ @param authzToken
+ @param resourceId Can be either a compute resource ID or storage resource ID
+ @param location Optional path/mount point. If null/empty, defaults to user's home directory ($HOME)
+ @return StorageDirectoryInfo containing directory size information
+
+ Parameters:
+ - authzToken
+ - resourceId
+ - location
+
+ """
+ pass
+
class Client(airavata.base.api.BaseAPI.Client, Iface):
def __init__(self, iprot, oprot=None):
@@ -5825,7 +5842,7 @@ class Client(airavata.base.api.BaseAPI.Client, Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -6034,7 +6051,7 @@ class Client(airavata.base.api.BaseAPI.Client, Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -6526,7 +6543,7 @@ class Client(airavata.base.api.BaseAPI.Client, Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -6705,7 +6722,7 @@ class Client(airavata.base.api.BaseAPI.Client, Iface):
@throws org.apache.airavata.model.error.AiravataClientException
The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
-
+
UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
step, then Airavata Registry will not have a provenance area setup. The client has to follow
gateway registration steps and retry this request.
@@ -14256,6 +14273,57 @@ class Client(airavata.base.api.BaseAPI.Client, Iface):
raise result.ae
raise TApplicationException(TApplicationException.MISSING_RESULT, "getResourceStorageInfo failed: unknown result")
+ def getStorageDirectoryInfo(self, authzToken: airavata.model.security.ttypes.AuthzToken, resourceId: str, location: str) -> airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo:
+ """
+ Get storage directory information for a compute or storage resource.
+
+ @param authzToken
+ @param resourceId Can be either a compute resource ID or storage resource ID
+ @param location Optional path/mount point. If null/empty, defaults to user's home directory ($HOME)
+ @return StorageDirectoryInfo containing directory size information
+
+ Parameters:
+ - authzToken
+ - resourceId
+ - location
+
+ """
+ self.send_getStorageDirectoryInfo(authzToken, resourceId, location)
+ return self.recv_getStorageDirectoryInfo()
+
+ def send_getStorageDirectoryInfo(self, authzToken: airavata.model.security.ttypes.AuthzToken, resourceId: str, location: str):
+ self._oprot.writeMessageBegin('getStorageDirectoryInfo', TMessageType.CALL, self._seqid)
+ args = getStorageDirectoryInfo_args()
+ args.authzToken = authzToken
+ args.resourceId = resourceId
+ args.location = location
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_getStorageDirectoryInfo(self) -> airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo:
+ iprot = self._iprot
+ (fname, mtype, rseqid) = iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(iprot)
+ iprot.readMessageEnd()
+ raise x
+ result = getStorageDirectoryInfo_result()
+ result.read(iprot)
+ iprot.readMessageEnd()
+ if result.success is not None:
+ return result.success
+ if result.ire is not None:
+ raise result.ire
+ if result.ace is not None:
+ raise result.ace
+ if result.ase is not None:
+ raise result.ase
+ if result.ae is not None:
+ raise result.ae
+ raise TApplicationException(TApplicationException.MISSING_RESULT, "getStorageDirectoryInfo failed: unknown result")
+
class Processor(airavata.base.api.BaseAPI.Processor, Iface, TProcessor):
def __init__(self, handler):
@@ -14454,6 +14522,7 @@ class Processor(airavata.base.api.BaseAPI.Processor, Iface, TProcessor):
self._processMap["removeParsingTemplate"] = Processor.process_removeParsingTemplate
self._processMap["listAllParsingTemplates"] = Processor.process_listAllParsingTemplates
self._processMap["getResourceStorageInfo"] = Processor.process_getResourceStorageInfo
+ self._processMap["getStorageDirectoryInfo"] = Processor.process_getStorageDirectoryInfo
self._on_message_begin = None
def on_message_begin(self, func):
@@ -21305,6 +21374,41 @@ class Processor(airavata.base.api.BaseAPI.Processor, Iface, TProcessor):
oprot.writeMessageEnd()
oprot.trans.flush()
+ def process_getStorageDirectoryInfo(self, seqid, iprot, oprot):
+ args = getStorageDirectoryInfo_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = getStorageDirectoryInfo_result()
+ try:
+ result.success = self._handler.getStorageDirectoryInfo(args.authzToken, args.resourceId, args.location)
+ msg_type = TMessageType.REPLY
+ except TTransport.TTransportException:
+ raise
+ except airavata.api.error.ttypes.InvalidRequestException as ire:
+ msg_type = TMessageType.REPLY
+ result.ire = ire
+ except airavata.api.error.ttypes.AiravataClientException as ace:
+ msg_type = TMessageType.REPLY
+ result.ace = ace
+ except airavata.api.error.ttypes.AiravataSystemException as ase:
+ msg_type = TMessageType.REPLY
+ result.ase = ase
+ except airavata.api.error.ttypes.AuthorizationException as ae:
+ msg_type = TMessageType.REPLY
+ result.ae = ae
+ except TApplicationException as ex:
+ logging.exception('TApplication exception in handler')
+ msg_type = TMessageType.EXCEPTION
+ result = ex
+ except Exception:
+ logging.exception('Unexpected exception in handler')
+ msg_type = TMessageType.EXCEPTION
+ result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+ oprot.writeMessageBegin("getStorageDirectoryInfo", msg_type, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
# HELPER FUNCTIONS AND STRUCTURES
@@ -61308,5 +61412,210 @@ getResourceStorageInfo_result.thrift_spec = (
(3, TType.STRUCT, 'ase', [airavata.api.error.ttypes.AiravataSystemException, None], None, ), # 3
(4, TType.STRUCT, 'ae', [airavata.api.error.ttypes.AuthorizationException, None], None, ), # 4
)
+
+
+class getStorageDirectoryInfo_args(object):
+ """
+ Attributes:
+ - authzToken
+ - resourceId
+ - location
+
+ """
+ thrift_spec: typing.Any = None
+
+
+ def __init__(self, authzToken: airavata.model.security.ttypes.AuthzToken = None, resourceId: str = None, location: typing.Optional[str] = None,):
+ self.authzToken: airavata.model.security.ttypes.AuthzToken = authzToken
+ self.resourceId: str = resourceId
+ self.location: typing.Optional[str] = location
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 1:
+ if ftype == TType.STRUCT:
+ self.authzToken = airavata.model.security.ttypes.AuthzToken()
+ self.authzToken.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.STRING:
+ self.resourceId = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
+ else:
+ iprot.skip(ftype)
+ elif fid == 3:
+ if ftype == TType.STRING:
+ self.location = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ self.validate()
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+ return
+ oprot.writeStructBegin('getStorageDirectoryInfo_args')
+ if self.authzToken is not None:
+ oprot.writeFieldBegin('authzToken', TType.STRUCT, 1)
+ self.authzToken.write(oprot)
+ oprot.writeFieldEnd()
+ if self.resourceId is not None:
+ oprot.writeFieldBegin('resourceId', TType.STRING, 2)
+ oprot.writeString(self.resourceId.encode('utf-8') if sys.version_info[0] == 2 else self.resourceId)
+ oprot.writeFieldEnd()
+ if self.location is not None:
+ oprot.writeFieldBegin('location', TType.STRING, 3)
+ oprot.writeString(self.location.encode('utf-8') if sys.version_info[0] == 2 else self.location)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ if self.authzToken is None:
+ raise TProtocolException(message='Required field authzToken is unset!')
+ if self.resourceId is None:
+ raise TProtocolException(message='Required field resourceId is unset!')
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
+all_structs.append(getStorageDirectoryInfo_args)
+getStorageDirectoryInfo_args.thrift_spec = (
+ None, # 0
+ (1, TType.STRUCT, 'authzToken', [airavata.model.security.ttypes.AuthzToken, None], None, ), # 1
+ (2, TType.STRING, 'resourceId', 'UTF8', None, ), # 2
+ (3, TType.STRING, 'location', 'UTF8', None, ), # 3
+)
+
+
+class getStorageDirectoryInfo_result(object):
+ """
+ Attributes:
+ - success
+ - ire
+ - ace
+ - ase
+ - ae
+
+ """
+ thrift_spec: typing.Any = None
+
+
+ def __init__(self, success: typing.Optional[airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo] = None, ire: typing.Optional[airavata.api.error.ttypes.InvalidRequestException] = None, ace: typing.Optional[airavata.api.error.ttypes.AiravataClientException] = None, ase: typing.Optional[airavata.api.error.ttypes.AiravataSystemException] = None, ae: typing.Optional[airavata.api.error.ttypes.AuthorizationException] = None,):
+ self.success: typing.Optional[airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo] = success
+ self.ire: typing.Optional[airavata.api.error.ttypes.InvalidRequestException] = ire
+ self.ace: typing.Optional[airavata.api.error.ttypes.AiravataClientException] = ace
+ self.ase: typing.Optional[airavata.api.error.ttypes.AiravataSystemException] = ase
+ self.ae: typing.Optional[airavata.api.error.ttypes.AuthorizationException] = ae
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 0:
+ if ftype == TType.STRUCT:
+ self.success = airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo()
+ self.success.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 1:
+ if ftype == TType.STRUCT:
+ self.ire = airavata.api.error.ttypes.InvalidRequestException.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.STRUCT:
+ self.ace = airavata.api.error.ttypes.AiravataClientException.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 3:
+ if ftype == TType.STRUCT:
+ self.ase = airavata.api.error.ttypes.AiravataSystemException.read(iprot)
+ else:
+ iprot.skip(ftype)
+ elif fid == 4:
+ if ftype == TType.STRUCT:
+ self.ae = airavata.api.error.ttypes.AuthorizationException.read(iprot)
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ self.validate()
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+ return
+ oprot.writeStructBegin('getStorageDirectoryInfo_result')
+ if self.success is not None:
+ oprot.writeFieldBegin('success', TType.STRUCT, 0)
+ self.success.write(oprot)
+ oprot.writeFieldEnd()
+ if self.ire is not None:
+ oprot.writeFieldBegin('ire', TType.STRUCT, 1)
+ self.ire.write(oprot)
+ oprot.writeFieldEnd()
+ if self.ace is not None:
+ oprot.writeFieldBegin('ace', TType.STRUCT, 2)
+ self.ace.write(oprot)
+ oprot.writeFieldEnd()
+ if self.ase is not None:
+ oprot.writeFieldBegin('ase', TType.STRUCT, 3)
+ self.ase.write(oprot)
+ oprot.writeFieldEnd()
+ if self.ae is not None:
+ oprot.writeFieldBegin('ae', TType.STRUCT, 4)
+ self.ae.write(oprot)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
+all_structs.append(getStorageDirectoryInfo_result)
+getStorageDirectoryInfo_result.thrift_spec = (
+ (0, TType.STRUCT, 'success', [airavata.model.appcatalog.storageresource.ttypes.StorageDirectoryInfo, None], None, ), # 0
+ (1, TType.STRUCT, 'ire', [airavata.api.error.ttypes.InvalidRequestException, None], None, ), # 1
+ (2, TType.STRUCT, 'ace', [airavata.api.error.ttypes.AiravataClientException, None], None, ), # 2
+ (3, TType.STRUCT, 'ase', [airavata.api.error.ttypes.AiravataSystemException, None], None, ), # 3
+ (4, TType.STRUCT, 'ae', [airavata.api.error.ttypes.AuthorizationException, None], None, ), # 4
+)
fix_spec(all_structs)
del all_structs
diff --git a/dev-tools/airavata-python-sdk/airavata/model/__init__.py b/dev-tools/airavata-python-sdk/airavata/model/__init__.py
index adefd8e51f..e69de29bb2 100644
--- a/dev-tools/airavata-python-sdk/airavata/model/__init__.py
+++ b/dev-tools/airavata-python-sdk/airavata/model/__init__.py
@@ -1 +0,0 @@
-__all__ = ['ttypes', 'constants']
diff --git a/dev-tools/airavata-python-sdk/airavata/model/appcatalog/storageresource/ttypes.py b/dev-tools/airavata-python-sdk/airavata/model/appcatalog/storageresource/ttypes.py
index 5481af5ae1..6a929fddf4 100644
--- a/dev-tools/airavata-python-sdk/airavata/model/appcatalog/storageresource/ttypes.py
+++ b/dev-tools/airavata-python-sdk/airavata/model/appcatalog/storageresource/ttypes.py
@@ -351,6 +351,85 @@ class StorageVolumeInfo(object):
def __ne__(self, other):
return not (self == other)
+
+
+class StorageDirectoryInfo(object):
+ """
+ Provides Directory Size Information of a given storage
+
+ totalSize: Total size in human-readable format (e.g., "100G", "500M")
+ totalSizeBytes: Total size in bytes
+
+ Attributes:
+ - totalSize
+ - totalSizeBytes
+
+ """
+ thrift_spec: typing.Any = None
+
+
+ def __init__(self, totalSize: str = None, totalSizeBytes: int = None,):
+ self.totalSize: str = totalSize
+ self.totalSizeBytes: int = totalSizeBytes
+
+ def read(self, iprot):
+ if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
+ iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
+ return
+ iprot.readStructBegin()
+ while True:
+ (fname, ftype, fid) = iprot.readFieldBegin()
+ if ftype == TType.STOP:
+ break
+ if fid == 1:
+ if ftype == TType.STRING:
+ self.totalSize = iprot.readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()
+ else:
+ iprot.skip(ftype)
+ elif fid == 2:
+ if ftype == TType.I64:
+ self.totalSizeBytes = iprot.readI64()
+ else:
+ iprot.skip(ftype)
+ else:
+ iprot.skip(ftype)
+ iprot.readFieldEnd()
+ iprot.readStructEnd()
+
+ def write(self, oprot):
+ self.validate()
+ if oprot._fast_encode is not None and self.thrift_spec is not None:
+ oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
+ return
+ oprot.writeStructBegin('StorageDirectoryInfo')
+ if self.totalSize is not None:
+ oprot.writeFieldBegin('totalSize', TType.STRING, 1)
+ oprot.writeString(self.totalSize.encode('utf-8') if sys.version_info[0] == 2 else self.totalSize)
+ oprot.writeFieldEnd()
+ if self.totalSizeBytes is not None:
+ oprot.writeFieldBegin('totalSizeBytes', TType.I64, 2)
+ oprot.writeI64(self.totalSizeBytes)
+ oprot.writeFieldEnd()
+ oprot.writeFieldStop()
+ oprot.writeStructEnd()
+
+ def validate(self):
+ if self.totalSize is None:
+ raise TProtocolException(message='Required field totalSize is unset!')
+ if self.totalSizeBytes is None:
+ raise TProtocolException(message='Required field totalSizeBytes is unset!')
+ return
+
+ def __repr__(self):
+ L = ['%s=%r' % (key, value)
+ for key, value in self.__dict__.items()]
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+ def __eq__(self, other):
+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+ def __ne__(self, other):
+ return not (self == other)
all_structs.append(StorageResourceDescription)
StorageResourceDescription.thrift_spec = (
None, # 0
@@ -375,5 +454,11 @@ StorageVolumeInfo.thrift_spec = (
(8, TType.STRING, 'mountPoint', 'UTF8', None, ), # 8
(9, TType.STRING, 'filesystemType', 'UTF8', None, ), # 9
)
+all_structs.append(StorageDirectoryInfo)
+StorageDirectoryInfo.thrift_spec = (
+ None, # 0
+ (1, TType.STRING, 'totalSize', 'UTF8', None, ), # 1
+ (2, TType.I64, 'totalSizeBytes', None, None, ), # 2
+)
fix_spec(all_structs)
del all_structs