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/05/20 05:06:45 UTC

(airavata-custos) 07/07: Enabling member level allocation restriction

This is an automated email from the ASF dual-hosted git repository.

DImuthuUpe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit 3d102159ee7bd58767ad639114574e37c7440fb6
Author: DImuthuUpe <di...@gmail.com>
AuthorDate: Wed May 20 00:58:31 2026 -0400

    Enabling member level allocation restriction
---
 .../internal/subscribers/members.go                |  8 +++----
 docs/API-Docs.md                                   | 26 +++++++++++++---------
 ...n_membership_resource_override_amounts.down.sql | 20 +++++++++++++++++
 ...ion_membership_resource_override_amounts.up.sql | 20 +++++++++++++++++
 ...llocation_membership_resource_override_store.go | 13 ++++++-----
 pkg/models/allocation.go                           |  3 ++-
 ...pute_allocation_membership_resource_override.go | 14 ++++++++----
 7 files changed, 78 insertions(+), 26 deletions(-)

diff --git a/connectors/SLURM/Association-Mapper/internal/subscribers/members.go b/connectors/SLURM/Association-Mapper/internal/subscribers/members.go
index dfcc4ee70..2a087ab60 100644
--- a/connectors/SLURM/Association-Mapper/internal/subscribers/members.go
+++ b/connectors/SLURM/Association-Mapper/internal/subscribers/members.go
@@ -116,19 +116,19 @@ func (a *AssociationSubscriber) SubscribeToComputeAllocationMembershipResourceOv
 
 	grpTres := []client.TRES{}
 
-	if allocationResource.ResourceType == "GrpTRES" {
+	if override.OverrideResourceAmount > 0 {
 		grpTres = append(grpTres, client.TRES{
 			Type:  allocationResource.ResourceType,
-			Count: override.OverriddenResourceAmount, // override.OverriddenResourceAmount is the SU amount, but SLURM needs the actual resource amount (e.g., number of CPU hours), so we need to convert it using the rate for the resource
+			Count: override.OverrideResourceAmount, // override.OverrideResourceAmount is the resource amount granted to the user for this resource (e.g., number of CPUs, GPUs).
 		})
 	}
 
 	grpTresMins := []client.TRES{}
 
-	if allocationResource.ResourceType == "GrpTRESMins" {
+	if override.OverrideResourceTime > 0 {
 		grpTresMins = append(grpTresMins, client.TRES{
 			Type:  allocationResource.ResourceType,
-			Count: override.OverriddenResourceAmount,
+			Count: override.OverrideResourceTime, // override.OverrideResourceTime is the wall-clock time in minutes that the resource amount is granted for.
 		})
 	}
 
diff --git a/docs/API-Docs.md b/docs/API-Docs.md
index 325a219bc..3d9ded43c 100644
--- a/docs/API-Docs.md
+++ b/docs/API-Docs.md
@@ -1234,9 +1234,11 @@ List every per-resource override recorded against the given membership.
 
 ## Compute Allocation Membership Resource Overrides
 
-A `ComputeAllocationMembershipResourceOverride` records the SU amount of a
-specific resource (`ComputeAllocationResource`) that has been granted to a
-specific membership. There can be at most one override per
+A `ComputeAllocationMembershipResourceOverride` records the resource amount
+and wall-clock time of a specific resource (`ComputeAllocationResource`)
+that has been granted to a specific membership, overriding whatever the
+parent `ComputeAllocationResourceMapping` would otherwise provide. There can
+be at most one override per
 `(compute_allocation_membership_id, compute_allocation_resource_id)` pair
 (enforced by a unique key). Overrides are cascade-deleted when either the
 parent membership or the parent resource is removed.
@@ -1251,18 +1253,19 @@ Create a new override.
 {
   "compute_allocation_membership_id": "membership-123",
   "compute_allocation_resource_id":   "resource-456",
-  "overridden_resource_amount":       10000
+  "override_resource_amount":         24,
+  "override_resource_time":           1440
 }
 ```
 
-- All three fields are required.
-- `overridden_resource_amount` must be non-negative.
+- `compute_allocation_membership_id` and `compute_allocation_resource_id` are required.
+- `override_resource_amount` and `override_resource_time` must be non-negative (default `0`).
 - `id` is generated server-side when omitted.
 
 **Errors**
 
 - `400` — missing required fields, referenced membership/resource not found,
-  or negative `overridden_resource_amount`.
+  or negative `override_resource_amount` / `override_resource_time`.
 - `409` — an override already exists for this `(membership, resource)` pair.
 
 ### GET `/compute-allocation-membership-resource-overrides/{id}`
@@ -1367,19 +1370,20 @@ curl -s $BASE/compute-allocations/$ALLOC_ID/memberships | jq
 # List every allocation this user is a member of.
 curl -s $BASE/users/$CLUSTER_USER_ACCT_ID/compute-allocation-memberships | jq
 
-# Grant the membership a per-resource SU override on the debug resource.
+# Grant the membership a per-resource override on the debug resource.
 OVERRIDE_ID=$(curl -s -X POST $BASE/compute-allocation-membership-resource-overrides \
   -H 'Content-Type: application/json' \
   -d "{
         \"compute_allocation_membership_id\":\"$MEMBERSHIP_ID\",
         \"compute_allocation_resource_id\":\"$RES_ID\",
-        \"overridden_resource_amount\":10
+        \"override_resource_amount\":1,
+        \"override_resource_time\":20
       }" | jq -r .id)
 
-# Bump the override amount.
+# Bump the override amount and time.
 curl -s -X PUT $BASE/compute-allocation-membership-resource-overrides/$OVERRIDE_ID \
   -H 'Content-Type: application/json' \
-  -d '{"overridden_resource_amount":15000}' | jq
+  -d '{"override_resource_amount":16,"override_resource_time":960}' | jq
 
 # List every resource override for the membership.
 curl -s $BASE/compute-allocation-memberships/$MEMBERSHIP_ID/resource-overrides | jq
diff --git a/internal/db/migrations/000013_compute_allocation_membership_resource_override_amounts.down.sql b/internal/db/migrations/000013_compute_allocation_membership_resource_override_amounts.down.sql
new file mode 100644
index 000000000..c937d1aca
--- /dev/null
+++ b/internal/db/migrations/000013_compute_allocation_membership_resource_override_amounts.down.sql
@@ -0,0 +1,20 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+ALTER TABLE compute_allocation_membership_resource_overrides
+    DROP COLUMN override_resource_time,
+    CHANGE COLUMN override_resource_amount overridden_resource_amount BIGINT NOT NULL DEFAULT 0;
diff --git a/internal/db/migrations/000013_compute_allocation_membership_resource_override_amounts.up.sql b/internal/db/migrations/000013_compute_allocation_membership_resource_override_amounts.up.sql
new file mode 100644
index 000000000..bc18ef857
--- /dev/null
+++ b/internal/db/migrations/000013_compute_allocation_membership_resource_override_amounts.up.sql
@@ -0,0 +1,20 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+ALTER TABLE compute_allocation_membership_resource_overrides
+    CHANGE COLUMN overridden_resource_amount override_resource_amount BIGINT NOT NULL DEFAULT 0,
+    ADD COLUMN override_resource_time BIGINT NOT NULL DEFAULT 0 AFTER override_resource_amount;
diff --git a/internal/store/compute_allocation_membership_resource_override_store.go b/internal/store/compute_allocation_membership_resource_override_store.go
index 1e0f0d1b0..d89f11e9c 100644
--- a/internal/store/compute_allocation_membership_resource_override_store.go
+++ b/internal/store/compute_allocation_membership_resource_override_store.go
@@ -27,7 +27,7 @@ import (
 	"github.com/apache/airavata-custos/pkg/models"
 )
 
-const computeAllocationMembershipResourceOverrideColumns = "id, compute_allocation_membership_id, compute_allocation_resource_id, overridden_resource_amount"
+const computeAllocationMembershipResourceOverrideColumns = "id, compute_allocation_membership_id, compute_allocation_resource_id, override_resource_amount, override_resource_time"
 
 type mysqlComputeAllocationMembershipResourceOverrideStore struct {
 	db *sqlx.DB
@@ -99,9 +99,9 @@ func (s *mysqlComputeAllocationMembershipResourceOverrideStore) FindByResource(c
 func (s *mysqlComputeAllocationMembershipResourceOverrideStore) Create(ctx context.Context, tx *sql.Tx, o *models.ComputeAllocationMembershipResourceOverride) error {
 	_, err := tx.ExecContext(ctx,
 		`INSERT INTO compute_allocation_membership_resource_overrides
-             (id, compute_allocation_membership_id, compute_allocation_resource_id, overridden_resource_amount)
-         VALUES (?, ?, ?, ?)`,
-		o.ID, o.ComputeAllocationMembershipID, o.ComputeAllocationResourceID, o.OverriddenResourceAmount)
+             (id, compute_allocation_membership_id, compute_allocation_resource_id, override_resource_amount, override_resource_time)
+         VALUES (?, ?, ?, ?, ?)`,
+		o.ID, o.ComputeAllocationMembershipID, o.ComputeAllocationResourceID, o.OverrideResourceAmount, o.OverrideResourceTime)
 	return err
 }
 
@@ -110,9 +110,10 @@ func (s *mysqlComputeAllocationMembershipResourceOverrideStore) Update(ctx conte
 		`UPDATE compute_allocation_membership_resource_overrides
             SET compute_allocation_membership_id = ?,
                 compute_allocation_resource_id   = ?,
-                overridden_resource_amount       = ?
+                override_resource_amount         = ?,
+                override_resource_time           = ?
           WHERE id = ?`,
-		o.ComputeAllocationMembershipID, o.ComputeAllocationResourceID, o.OverriddenResourceAmount, o.ID)
+		o.ComputeAllocationMembershipID, o.ComputeAllocationResourceID, o.OverrideResourceAmount, o.OverrideResourceTime, o.ID)
 	return err
 }
 
diff --git a/pkg/models/allocation.go b/pkg/models/allocation.go
index 582bce606..a8fcd3976 100644
--- a/pkg/models/allocation.go
+++ b/pkg/models/allocation.go
@@ -103,7 +103,8 @@ type ComputeAllocationMembershipResourceOverride struct {
 	ID                            string `json:"id"                             db:"id"`
 	ComputeAllocationMembershipID string `json:"compute_allocation_membership_id" db:"compute_allocation_membership_id"`
 	ComputeAllocationResourceID   string `json:"compute_allocation_resource_id" db:"compute_allocation_resource_id"`
-	OverriddenResourceAmount      int64  `json:"overridden_resource_amount"       db:"overridden_resource_amount"` // The overridden SU amount for the user for this specific resource, e.g., 150 SUs for GPU hours, etc.
+	OverrideResourceAmount        int64  `json:"override_resource_amount"         db:"override_resource_amount"` // The overridden amount of the resource for the user (e.g., number of CPUs, GPUs).
+	OverrideResourceTime          int64  `json:"override_resource_time"           db:"override_resource_time"`   // The overridden wall-clock time in minutes that the resource amount is granted for.
 }
 
 type ComputeAllocationMembership struct {
diff --git a/pkg/service/compute_allocation_membership_resource_override.go b/pkg/service/compute_allocation_membership_resource_override.go
index 81fadee40..e3148cd00 100644
--- a/pkg/service/compute_allocation_membership_resource_override.go
+++ b/pkg/service/compute_allocation_membership_resource_override.go
@@ -40,8 +40,11 @@ func (s *Service) CreateComputeAllocationMembershipResourceOverride(ctx context.
 	if o.ComputeAllocationResourceID == "" {
 		return nil, fmt.Errorf("%w: compute_allocation_resource_id is required", ErrInvalidInput)
 	}
-	if o.OverriddenResourceAmount < 0 {
-		return nil, fmt.Errorf("%w: overridden_resource_amount must be non-negative", ErrInvalidInput)
+	if o.OverrideResourceAmount < 0 {
+		return nil, fmt.Errorf("%w: override_resource_amount must be non-negative", ErrInvalidInput)
+	}
+	if o.OverrideResourceTime < 0 {
+		return nil, fmt.Errorf("%w: override_resource_time must be non-negative", ErrInvalidInput)
 	}
 
 	if m, err := s.memberships.FindByID(ctx, o.ComputeAllocationMembershipID); err != nil {
@@ -141,8 +144,11 @@ func (s *Service) UpdateComputeAllocationMembershipResourceOverride(ctx context.
 	if o == nil || o.ID == "" {
 		return nil, fmt.Errorf("%w: membership resource override id is required", ErrInvalidInput)
 	}
-	if o.OverriddenResourceAmount < 0 {
-		return nil, fmt.Errorf("%w: overridden_resource_amount must be non-negative", ErrInvalidInput)
+	if o.OverrideResourceAmount < 0 {
+		return nil, fmt.Errorf("%w: override_resource_amount must be non-negative", ErrInvalidInput)
+	}
+	if o.OverrideResourceTime < 0 {
+		return nil, fmt.Errorf("%w: override_resource_time must be non-negative", ErrInvalidInput)
 	}
 	existing, err := s.membershipOverrides.FindByID(ctx, o.ID)
 	if err != nil {