You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2020/03/25 19:46:41 UTC

[airavata] branch develop updated (cd0f271 -> b801135)

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

machristie pushed a change to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata.git.


    from cd0f271  Merge pull request #245 from isururanawaka/pythonSDK
     new af5cc07  AIRAVATA-3126 Add ComputeResourceReservation data model and entity
     new d698f9b  AIRAVATA-3126 Update logic to get active reservation
     new 3fb981b  AIRAVATA-3126 Prevent MariaDB ON UPDATE CURRENT_TIMESTAMP
     new b801135  Merge branch 'AIRAVATA-3126--Implement-compute-resource-reservation-addition' into develop

The 4 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.


Summary of changes:
 .../appcatalog/groupresourceprofile/ttypes.py      | 217 +++++-
 .../ComputeResourcePolicy.java                     |  32 +-
 .../ComputeResourceReservation.java                | 820 +++++++++++++++++++++
 .../GroupComputeResourcePreference.java            | 189 ++++-
 .../groupresourceprofile/GroupResourceProfile.java | 108 +--
 airavata-api/airavata-model-utils/pom.xml          |   6 +
 .../util/GroupComputeResourcePreferenceUtil.java   |  30 +-
 .../GroupComputeResourcePreferenceUtilTest.java    | 116 +++
 .../airavata/helix/impl/task/TaskContext.java      |   9 +
 .../org/apache/airavata/common/utils/JPAUtils.java |  13 +
 .../src/main/resources/META-INF/persistence.xml    |   1 +
 .../init/03-appcatalog-migrations.sql              |   9 +
 modules/registry/registry-core/README.md           |  13 +
 ....java => ComputeResourceReservationEntity.java} |  93 ++-
 .../appcatalog/GroupComputeResourcePrefEntity.java |  15 +-
 .../GroupSSHAccountProvisionerConfig.java          |   2 +-
 .../core/repositories/AbstractRepository.java      |  10 +-
 .../appcatalog/GroupResourceProfileRepository.java |  29 +-
 .../core/utils/JPAUtil/AppCatalogJPAUtils.java     |  40 +-
 .../src/main/resources/META-INF/persistence.xml    |   1 +
 .../src/main/resources/appcatalog-derby.sql        |   6 +
 .../src/main/resources/appcatalog-mysql.sql        |   8 +
 .../GroupResourceProfileRepositoryTest.java        | 257 ++++++-
 .../next/DeltaScripts/appCatalog_schema_delta.sql  |   9 +
 .../group_resource_profile_model.thrift            |  13 +-
 25 files changed, 1858 insertions(+), 188 deletions(-)
 create mode 100644 airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourceReservation.java
 copy modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/appcatalog/GrpComputePrefRepository.java => airavata-api/airavata-model-utils/src/main/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtil.java (51%)
 create mode 100644 airavata-api/airavata-model-utils/src/test/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtilTest.java
 create mode 100644 modules/registry/registry-core/README.md
 copy modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/{GroupSSHAccountProvisionerConfig.java => ComputeResourceReservationEntity.java} (52%)


[airavata] 01/04: AIRAVATA-3126 Add ComputeResourceReservation data model and entity

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit af5cc079cbc2223d709f8b474d452cb7becacfde
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri Feb 28 15:03:24 2020 -0500

    AIRAVATA-3126 Add ComputeResourceReservation data model and entity
---
 .../appcatalog/groupresourceprofile/ttypes.py      | 217 +++++-
 .../resources/lib/airavata/model/group/ttypes.py   |   3 +
 .../resources/lib/airavata/model/sharing/ttypes.py |  15 +-
 .../ComputeResourcePolicy.java                     |  32 +-
 .../ComputeResourceReservation.java                | 820 +++++++++++++++++++++
 .../GroupComputeResourcePreference.java            | 189 ++++-
 .../groupresourceprofile/GroupResourceProfile.java | 108 +--
 .../org/apache/airavata/common/utils/JPAUtils.java |  13 +
 .../src/main/resources/META-INF/persistence.xml    |   1 +
 .../init/03-appcatalog-migrations.sql              |  10 +
 modules/registry/registry-core/README.md           |  13 +
 ....java => ComputeResourceReservationEntity.java} |  93 ++-
 .../appcatalog/GroupComputeResourcePrefEntity.java |  15 +-
 .../GroupSSHAccountProvisionerConfig.java          |   2 +-
 .../core/repositories/AbstractRepository.java      |  10 +-
 .../appcatalog/GroupResourceProfileRepository.java |  29 +-
 .../core/utils/JPAUtil/AppCatalogJPAUtils.java     |  40 +-
 .../src/main/resources/META-INF/persistence.xml    |   1 +
 .../src/main/resources/appcatalog-derby.sql        |   6 +
 .../src/main/resources/appcatalog-mysql.sql        |   8 +
 .../GroupResourceProfileRepositoryTest.java        | 257 ++++++-
 .../next/DeltaScripts/appCatalog_schema_delta.sql  |   9 +
 .../group_resource_profile_model.thrift            |  13 +-
 23 files changed, 1725 insertions(+), 179 deletions(-)

diff --git a/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/appcatalog/groupresourceprofile/ttypes.py b/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/appcatalog/groupresourceprofile/ttypes.py
index e2841da..d5b8e18 100644
--- a/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/appcatalog/groupresourceprofile/ttypes.py
+++ b/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/appcatalog/groupresourceprofile/ttypes.py
@@ -118,6 +118,132 @@ class GroupAccountSSHProvisionerConfig(object):
         return not (self == other)
 
 
+class ComputeResourceReservation(object):
+    """
+    Attributes:
+     - reservationId
+     - reservationName
+     - queueNames
+     - startTime
+     - endTime
+    """
+
+    thrift_spec = (
+        None,  # 0
+        (1, TType.STRING, 'reservationId', 'UTF8', "DO_NOT_SET_AT_CLIENTS", ),  # 1
+        (2, TType.STRING, 'reservationName', 'UTF8', None, ),  # 2
+        (3, TType.LIST, 'queueNames', (TType.STRING, 'UTF8', False), None, ),  # 3
+        (4, TType.I64, 'startTime', None, None, ),  # 4
+        (5, TType.I64, 'endTime', None, None, ),  # 5
+    )
+
+    def __init__(self, reservationId=thrift_spec[1][4], reservationName=None, queueNames=None, startTime=None, endTime=None,):
+        self.reservationId = reservationId
+        self.reservationName = reservationName
+        self.queueNames = queueNames
+        self.startTime = startTime
+        self.endTime = endTime
+
+    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.reservationId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 2:
+                if ftype == TType.STRING:
+                    self.reservationName = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 3:
+                if ftype == TType.LIST:
+                    self.queueNames = []
+                    (_etype3, _size0) = iprot.readListBegin()
+                    for _i4 in range(_size0):
+                        _elem5 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.queueNames.append(_elem5)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 4:
+                if ftype == TType.I64:
+                    self.startTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            elif fid == 5:
+                if ftype == TType.I64:
+                    self.endTime = iprot.readI64()
+                else:
+                    iprot.skip(ftype)
+            else:
+                iprot.skip(ftype)
+            iprot.readFieldEnd()
+        iprot.readStructEnd()
+
+    def write(self, oprot):
+        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('ComputeResourceReservation')
+        if self.reservationId is not None:
+            oprot.writeFieldBegin('reservationId', TType.STRING, 1)
+            oprot.writeString(self.reservationId.encode('utf-8') if sys.version_info[0] == 2 else self.reservationId)
+            oprot.writeFieldEnd()
+        if self.reservationName is not None:
+            oprot.writeFieldBegin('reservationName', TType.STRING, 2)
+            oprot.writeString(self.reservationName.encode('utf-8') if sys.version_info[0] == 2 else self.reservationName)
+            oprot.writeFieldEnd()
+        if self.queueNames is not None:
+            oprot.writeFieldBegin('queueNames', TType.LIST, 3)
+            oprot.writeListBegin(TType.STRING, len(self.queueNames))
+            for iter6 in self.queueNames:
+                oprot.writeString(iter6.encode('utf-8') if sys.version_info[0] == 2 else iter6)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
+        if self.startTime is not None:
+            oprot.writeFieldBegin('startTime', TType.I64, 4)
+            oprot.writeI64(self.startTime)
+            oprot.writeFieldEnd()
+        if self.endTime is not None:
+            oprot.writeFieldBegin('endTime', TType.I64, 5)
+            oprot.writeI64(self.endTime)
+            oprot.writeFieldEnd()
+        oprot.writeFieldStop()
+        oprot.writeStructEnd()
+
+    def validate(self):
+        if self.reservationId is None:
+            raise TProtocolException(message='Required field reservationId is unset!')
+        if self.reservationName is None:
+            raise TProtocolException(message='Required field reservationName is unset!')
+        if self.queueNames is None:
+            raise TProtocolException(message='Required field queueNames is unset!')
+        if self.startTime is None:
+            raise TProtocolException(message='Required field startTime is unset!')
+        if self.endTime is None:
+            raise TProtocolException(message='Required field endTime 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)
+
+
 class GroupComputeResourcePreference(object):
     """
     Attributes:
@@ -139,6 +265,7 @@ class GroupComputeResourcePreference(object):
      - sshAccountProvisioner
      - groupSSHAccountProvisionerConfigs
      - sshAccountProvisionerAdditionalInfo
+     - reservations
     """
 
     thrift_spec = (
@@ -161,9 +288,10 @@ class GroupComputeResourcePreference(object):
         (16, TType.STRING, 'sshAccountProvisioner', 'UTF8', None, ),  # 16
         (17, TType.LIST, 'groupSSHAccountProvisionerConfigs', (TType.STRUCT, (GroupAccountSSHProvisionerConfig, GroupAccountSSHProvisionerConfig.thrift_spec), False), None, ),  # 17
         (18, TType.STRING, 'sshAccountProvisionerAdditionalInfo', 'UTF8', None, ),  # 18
+        (19, TType.LIST, 'reservations', (TType.STRUCT, (ComputeResourceReservation, ComputeResourceReservation.thrift_spec), False), None, ),  # 19
     )
 
-    def __init__(self, computeResourceId=None, groupResourceProfileId=thrift_spec[2][4], overridebyAiravata=thrift_spec[3][4], loginUserName=None, preferredJobSubmissionProtocol=None, preferredDataMovementProtocol=None, preferredBatchQueue=None, scratchLocation=None, allocationProjectNumber=None, resourceSpecificCredentialStoreToken=None, usageReportingGatewayId=None, qualityOfService=None, reservation=None, reservationStartTime=None, reservationEndTime=None, sshAccountProvisioner=None,  [...]
+    def __init__(self, computeResourceId=None, groupResourceProfileId=thrift_spec[2][4], overridebyAiravata=thrift_spec[3][4], loginUserName=None, preferredJobSubmissionProtocol=None, preferredDataMovementProtocol=None, preferredBatchQueue=None, scratchLocation=None, allocationProjectNumber=None, resourceSpecificCredentialStoreToken=None, usageReportingGatewayId=None, qualityOfService=None, reservation=None, reservationStartTime=None, reservationEndTime=None, sshAccountProvisioner=None,  [...]
         self.computeResourceId = computeResourceId
         self.groupResourceProfileId = groupResourceProfileId
         self.overridebyAiravata = overridebyAiravata
@@ -182,6 +310,7 @@ class GroupComputeResourcePreference(object):
         self.sshAccountProvisioner = sshAccountProvisioner
         self.groupSSHAccountProvisionerConfigs = groupSSHAccountProvisionerConfigs
         self.sshAccountProvisionerAdditionalInfo = sshAccountProvisionerAdditionalInfo
+        self.reservations = reservations
 
     def read(self, iprot):
         if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
@@ -275,11 +404,11 @@ class GroupComputeResourcePreference(object):
             elif fid == 17:
                 if ftype == TType.LIST:
                     self.groupSSHAccountProvisionerConfigs = []
-                    (_etype3, _size0) = iprot.readListBegin()
-                    for _i4 in range(_size0):
-                        _elem5 = GroupAccountSSHProvisionerConfig()
-                        _elem5.read(iprot)
-                        self.groupSSHAccountProvisionerConfigs.append(_elem5)
+                    (_etype10, _size7) = iprot.readListBegin()
+                    for _i11 in range(_size7):
+                        _elem12 = GroupAccountSSHProvisionerConfig()
+                        _elem12.read(iprot)
+                        self.groupSSHAccountProvisionerConfigs.append(_elem12)
                     iprot.readListEnd()
                 else:
                     iprot.skip(ftype)
@@ -288,6 +417,17 @@ class GroupComputeResourcePreference(object):
                     self.sshAccountProvisionerAdditionalInfo = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
                 else:
                     iprot.skip(ftype)
+            elif fid == 19:
+                if ftype == TType.LIST:
+                    self.reservations = []
+                    (_etype16, _size13) = iprot.readListBegin()
+                    for _i17 in range(_size13):
+                        _elem18 = ComputeResourceReservation()
+                        _elem18.read(iprot)
+                        self.reservations.append(_elem18)
+                    iprot.readListEnd()
+                else:
+                    iprot.skip(ftype)
             else:
                 iprot.skip(ftype)
             iprot.readFieldEnd()
@@ -365,14 +505,21 @@ class GroupComputeResourcePreference(object):
         if self.groupSSHAccountProvisionerConfigs is not None:
             oprot.writeFieldBegin('groupSSHAccountProvisionerConfigs', TType.LIST, 17)
             oprot.writeListBegin(TType.STRUCT, len(self.groupSSHAccountProvisionerConfigs))
-            for iter6 in self.groupSSHAccountProvisionerConfigs:
-                iter6.write(oprot)
+            for iter19 in self.groupSSHAccountProvisionerConfigs:
+                iter19.write(oprot)
             oprot.writeListEnd()
             oprot.writeFieldEnd()
         if self.sshAccountProvisionerAdditionalInfo is not None:
             oprot.writeFieldBegin('sshAccountProvisionerAdditionalInfo', TType.STRING, 18)
             oprot.writeString(self.sshAccountProvisionerAdditionalInfo.encode('utf-8') if sys.version_info[0] == 2 else self.sshAccountProvisionerAdditionalInfo)
             oprot.writeFieldEnd()
+        if self.reservations is not None:
+            oprot.writeFieldBegin('reservations', TType.LIST, 19)
+            oprot.writeListBegin(TType.STRUCT, len(self.reservations))
+            for iter20 in self.reservations:
+                iter20.write(oprot)
+            oprot.writeListEnd()
+            oprot.writeFieldEnd()
         oprot.writeFieldStop()
         oprot.writeStructEnd()
 
@@ -447,10 +594,10 @@ class ComputeResourcePolicy(object):
             elif fid == 4:
                 if ftype == TType.LIST:
                     self.allowedBatchQueues = []
-                    (_etype10, _size7) = iprot.readListBegin()
-                    for _i11 in range(_size7):
-                        _elem12 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
-                        self.allowedBatchQueues.append(_elem12)
+                    (_etype24, _size21) = iprot.readListBegin()
+                    for _i25 in range(_size21):
+                        _elem26 = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                        self.allowedBatchQueues.append(_elem26)
                     iprot.readListEnd()
                 else:
                     iprot.skip(ftype)
@@ -479,8 +626,8 @@ class ComputeResourcePolicy(object):
         if self.allowedBatchQueues is not None:
             oprot.writeFieldBegin('allowedBatchQueues', TType.LIST, 4)
             oprot.writeListBegin(TType.STRING, len(self.allowedBatchQueues))
-            for iter13 in self.allowedBatchQueues:
-                oprot.writeString(iter13.encode('utf-8') if sys.version_info[0] == 2 else iter13)
+            for iter27 in self.allowedBatchQueues:
+                oprot.writeString(iter27.encode('utf-8') if sys.version_info[0] == 2 else iter27)
             oprot.writeListEnd()
             oprot.writeFieldEnd()
         oprot.writeFieldStop()
@@ -730,33 +877,33 @@ class GroupResourceProfile(object):
             elif fid == 4:
                 if ftype == TType.LIST:
                     self.computePreferences = []
-                    (_etype17, _size14) = iprot.readListBegin()
-                    for _i18 in range(_size14):
-                        _elem19 = GroupComputeResourcePreference()
-                        _elem19.read(iprot)
-                        self.computePreferences.append(_elem19)
+                    (_etype31, _size28) = iprot.readListBegin()
+                    for _i32 in range(_size28):
+                        _elem33 = GroupComputeResourcePreference()
+                        _elem33.read(iprot)
+                        self.computePreferences.append(_elem33)
                     iprot.readListEnd()
                 else:
                     iprot.skip(ftype)
             elif fid == 5:
                 if ftype == TType.LIST:
                     self.computeResourcePolicies = []
-                    (_etype23, _size20) = iprot.readListBegin()
-                    for _i24 in range(_size20):
-                        _elem25 = ComputeResourcePolicy()
-                        _elem25.read(iprot)
-                        self.computeResourcePolicies.append(_elem25)
+                    (_etype37, _size34) = iprot.readListBegin()
+                    for _i38 in range(_size34):
+                        _elem39 = ComputeResourcePolicy()
+                        _elem39.read(iprot)
+                        self.computeResourcePolicies.append(_elem39)
                     iprot.readListEnd()
                 else:
                     iprot.skip(ftype)
             elif fid == 6:
                 if ftype == TType.LIST:
                     self.batchQueueResourcePolicies = []
-                    (_etype29, _size26) = iprot.readListBegin()
-                    for _i30 in range(_size26):
-                        _elem31 = BatchQueueResourcePolicy()
-                        _elem31.read(iprot)
-                        self.batchQueueResourcePolicies.append(_elem31)
+                    (_etype43, _size40) = iprot.readListBegin()
+                    for _i44 in range(_size40):
+                        _elem45 = BatchQueueResourcePolicy()
+                        _elem45.read(iprot)
+                        self.batchQueueResourcePolicies.append(_elem45)
                     iprot.readListEnd()
                 else:
                     iprot.skip(ftype)
@@ -800,22 +947,22 @@ class GroupResourceProfile(object):
         if self.computePreferences is not None:
             oprot.writeFieldBegin('computePreferences', TType.LIST, 4)
             oprot.writeListBegin(TType.STRUCT, len(self.computePreferences))
-            for iter32 in self.computePreferences:
-                iter32.write(oprot)
+            for iter46 in self.computePreferences:
+                iter46.write(oprot)
             oprot.writeListEnd()
             oprot.writeFieldEnd()
         if self.computeResourcePolicies is not None:
             oprot.writeFieldBegin('computeResourcePolicies', TType.LIST, 5)
             oprot.writeListBegin(TType.STRUCT, len(self.computeResourcePolicies))
-            for iter33 in self.computeResourcePolicies:
-                iter33.write(oprot)
+            for iter47 in self.computeResourcePolicies:
+                iter47.write(oprot)
             oprot.writeListEnd()
             oprot.writeFieldEnd()
         if self.batchQueueResourcePolicies is not None:
             oprot.writeFieldBegin('batchQueueResourcePolicies', TType.LIST, 6)
             oprot.writeListBegin(TType.STRUCT, len(self.batchQueueResourcePolicies))
-            for iter34 in self.batchQueueResourcePolicies:
-                iter34.write(oprot)
+            for iter48 in self.batchQueueResourcePolicies:
+                iter48.write(oprot)
             oprot.writeListEnd()
             oprot.writeFieldEnd()
         if self.creationTime is not None:
diff --git a/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/group/ttypes.py b/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/group/ttypes.py
index 3be6af0..8bce444 100644
--- a/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/group/ttypes.py
+++ b/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/group/ttypes.py
@@ -48,17 +48,20 @@ class ResourcePermissionType(object):
     WRITE = 0
     READ = 1
     OWNER = 2
+    MANAGE_SHARING = 3
 
     _VALUES_TO_NAMES = {
         0: "WRITE",
         1: "READ",
         2: "OWNER",
+        3: "MANAGE_SHARING",
     }
 
     _NAMES_TO_VALUES = {
         "WRITE": 0,
         "READ": 1,
         "OWNER": 2,
+        "MANAGE_SHARING": 3,
     }
 
 
diff --git a/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/sharing/ttypes.py b/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/sharing/ttypes.py
index 1f2f0e9..661367f 100644
--- a/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/sharing/ttypes.py
+++ b/airavata-api/airavata-client-sdks/airavata-python-sdk/src/main/resources/lib/airavata/model/sharing/ttypes.py
@@ -190,6 +190,7 @@ class Domain(object):
     <li>description : A short description for the domain</li>
     <li>createdTime : Will be set by the system</li>
     <li>updatedTime : Will be set by the system</li>
+    <li>initialUserGroupId : New users will automatically be added to this group</li>
 
 
     Attributes:
@@ -198,6 +199,7 @@ class Domain(object):
      - description
      - createdTime
      - updatedTime
+     - initialUserGroupId
     """
 
     thrift_spec = (
@@ -207,14 +209,16 @@ class Domain(object):
         (3, TType.STRING, 'description', 'UTF8', None, ),  # 3
         (4, TType.I64, 'createdTime', None, None, ),  # 4
         (5, TType.I64, 'updatedTime', None, None, ),  # 5
+        (6, TType.STRING, 'initialUserGroupId', 'UTF8', None, ),  # 6
     )
 
-    def __init__(self, domainId=thrift_spec[1][4], name=None, description=None, createdTime=None, updatedTime=None,):
+    def __init__(self, domainId=thrift_spec[1][4], name=None, description=None, createdTime=None, updatedTime=None, initialUserGroupId=None,):
         self.domainId = domainId
         self.name = name
         self.description = description
         self.createdTime = createdTime
         self.updatedTime = updatedTime
+        self.initialUserGroupId = initialUserGroupId
 
     def read(self, iprot):
         if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
@@ -250,6 +254,11 @@ class Domain(object):
                     self.updatedTime = iprot.readI64()
                 else:
                     iprot.skip(ftype)
+            elif fid == 6:
+                if ftype == TType.STRING:
+                    self.initialUserGroupId = iprot.readString().decode('utf-8') if sys.version_info[0] == 2 else iprot.readString()
+                else:
+                    iprot.skip(ftype)
             else:
                 iprot.skip(ftype)
             iprot.readFieldEnd()
@@ -280,6 +289,10 @@ class Domain(object):
             oprot.writeFieldBegin('updatedTime', TType.I64, 5)
             oprot.writeI64(self.updatedTime)
             oprot.writeFieldEnd()
+        if self.initialUserGroupId is not None:
+            oprot.writeFieldBegin('initialUserGroupId', TType.STRING, 6)
+            oprot.writeString(self.initialUserGroupId.encode('utf-8') if sys.version_info[0] == 2 else self.initialUserGroupId)
+            oprot.writeFieldEnd()
         oprot.writeFieldStop()
         oprot.writeStructEnd()
 
diff --git a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourcePolicy.java b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourcePolicy.java
index 4f7f4bd..48f5ac2 100644
--- a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourcePolicy.java
+++ b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourcePolicy.java
@@ -618,13 +618,13 @@ public class ComputeResourcePolicy implements org.apache.thrift.TBase<ComputeRes
           case 4: // ALLOWED_BATCH_QUEUES
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list8 = iprot.readListBegin();
-                struct.allowedBatchQueues = new java.util.ArrayList<java.lang.String>(_list8.size);
-                java.lang.String _elem9;
-                for (int _i10 = 0; _i10 < _list8.size; ++_i10)
+                org.apache.thrift.protocol.TList _list24 = iprot.readListBegin();
+                struct.allowedBatchQueues = new java.util.ArrayList<java.lang.String>(_list24.size);
+                java.lang.String _elem25;
+                for (int _i26 = 0; _i26 < _list24.size; ++_i26)
                 {
-                  _elem9 = iprot.readString();
-                  struct.allowedBatchQueues.add(_elem9);
+                  _elem25 = iprot.readString();
+                  struct.allowedBatchQueues.add(_elem25);
                 }
                 iprot.readListEnd();
               }
@@ -666,9 +666,9 @@ public class ComputeResourcePolicy implements org.apache.thrift.TBase<ComputeRes
           oprot.writeFieldBegin(ALLOWED_BATCH_QUEUES_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.allowedBatchQueues.size()));
-            for (java.lang.String _iter11 : struct.allowedBatchQueues)
+            for (java.lang.String _iter27 : struct.allowedBatchQueues)
             {
-              oprot.writeString(_iter11);
+              oprot.writeString(_iter27);
             }
             oprot.writeListEnd();
           }
@@ -703,9 +703,9 @@ public class ComputeResourcePolicy implements org.apache.thrift.TBase<ComputeRes
       if (struct.isSetAllowedBatchQueues()) {
         {
           oprot.writeI32(struct.allowedBatchQueues.size());
-          for (java.lang.String _iter12 : struct.allowedBatchQueues)
+          for (java.lang.String _iter28 : struct.allowedBatchQueues)
           {
-            oprot.writeString(_iter12);
+            oprot.writeString(_iter28);
           }
         }
       }
@@ -723,13 +723,13 @@ public class ComputeResourcePolicy implements org.apache.thrift.TBase<ComputeRes
       java.util.BitSet incoming = iprot.readBitSet(1);
       if (incoming.get(0)) {
         {
-          org.apache.thrift.protocol.TList _list13 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
-          struct.allowedBatchQueues = new java.util.ArrayList<java.lang.String>(_list13.size);
-          java.lang.String _elem14;
-          for (int _i15 = 0; _i15 < _list13.size; ++_i15)
+          org.apache.thrift.protocol.TList _list29 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.allowedBatchQueues = new java.util.ArrayList<java.lang.String>(_list29.size);
+          java.lang.String _elem30;
+          for (int _i31 = 0; _i31 < _list29.size; ++_i31)
           {
-            _elem14 = iprot.readString();
-            struct.allowedBatchQueues.add(_elem14);
+            _elem30 = iprot.readString();
+            struct.allowedBatchQueues.add(_elem30);
           }
         }
         struct.setAllowedBatchQueuesIsSet(true);
diff --git a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourceReservation.java b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourceReservation.java
new file mode 100644
index 0000000..5909f9c
--- /dev/null
+++ b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/ComputeResourceReservation.java
@@ -0,0 +1,820 @@
+/**
+ * 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.
+ */
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.airavata.model.appcatalog.groupresourceprofile;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
+public class ComputeResourceReservation implements org.apache.thrift.TBase<ComputeResourceReservation, ComputeResourceReservation._Fields>, java.io.Serializable, Cloneable, Comparable<ComputeResourceReservation> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("ComputeResourceReservation");
+
+  private static final org.apache.thrift.protocol.TField RESERVATION_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("reservationId", org.apache.thrift.protocol.TType.STRING, (short)1);
+  private static final org.apache.thrift.protocol.TField RESERVATION_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("reservationName", org.apache.thrift.protocol.TType.STRING, (short)2);
+  private static final org.apache.thrift.protocol.TField QUEUE_NAMES_FIELD_DESC = new org.apache.thrift.protocol.TField("queueNames", org.apache.thrift.protocol.TType.LIST, (short)3);
+  private static final org.apache.thrift.protocol.TField START_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("startTime", org.apache.thrift.protocol.TType.I64, (short)4);
+  private static final org.apache.thrift.protocol.TField END_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("endTime", org.apache.thrift.protocol.TType.I64, (short)5);
+
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ComputeResourceReservationStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ComputeResourceReservationTupleSchemeFactory();
+
+  private java.lang.String reservationId; // required
+  private java.lang.String reservationName; // required
+  private java.util.List<java.lang.String> queueNames; // required
+  private long startTime; // required
+  private long endTime; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    RESERVATION_ID((short)1, "reservationId"),
+    RESERVATION_NAME((short)2, "reservationName"),
+    QUEUE_NAMES((short)3, "queueNames"),
+    START_TIME((short)4, "startTime"),
+    END_TIME((short)5, "endTime");
+
+    private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();
+
+    static {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // RESERVATION_ID
+          return RESERVATION_ID;
+        case 2: // RESERVATION_NAME
+          return RESERVATION_NAME;
+        case 3: // QUEUE_NAMES
+          return QUEUE_NAMES;
+        case 4: // START_TIME
+          return START_TIME;
+        case 5: // END_TIME
+          return END_TIME;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(java.lang.String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final java.lang.String _fieldName;
+
+    _Fields(short thriftId, java.lang.String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public java.lang.String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  private static final int __STARTTIME_ISSET_ID = 0;
+  private static final int __ENDTIME_ISSET_ID = 1;
+  private byte __isset_bitfield = 0;
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.RESERVATION_ID, new org.apache.thrift.meta_data.FieldMetaData("reservationId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.RESERVATION_NAME, new org.apache.thrift.meta_data.FieldMetaData("reservationName", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.QUEUE_NAMES, new org.apache.thrift.meta_data.FieldMetaData("queueNames", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
+    tmpMap.put(_Fields.START_TIME, new org.apache.thrift.meta_data.FieldMetaData("startTime", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    tmpMap.put(_Fields.END_TIME, new org.apache.thrift.meta_data.FieldMetaData("endTime", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ComputeResourceReservation.class, metaDataMap);
+  }
+
+  public ComputeResourceReservation() {
+    this.reservationId = "DO_NOT_SET_AT_CLIENTS";
+
+  }
+
+  public ComputeResourceReservation(
+    java.lang.String reservationId,
+    java.lang.String reservationName,
+    java.util.List<java.lang.String> queueNames,
+    long startTime,
+    long endTime)
+  {
+    this();
+    this.reservationId = reservationId;
+    this.reservationName = reservationName;
+    this.queueNames = queueNames;
+    this.startTime = startTime;
+    setStartTimeIsSet(true);
+    this.endTime = endTime;
+    setEndTimeIsSet(true);
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public ComputeResourceReservation(ComputeResourceReservation other) {
+    __isset_bitfield = other.__isset_bitfield;
+    if (other.isSetReservationId()) {
+      this.reservationId = other.reservationId;
+    }
+    if (other.isSetReservationName()) {
+      this.reservationName = other.reservationName;
+    }
+    if (other.isSetQueueNames()) {
+      java.util.List<java.lang.String> __this__queueNames = new java.util.ArrayList<java.lang.String>(other.queueNames);
+      this.queueNames = __this__queueNames;
+    }
+    this.startTime = other.startTime;
+    this.endTime = other.endTime;
+  }
+
+  public ComputeResourceReservation deepCopy() {
+    return new ComputeResourceReservation(this);
+  }
+
+  @Override
+  public void clear() {
+    this.reservationId = "DO_NOT_SET_AT_CLIENTS";
+
+    this.reservationName = null;
+    this.queueNames = null;
+    setStartTimeIsSet(false);
+    this.startTime = 0;
+    setEndTimeIsSet(false);
+    this.endTime = 0;
+  }
+
+  public java.lang.String getReservationId() {
+    return this.reservationId;
+  }
+
+  public void setReservationId(java.lang.String reservationId) {
+    this.reservationId = reservationId;
+  }
+
+  public void unsetReservationId() {
+    this.reservationId = null;
+  }
+
+  /** Returns true if field reservationId is set (has been assigned a value) and false otherwise */
+  public boolean isSetReservationId() {
+    return this.reservationId != null;
+  }
+
+  public void setReservationIdIsSet(boolean value) {
+    if (!value) {
+      this.reservationId = null;
+    }
+  }
+
+  public java.lang.String getReservationName() {
+    return this.reservationName;
+  }
+
+  public void setReservationName(java.lang.String reservationName) {
+    this.reservationName = reservationName;
+  }
+
+  public void unsetReservationName() {
+    this.reservationName = null;
+  }
+
+  /** Returns true if field reservationName is set (has been assigned a value) and false otherwise */
+  public boolean isSetReservationName() {
+    return this.reservationName != null;
+  }
+
+  public void setReservationNameIsSet(boolean value) {
+    if (!value) {
+      this.reservationName = null;
+    }
+  }
+
+  public int getQueueNamesSize() {
+    return (this.queueNames == null) ? 0 : this.queueNames.size();
+  }
+
+  public java.util.Iterator<java.lang.String> getQueueNamesIterator() {
+    return (this.queueNames == null) ? null : this.queueNames.iterator();
+  }
+
+  public void addToQueueNames(java.lang.String elem) {
+    if (this.queueNames == null) {
+      this.queueNames = new java.util.ArrayList<java.lang.String>();
+    }
+    this.queueNames.add(elem);
+  }
+
+  public java.util.List<java.lang.String> getQueueNames() {
+    return this.queueNames;
+  }
+
+  public void setQueueNames(java.util.List<java.lang.String> queueNames) {
+    this.queueNames = queueNames;
+  }
+
+  public void unsetQueueNames() {
+    this.queueNames = null;
+  }
+
+  /** Returns true if field queueNames is set (has been assigned a value) and false otherwise */
+  public boolean isSetQueueNames() {
+    return this.queueNames != null;
+  }
+
+  public void setQueueNamesIsSet(boolean value) {
+    if (!value) {
+      this.queueNames = null;
+    }
+  }
+
+  public long getStartTime() {
+    return this.startTime;
+  }
+
+  public void setStartTime(long startTime) {
+    this.startTime = startTime;
+    setStartTimeIsSet(true);
+  }
+
+  public void unsetStartTime() {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __STARTTIME_ISSET_ID);
+  }
+
+  /** Returns true if field startTime is set (has been assigned a value) and false otherwise */
+  public boolean isSetStartTime() {
+    return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __STARTTIME_ISSET_ID);
+  }
+
+  public void setStartTimeIsSet(boolean value) {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __STARTTIME_ISSET_ID, value);
+  }
+
+  public long getEndTime() {
+    return this.endTime;
+  }
+
+  public void setEndTime(long endTime) {
+    this.endTime = endTime;
+    setEndTimeIsSet(true);
+  }
+
+  public void unsetEndTime() {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __ENDTIME_ISSET_ID);
+  }
+
+  /** Returns true if field endTime is set (has been assigned a value) and false otherwise */
+  public boolean isSetEndTime() {
+    return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __ENDTIME_ISSET_ID);
+  }
+
+  public void setEndTimeIsSet(boolean value) {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __ENDTIME_ISSET_ID, value);
+  }
+
+  public void setFieldValue(_Fields field, java.lang.Object value) {
+    switch (field) {
+    case RESERVATION_ID:
+      if (value == null) {
+        unsetReservationId();
+      } else {
+        setReservationId((java.lang.String)value);
+      }
+      break;
+
+    case RESERVATION_NAME:
+      if (value == null) {
+        unsetReservationName();
+      } else {
+        setReservationName((java.lang.String)value);
+      }
+      break;
+
+    case QUEUE_NAMES:
+      if (value == null) {
+        unsetQueueNames();
+      } else {
+        setQueueNames((java.util.List<java.lang.String>)value);
+      }
+      break;
+
+    case START_TIME:
+      if (value == null) {
+        unsetStartTime();
+      } else {
+        setStartTime((java.lang.Long)value);
+      }
+      break;
+
+    case END_TIME:
+      if (value == null) {
+        unsetEndTime();
+      } else {
+        setEndTime((java.lang.Long)value);
+      }
+      break;
+
+    }
+  }
+
+  public java.lang.Object getFieldValue(_Fields field) {
+    switch (field) {
+    case RESERVATION_ID:
+      return getReservationId();
+
+    case RESERVATION_NAME:
+      return getReservationName();
+
+    case QUEUE_NAMES:
+      return getQueueNames();
+
+    case START_TIME:
+      return getStartTime();
+
+    case END_TIME:
+      return getEndTime();
+
+    }
+    throw new java.lang.IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new java.lang.IllegalArgumentException();
+    }
+
+    switch (field) {
+    case RESERVATION_ID:
+      return isSetReservationId();
+    case RESERVATION_NAME:
+      return isSetReservationName();
+    case QUEUE_NAMES:
+      return isSetQueueNames();
+    case START_TIME:
+      return isSetStartTime();
+    case END_TIME:
+      return isSetEndTime();
+    }
+    throw new java.lang.IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(java.lang.Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof ComputeResourceReservation)
+      return this.equals((ComputeResourceReservation)that);
+    return false;
+  }
+
+  public boolean equals(ComputeResourceReservation that) {
+    if (that == null)
+      return false;
+    if (this == that)
+      return true;
+
+    boolean this_present_reservationId = true && this.isSetReservationId();
+    boolean that_present_reservationId = true && that.isSetReservationId();
+    if (this_present_reservationId || that_present_reservationId) {
+      if (!(this_present_reservationId && that_present_reservationId))
+        return false;
+      if (!this.reservationId.equals(that.reservationId))
+        return false;
+    }
+
+    boolean this_present_reservationName = true && this.isSetReservationName();
+    boolean that_present_reservationName = true && that.isSetReservationName();
+    if (this_present_reservationName || that_present_reservationName) {
+      if (!(this_present_reservationName && that_present_reservationName))
+        return false;
+      if (!this.reservationName.equals(that.reservationName))
+        return false;
+    }
+
+    boolean this_present_queueNames = true && this.isSetQueueNames();
+    boolean that_present_queueNames = true && that.isSetQueueNames();
+    if (this_present_queueNames || that_present_queueNames) {
+      if (!(this_present_queueNames && that_present_queueNames))
+        return false;
+      if (!this.queueNames.equals(that.queueNames))
+        return false;
+    }
+
+    boolean this_present_startTime = true;
+    boolean that_present_startTime = true;
+    if (this_present_startTime || that_present_startTime) {
+      if (!(this_present_startTime && that_present_startTime))
+        return false;
+      if (this.startTime != that.startTime)
+        return false;
+    }
+
+    boolean this_present_endTime = true;
+    boolean that_present_endTime = true;
+    if (this_present_endTime || that_present_endTime) {
+      if (!(this_present_endTime && that_present_endTime))
+        return false;
+      if (this.endTime != that.endTime)
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 1;
+
+    hashCode = hashCode * 8191 + ((isSetReservationId()) ? 131071 : 524287);
+    if (isSetReservationId())
+      hashCode = hashCode * 8191 + reservationId.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetReservationName()) ? 131071 : 524287);
+    if (isSetReservationName())
+      hashCode = hashCode * 8191 + reservationName.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetQueueNames()) ? 131071 : 524287);
+    if (isSetQueueNames())
+      hashCode = hashCode * 8191 + queueNames.hashCode();
+
+    hashCode = hashCode * 8191 + org.apache.thrift.TBaseHelper.hashCode(startTime);
+
+    hashCode = hashCode * 8191 + org.apache.thrift.TBaseHelper.hashCode(endTime);
+
+    return hashCode;
+  }
+
+  @Override
+  public int compareTo(ComputeResourceReservation other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = java.lang.Boolean.valueOf(isSetReservationId()).compareTo(other.isSetReservationId());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetReservationId()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reservationId, other.reservationId);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = java.lang.Boolean.valueOf(isSetReservationName()).compareTo(other.isSetReservationName());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetReservationName()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reservationName, other.reservationName);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = java.lang.Boolean.valueOf(isSetQueueNames()).compareTo(other.isSetQueueNames());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetQueueNames()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.queueNames, other.queueNames);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = java.lang.Boolean.valueOf(isSetStartTime()).compareTo(other.isSetStartTime());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetStartTime()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.startTime, other.startTime);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = java.lang.Boolean.valueOf(isSetEndTime()).compareTo(other.isSetEndTime());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetEndTime()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.endTime, other.endTime);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
+  }
+
+  @Override
+  public java.lang.String toString() {
+    java.lang.StringBuilder sb = new java.lang.StringBuilder("ComputeResourceReservation(");
+    boolean first = true;
+
+    sb.append("reservationId:");
+    if (this.reservationId == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.reservationId);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("reservationName:");
+    if (this.reservationName == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.reservationName);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("queueNames:");
+    if (this.queueNames == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.queueNames);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("startTime:");
+    sb.append(this.startTime);
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("endTime:");
+    sb.append(this.endTime);
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    if (!isSetReservationId()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'reservationId' is unset! Struct:" + toString());
+    }
+
+    if (!isSetReservationName()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'reservationName' is unset! Struct:" + toString());
+    }
+
+    if (!isSetQueueNames()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'queueNames' is unset! Struct:" + toString());
+    }
+
+    if (!isSetStartTime()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'startTime' is unset! Struct:" + toString());
+    }
+
+    if (!isSetEndTime()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'endTime' is unset! Struct:" + toString());
+    }
+
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
+    try {
+      // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+      __isset_bitfield = 0;
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class ComputeResourceReservationStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public ComputeResourceReservationStandardScheme getScheme() {
+      return new ComputeResourceReservationStandardScheme();
+    }
+  }
+
+  private static class ComputeResourceReservationStandardScheme extends org.apache.thrift.scheme.StandardScheme<ComputeResourceReservation> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, ComputeResourceReservation struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // RESERVATION_ID
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.reservationId = iprot.readString();
+              struct.setReservationIdIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 2: // RESERVATION_NAME
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.reservationName = iprot.readString();
+              struct.setReservationNameIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 3: // QUEUE_NAMES
+            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
+              {
+                org.apache.thrift.protocol.TList _list16 = iprot.readListBegin();
+                struct.queueNames = new java.util.ArrayList<java.lang.String>(_list16.size);
+                java.lang.String _elem17;
+                for (int _i18 = 0; _i18 < _list16.size; ++_i18)
+                {
+                  _elem17 = iprot.readString();
+                  struct.queueNames.add(_elem17);
+                }
+                iprot.readListEnd();
+              }
+              struct.setQueueNamesIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 4: // START_TIME
+            if (schemeField.type == org.apache.thrift.protocol.TType.I64) {
+              struct.startTime = iprot.readI64();
+              struct.setStartTimeIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 5: // END_TIME
+            if (schemeField.type == org.apache.thrift.protocol.TType.I64) {
+              struct.endTime = iprot.readI64();
+              struct.setEndTimeIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, ComputeResourceReservation struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.reservationId != null) {
+        oprot.writeFieldBegin(RESERVATION_ID_FIELD_DESC);
+        oprot.writeString(struct.reservationId);
+        oprot.writeFieldEnd();
+      }
+      if (struct.reservationName != null) {
+        oprot.writeFieldBegin(RESERVATION_NAME_FIELD_DESC);
+        oprot.writeString(struct.reservationName);
+        oprot.writeFieldEnd();
+      }
+      if (struct.queueNames != null) {
+        oprot.writeFieldBegin(QUEUE_NAMES_FIELD_DESC);
+        {
+          oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.queueNames.size()));
+          for (java.lang.String _iter19 : struct.queueNames)
+          {
+            oprot.writeString(_iter19);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldBegin(START_TIME_FIELD_DESC);
+      oprot.writeI64(struct.startTime);
+      oprot.writeFieldEnd();
+      oprot.writeFieldBegin(END_TIME_FIELD_DESC);
+      oprot.writeI64(struct.endTime);
+      oprot.writeFieldEnd();
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class ComputeResourceReservationTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public ComputeResourceReservationTupleScheme getScheme() {
+      return new ComputeResourceReservationTupleScheme();
+    }
+  }
+
+  private static class ComputeResourceReservationTupleScheme extends org.apache.thrift.scheme.TupleScheme<ComputeResourceReservation> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, ComputeResourceReservation struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      oprot.writeString(struct.reservationId);
+      oprot.writeString(struct.reservationName);
+      {
+        oprot.writeI32(struct.queueNames.size());
+        for (java.lang.String _iter20 : struct.queueNames)
+        {
+          oprot.writeString(_iter20);
+        }
+      }
+      oprot.writeI64(struct.startTime);
+      oprot.writeI64(struct.endTime);
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, ComputeResourceReservation struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      struct.reservationId = iprot.readString();
+      struct.setReservationIdIsSet(true);
+      struct.reservationName = iprot.readString();
+      struct.setReservationNameIsSet(true);
+      {
+        org.apache.thrift.protocol.TList _list21 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+        struct.queueNames = new java.util.ArrayList<java.lang.String>(_list21.size);
+        java.lang.String _elem22;
+        for (int _i23 = 0; _i23 < _list21.size; ++_i23)
+        {
+          _elem22 = iprot.readString();
+          struct.queueNames.add(_elem22);
+        }
+      }
+      struct.setQueueNamesIsSet(true);
+      struct.startTime = iprot.readI64();
+      struct.setStartTimeIsSet(true);
+      struct.endTime = iprot.readI64();
+      struct.setEndTimeIsSet(true);
+    }
+  }
+
+  private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
+    return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
+  }
+}
+
diff --git a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupComputeResourcePreference.java b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupComputeResourcePreference.java
index 32c0c42..f43c58b 100644
--- a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupComputeResourcePreference.java
+++ b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupComputeResourcePreference.java
@@ -46,6 +46,7 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
   private static final org.apache.thrift.protocol.TField SSH_ACCOUNT_PROVISIONER_FIELD_DESC = new org.apache.thrift.protocol.TField("sshAccountProvisioner", org.apache.thrift.protocol.TType.STRING, (short)16);
   private static final org.apache.thrift.protocol.TField GROUP_SSHACCOUNT_PROVISIONER_CONFIGS_FIELD_DESC = new org.apache.thrift.protocol.TField("groupSSHAccountProvisionerConfigs", org.apache.thrift.protocol.TType.LIST, (short)17);
   private static final org.apache.thrift.protocol.TField SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO_FIELD_DESC = new org.apache.thrift.protocol.TField("sshAccountProvisionerAdditionalInfo", org.apache.thrift.protocol.TType.STRING, (short)18);
+  private static final org.apache.thrift.protocol.TField RESERVATIONS_FIELD_DESC = new org.apache.thrift.protocol.TField("reservations", org.apache.thrift.protocol.TType.LIST, (short)19);
 
   private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new GroupComputeResourcePreferenceStandardSchemeFactory();
   private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new GroupComputeResourcePreferenceTupleSchemeFactory();
@@ -68,6 +69,7 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
   private java.lang.String sshAccountProvisioner; // optional
   private java.util.List<GroupAccountSSHProvisionerConfig> groupSSHAccountProvisionerConfigs; // optional
   private java.lang.String sshAccountProvisionerAdditionalInfo; // optional
+  private java.util.List<ComputeResourceReservation> reservations; // optional
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
@@ -96,7 +98,8 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
     RESERVATION_END_TIME((short)15, "reservationEndTime"),
     SSH_ACCOUNT_PROVISIONER((short)16, "sshAccountProvisioner"),
     GROUP_SSHACCOUNT_PROVISIONER_CONFIGS((short)17, "groupSSHAccountProvisionerConfigs"),
-    SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO((short)18, "sshAccountProvisionerAdditionalInfo");
+    SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO((short)18, "sshAccountProvisionerAdditionalInfo"),
+    RESERVATIONS((short)19, "reservations");
 
     private static final java.util.Map<java.lang.String, _Fields> byName = new java.util.HashMap<java.lang.String, _Fields>();
 
@@ -147,6 +150,8 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
           return GROUP_SSHACCOUNT_PROVISIONER_CONFIGS;
         case 18: // SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO
           return SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO;
+        case 19: // RESERVATIONS
+          return RESERVATIONS;
         default:
           return null;
       }
@@ -191,7 +196,7 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
   private static final int __RESERVATIONSTARTTIME_ISSET_ID = 1;
   private static final int __RESERVATIONENDTIME_ISSET_ID = 2;
   private byte __isset_bitfield = 0;
-  private static final _Fields optionals[] = {_Fields.LOGIN_USER_NAME,_Fields.PREFERRED_JOB_SUBMISSION_PROTOCOL,_Fields.PREFERRED_DATA_MOVEMENT_PROTOCOL,_Fields.PREFERRED_BATCH_QUEUE,_Fields.SCRATCH_LOCATION,_Fields.ALLOCATION_PROJECT_NUMBER,_Fields.RESOURCE_SPECIFIC_CREDENTIAL_STORE_TOKEN,_Fields.USAGE_REPORTING_GATEWAY_ID,_Fields.QUALITY_OF_SERVICE,_Fields.RESERVATION,_Fields.RESERVATION_START_TIME,_Fields.RESERVATION_END_TIME,_Fields.SSH_ACCOUNT_PROVISIONER,_Fields.GROUP_SSHACCOUNT_PR [...]
+  private static final _Fields optionals[] = {_Fields.LOGIN_USER_NAME,_Fields.PREFERRED_JOB_SUBMISSION_PROTOCOL,_Fields.PREFERRED_DATA_MOVEMENT_PROTOCOL,_Fields.PREFERRED_BATCH_QUEUE,_Fields.SCRATCH_LOCATION,_Fields.ALLOCATION_PROJECT_NUMBER,_Fields.RESOURCE_SPECIFIC_CREDENTIAL_STORE_TOKEN,_Fields.USAGE_REPORTING_GATEWAY_ID,_Fields.QUALITY_OF_SERVICE,_Fields.RESERVATION,_Fields.RESERVATION_START_TIME,_Fields.RESERVATION_END_TIME,_Fields.SSH_ACCOUNT_PROVISIONER,_Fields.GROUP_SSHACCOUNT_PR [...]
   public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
   static {
     java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
@@ -232,6 +237,9 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
             new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, GroupAccountSSHProvisionerConfig.class))));
     tmpMap.put(_Fields.SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO, new org.apache.thrift.meta_data.FieldMetaData("sshAccountProvisionerAdditionalInfo", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.RESERVATIONS, new org.apache.thrift.meta_data.FieldMetaData("reservations", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT            , "ComputeResourceReservation"))));
     metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(GroupComputeResourcePreference.class, metaDataMap);
   }
@@ -312,6 +320,13 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
     if (other.isSetSshAccountProvisionerAdditionalInfo()) {
       this.sshAccountProvisionerAdditionalInfo = other.sshAccountProvisionerAdditionalInfo;
     }
+    if (other.isSetReservations()) {
+      java.util.List<ComputeResourceReservation> __this__reservations = new java.util.ArrayList<ComputeResourceReservation>(other.reservations.size());
+      for (ComputeResourceReservation other_element : other.reservations) {
+        __this__reservations.add(other_element);
+      }
+      this.reservations = __this__reservations;
+    }
   }
 
   public GroupComputeResourcePreference deepCopy() {
@@ -342,6 +357,7 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
     this.sshAccountProvisioner = null;
     this.groupSSHAccountProvisionerConfigs = null;
     this.sshAccountProvisionerAdditionalInfo = null;
+    this.reservations = null;
   }
 
   public java.lang.String getComputeResourceId() {
@@ -786,6 +802,44 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
     }
   }
 
+  public int getReservationsSize() {
+    return (this.reservations == null) ? 0 : this.reservations.size();
+  }
+
+  public java.util.Iterator<ComputeResourceReservation> getReservationsIterator() {
+    return (this.reservations == null) ? null : this.reservations.iterator();
+  }
+
+  public void addToReservations(ComputeResourceReservation elem) {
+    if (this.reservations == null) {
+      this.reservations = new java.util.ArrayList<ComputeResourceReservation>();
+    }
+    this.reservations.add(elem);
+  }
+
+  public java.util.List<ComputeResourceReservation> getReservations() {
+    return this.reservations;
+  }
+
+  public void setReservations(java.util.List<ComputeResourceReservation> reservations) {
+    this.reservations = reservations;
+  }
+
+  public void unsetReservations() {
+    this.reservations = null;
+  }
+
+  /** Returns true if field reservations is set (has been assigned a value) and false otherwise */
+  public boolean isSetReservations() {
+    return this.reservations != null;
+  }
+
+  public void setReservationsIsSet(boolean value) {
+    if (!value) {
+      this.reservations = null;
+    }
+  }
+
   public void setFieldValue(_Fields field, java.lang.Object value) {
     switch (field) {
     case COMPUTE_RESOURCE_ID:
@@ -932,6 +986,14 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       }
       break;
 
+    case RESERVATIONS:
+      if (value == null) {
+        unsetReservations();
+      } else {
+        setReservations((java.util.List<ComputeResourceReservation>)value);
+      }
+      break;
+
     }
   }
 
@@ -991,6 +1053,9 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
     case SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO:
       return getSshAccountProvisionerAdditionalInfo();
 
+    case RESERVATIONS:
+      return getReservations();
+
     }
     throw new java.lang.IllegalStateException();
   }
@@ -1038,6 +1103,8 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       return isSetGroupSSHAccountProvisionerConfigs();
     case SSH_ACCOUNT_PROVISIONER_ADDITIONAL_INFO:
       return isSetSshAccountProvisionerAdditionalInfo();
+    case RESERVATIONS:
+      return isSetReservations();
     }
     throw new java.lang.IllegalStateException();
   }
@@ -1219,6 +1286,15 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
         return false;
     }
 
+    boolean this_present_reservations = true && this.isSetReservations();
+    boolean that_present_reservations = true && that.isSetReservations();
+    if (this_present_reservations || that_present_reservations) {
+      if (!(this_present_reservations && that_present_reservations))
+        return false;
+      if (!this.reservations.equals(that.reservations))
+        return false;
+    }
+
     return true;
   }
 
@@ -1296,6 +1372,10 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
     if (isSetSshAccountProvisionerAdditionalInfo())
       hashCode = hashCode * 8191 + sshAccountProvisionerAdditionalInfo.hashCode();
 
+    hashCode = hashCode * 8191 + ((isSetReservations()) ? 131071 : 524287);
+    if (isSetReservations())
+      hashCode = hashCode * 8191 + reservations.hashCode();
+
     return hashCode;
   }
 
@@ -1487,6 +1567,16 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
         return lastComparison;
       }
     }
+    lastComparison = java.lang.Boolean.valueOf(isSetReservations()).compareTo(other.isSetReservations());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetReservations()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reservations, other.reservations);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     return 0;
   }
 
@@ -1668,6 +1758,16 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       }
       first = false;
     }
+    if (isSetReservations()) {
+      if (!first) sb.append(", ");
+      sb.append("reservations:");
+      if (this.reservations == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.reservations);
+      }
+      first = false;
+    }
     sb.append(")");
     return sb.toString();
   }
@@ -1880,6 +1980,25 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
+          case 19: // RESERVATIONS
+            if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
+              {
+                org.apache.thrift.protocol.TList _list3 = iprot.readListBegin();
+                struct.reservations = new java.util.ArrayList<ComputeResourceReservation>(_list3.size);
+                ComputeResourceReservation _elem4;
+                for (int _i5 = 0; _i5 < _list3.size; ++_i5)
+                {
+                  _elem4 = new ComputeResourceReservation();
+                  _elem4.read(iprot);
+                  struct.reservations.add(_elem4);
+                }
+                iprot.readListEnd();
+              }
+              struct.setReservationsIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
           default:
             org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
         }
@@ -1998,9 +2117,9 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
           oprot.writeFieldBegin(GROUP_SSHACCOUNT_PROVISIONER_CONFIGS_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.groupSSHAccountProvisionerConfigs.size()));
-            for (GroupAccountSSHProvisionerConfig _iter3 : struct.groupSSHAccountProvisionerConfigs)
+            for (GroupAccountSSHProvisionerConfig _iter6 : struct.groupSSHAccountProvisionerConfigs)
             {
-              _iter3.write(oprot);
+              _iter6.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -2014,6 +2133,20 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
           oprot.writeFieldEnd();
         }
       }
+      if (struct.reservations != null) {
+        if (struct.isSetReservations()) {
+          oprot.writeFieldBegin(RESERVATIONS_FIELD_DESC);
+          {
+            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.reservations.size()));
+            for (ComputeResourceReservation _iter7 : struct.reservations)
+            {
+              _iter7.write(oprot);
+            }
+            oprot.writeListEnd();
+          }
+          oprot.writeFieldEnd();
+        }
+      }
       oprot.writeFieldStop();
       oprot.writeStructEnd();
     }
@@ -2080,7 +2213,10 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       if (struct.isSetSshAccountProvisionerAdditionalInfo()) {
         optionals.set(14);
       }
-      oprot.writeBitSet(optionals, 15);
+      if (struct.isSetReservations()) {
+        optionals.set(15);
+      }
+      oprot.writeBitSet(optionals, 16);
       if (struct.isSetLoginUserName()) {
         oprot.writeString(struct.loginUserName);
       }
@@ -2123,15 +2259,24 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       if (struct.isSetGroupSSHAccountProvisionerConfigs()) {
         {
           oprot.writeI32(struct.groupSSHAccountProvisionerConfigs.size());
-          for (GroupAccountSSHProvisionerConfig _iter4 : struct.groupSSHAccountProvisionerConfigs)
+          for (GroupAccountSSHProvisionerConfig _iter8 : struct.groupSSHAccountProvisionerConfigs)
           {
-            _iter4.write(oprot);
+            _iter8.write(oprot);
           }
         }
       }
       if (struct.isSetSshAccountProvisionerAdditionalInfo()) {
         oprot.writeString(struct.sshAccountProvisionerAdditionalInfo);
       }
+      if (struct.isSetReservations()) {
+        {
+          oprot.writeI32(struct.reservations.size());
+          for (ComputeResourceReservation _iter9 : struct.reservations)
+          {
+            _iter9.write(oprot);
+          }
+        }
+      }
     }
 
     @Override
@@ -2143,7 +2288,7 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       struct.setGroupResourceProfileIdIsSet(true);
       struct.overridebyAiravata = iprot.readBool();
       struct.setOverridebyAiravataIsSet(true);
-      java.util.BitSet incoming = iprot.readBitSet(15);
+      java.util.BitSet incoming = iprot.readBitSet(16);
       if (incoming.get(0)) {
         struct.loginUserName = iprot.readString();
         struct.setLoginUserNameIsSet(true);
@@ -2198,14 +2343,14 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
       }
       if (incoming.get(13)) {
         {
-          org.apache.thrift.protocol.TList _list5 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.groupSSHAccountProvisionerConfigs = new java.util.ArrayList<GroupAccountSSHProvisionerConfig>(_list5.size);
-          GroupAccountSSHProvisionerConfig _elem6;
-          for (int _i7 = 0; _i7 < _list5.size; ++_i7)
+          org.apache.thrift.protocol.TList _list10 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.groupSSHAccountProvisionerConfigs = new java.util.ArrayList<GroupAccountSSHProvisionerConfig>(_list10.size);
+          GroupAccountSSHProvisionerConfig _elem11;
+          for (int _i12 = 0; _i12 < _list10.size; ++_i12)
           {
-            _elem6 = new GroupAccountSSHProvisionerConfig();
-            _elem6.read(iprot);
-            struct.groupSSHAccountProvisionerConfigs.add(_elem6);
+            _elem11 = new GroupAccountSSHProvisionerConfig();
+            _elem11.read(iprot);
+            struct.groupSSHAccountProvisionerConfigs.add(_elem11);
           }
         }
         struct.setGroupSSHAccountProvisionerConfigsIsSet(true);
@@ -2214,6 +2359,20 @@ public class GroupComputeResourcePreference implements org.apache.thrift.TBase<G
         struct.sshAccountProvisionerAdditionalInfo = iprot.readString();
         struct.setSshAccountProvisionerAdditionalInfoIsSet(true);
       }
+      if (incoming.get(15)) {
+        {
+          org.apache.thrift.protocol.TList _list13 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.reservations = new java.util.ArrayList<ComputeResourceReservation>(_list13.size);
+          ComputeResourceReservation _elem14;
+          for (int _i15 = 0; _i15 < _list13.size; ++_i15)
+          {
+            _elem14 = new ComputeResourceReservation();
+            _elem14.read(iprot);
+            struct.reservations.add(_elem14);
+          }
+        }
+        struct.setReservationsIsSet(true);
+      }
     }
   }
 
diff --git a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupResourceProfile.java b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupResourceProfile.java
index e9eef80..b6e4526 100644
--- a/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupResourceProfile.java
+++ b/airavata-api/airavata-data-models/src/main/java/org/apache/airavata/model/appcatalog/groupresourceprofile/GroupResourceProfile.java
@@ -1069,14 +1069,14 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
           case 4: // COMPUTE_PREFERENCES
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list16 = iprot.readListBegin();
-                struct.computePreferences = new java.util.ArrayList<GroupComputeResourcePreference>(_list16.size);
-                GroupComputeResourcePreference _elem17;
-                for (int _i18 = 0; _i18 < _list16.size; ++_i18)
+                org.apache.thrift.protocol.TList _list32 = iprot.readListBegin();
+                struct.computePreferences = new java.util.ArrayList<GroupComputeResourcePreference>(_list32.size);
+                GroupComputeResourcePreference _elem33;
+                for (int _i34 = 0; _i34 < _list32.size; ++_i34)
                 {
-                  _elem17 = new GroupComputeResourcePreference();
-                  _elem17.read(iprot);
-                  struct.computePreferences.add(_elem17);
+                  _elem33 = new GroupComputeResourcePreference();
+                  _elem33.read(iprot);
+                  struct.computePreferences.add(_elem33);
                 }
                 iprot.readListEnd();
               }
@@ -1088,14 +1088,14 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
           case 5: // COMPUTE_RESOURCE_POLICIES
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list19 = iprot.readListBegin();
-                struct.computeResourcePolicies = new java.util.ArrayList<ComputeResourcePolicy>(_list19.size);
-                ComputeResourcePolicy _elem20;
-                for (int _i21 = 0; _i21 < _list19.size; ++_i21)
+                org.apache.thrift.protocol.TList _list35 = iprot.readListBegin();
+                struct.computeResourcePolicies = new java.util.ArrayList<ComputeResourcePolicy>(_list35.size);
+                ComputeResourcePolicy _elem36;
+                for (int _i37 = 0; _i37 < _list35.size; ++_i37)
                 {
-                  _elem20 = new ComputeResourcePolicy();
-                  _elem20.read(iprot);
-                  struct.computeResourcePolicies.add(_elem20);
+                  _elem36 = new ComputeResourcePolicy();
+                  _elem36.read(iprot);
+                  struct.computeResourcePolicies.add(_elem36);
                 }
                 iprot.readListEnd();
               }
@@ -1107,14 +1107,14 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
           case 6: // BATCH_QUEUE_RESOURCE_POLICIES
             if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list22 = iprot.readListBegin();
-                struct.batchQueueResourcePolicies = new java.util.ArrayList<BatchQueueResourcePolicy>(_list22.size);
-                BatchQueueResourcePolicy _elem23;
-                for (int _i24 = 0; _i24 < _list22.size; ++_i24)
+                org.apache.thrift.protocol.TList _list38 = iprot.readListBegin();
+                struct.batchQueueResourcePolicies = new java.util.ArrayList<BatchQueueResourcePolicy>(_list38.size);
+                BatchQueueResourcePolicy _elem39;
+                for (int _i40 = 0; _i40 < _list38.size; ++_i40)
                 {
-                  _elem23 = new BatchQueueResourcePolicy();
-                  _elem23.read(iprot);
-                  struct.batchQueueResourcePolicies.add(_elem23);
+                  _elem39 = new BatchQueueResourcePolicy();
+                  _elem39.read(iprot);
+                  struct.batchQueueResourcePolicies.add(_elem39);
                 }
                 iprot.readListEnd();
               }
@@ -1182,9 +1182,9 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
           oprot.writeFieldBegin(COMPUTE_PREFERENCES_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.computePreferences.size()));
-            for (GroupComputeResourcePreference _iter25 : struct.computePreferences)
+            for (GroupComputeResourcePreference _iter41 : struct.computePreferences)
             {
-              _iter25.write(oprot);
+              _iter41.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -1196,9 +1196,9 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
           oprot.writeFieldBegin(COMPUTE_RESOURCE_POLICIES_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.computeResourcePolicies.size()));
-            for (ComputeResourcePolicy _iter26 : struct.computeResourcePolicies)
+            for (ComputeResourcePolicy _iter42 : struct.computeResourcePolicies)
             {
-              _iter26.write(oprot);
+              _iter42.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -1210,9 +1210,9 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
           oprot.writeFieldBegin(BATCH_QUEUE_RESOURCE_POLICIES_FIELD_DESC);
           {
             oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.batchQueueResourcePolicies.size()));
-            for (BatchQueueResourcePolicy _iter27 : struct.batchQueueResourcePolicies)
+            for (BatchQueueResourcePolicy _iter43 : struct.batchQueueResourcePolicies)
             {
-              _iter27.write(oprot);
+              _iter43.write(oprot);
             }
             oprot.writeListEnd();
           }
@@ -1284,27 +1284,27 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
       if (struct.isSetComputePreferences()) {
         {
           oprot.writeI32(struct.computePreferences.size());
-          for (GroupComputeResourcePreference _iter28 : struct.computePreferences)
+          for (GroupComputeResourcePreference _iter44 : struct.computePreferences)
           {
-            _iter28.write(oprot);
+            _iter44.write(oprot);
           }
         }
       }
       if (struct.isSetComputeResourcePolicies()) {
         {
           oprot.writeI32(struct.computeResourcePolicies.size());
-          for (ComputeResourcePolicy _iter29 : struct.computeResourcePolicies)
+          for (ComputeResourcePolicy _iter45 : struct.computeResourcePolicies)
           {
-            _iter29.write(oprot);
+            _iter45.write(oprot);
           }
         }
       }
       if (struct.isSetBatchQueueResourcePolicies()) {
         {
           oprot.writeI32(struct.batchQueueResourcePolicies.size());
-          for (BatchQueueResourcePolicy _iter30 : struct.batchQueueResourcePolicies)
+          for (BatchQueueResourcePolicy _iter46 : struct.batchQueueResourcePolicies)
           {
-            _iter30.write(oprot);
+            _iter46.write(oprot);
           }
         }
       }
@@ -1333,42 +1333,42 @@ public class GroupResourceProfile implements org.apache.thrift.TBase<GroupResour
       }
       if (incoming.get(1)) {
         {
-          org.apache.thrift.protocol.TList _list31 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.computePreferences = new java.util.ArrayList<GroupComputeResourcePreference>(_list31.size);
-          GroupComputeResourcePreference _elem32;
-          for (int _i33 = 0; _i33 < _list31.size; ++_i33)
+          org.apache.thrift.protocol.TList _list47 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.computePreferences = new java.util.ArrayList<GroupComputeResourcePreference>(_list47.size);
+          GroupComputeResourcePreference _elem48;
+          for (int _i49 = 0; _i49 < _list47.size; ++_i49)
           {
-            _elem32 = new GroupComputeResourcePreference();
-            _elem32.read(iprot);
-            struct.computePreferences.add(_elem32);
+            _elem48 = new GroupComputeResourcePreference();
+            _elem48.read(iprot);
+            struct.computePreferences.add(_elem48);
           }
         }
         struct.setComputePreferencesIsSet(true);
       }
       if (incoming.get(2)) {
         {
-          org.apache.thrift.protocol.TList _list34 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.computeResourcePolicies = new java.util.ArrayList<ComputeResourcePolicy>(_list34.size);
-          ComputeResourcePolicy _elem35;
-          for (int _i36 = 0; _i36 < _list34.size; ++_i36)
+          org.apache.thrift.protocol.TList _list50 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.computeResourcePolicies = new java.util.ArrayList<ComputeResourcePolicy>(_list50.size);
+          ComputeResourcePolicy _elem51;
+          for (int _i52 = 0; _i52 < _list50.size; ++_i52)
           {
-            _elem35 = new ComputeResourcePolicy();
-            _elem35.read(iprot);
-            struct.computeResourcePolicies.add(_elem35);
+            _elem51 = new ComputeResourcePolicy();
+            _elem51.read(iprot);
+            struct.computeResourcePolicies.add(_elem51);
           }
         }
         struct.setComputeResourcePoliciesIsSet(true);
       }
       if (incoming.get(3)) {
         {
-          org.apache.thrift.protocol.TList _list37 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
-          struct.batchQueueResourcePolicies = new java.util.ArrayList<BatchQueueResourcePolicy>(_list37.size);
-          BatchQueueResourcePolicy _elem38;
-          for (int _i39 = 0; _i39 < _list37.size; ++_i39)
+          org.apache.thrift.protocol.TList _list53 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+          struct.batchQueueResourcePolicies = new java.util.ArrayList<BatchQueueResourcePolicy>(_list53.size);
+          BatchQueueResourcePolicy _elem54;
+          for (int _i55 = 0; _i55 < _list53.size; ++_i55)
           {
-            _elem38 = new BatchQueueResourcePolicy();
-            _elem38.read(iprot);
-            struct.batchQueueResourcePolicies.add(_elem38);
+            _elem54 = new BatchQueueResourcePolicy();
+            _elem54.read(iprot);
+            struct.batchQueueResourcePolicies.add(_elem54);
           }
         }
         struct.setBatchQueueResourcePoliciesIsSet(true);
diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/JPAUtils.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/JPAUtils.java
index 49c0686..64395ff 100644
--- a/modules/commons/src/main/java/org/apache/airavata/common/utils/JPAUtils.java
+++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/JPAUtils.java
@@ -7,6 +7,8 @@ import java.util.Map;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
 
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -24,6 +26,8 @@ public class JPAUtils {
         properties.put("openjpa.RuntimeUnenhancedClasses", "unsupported");
         properties.put("openjpa.RemoteCommitProvider", "sjvm");
         properties.put("openjpa.Log", "DefaultLevel=INFO, Runtime=INFO, Tool=INFO, SQL=INFO");
+        // use the following to enable logging of all SQL statements
+        // properties.put("openjpa.Log", "DefaultLevel=INFO, Runtime=INFO, Tool=INFO, SQL=TRACE");
         properties.put("openjpa.jdbc.SynchronizeMappings", "validate");
         properties.put("openjpa.jdbc.QuerySQLCache", "false");
         properties.put("openjpa.DetachState", "all");
@@ -58,6 +62,15 @@ public class JPAUtils {
         return Persistence.createEntityManagerFactory(persistenceUnitName, finalProperties);
     }
 
+    public static JDBCConfiguration getJDBCConfiguration(JDBCConfig jdbcConfig) {
+
+        Map<String, String> finalProperties = new HashMap<>(DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES);
+        finalProperties.putAll(createConnectionProperties(jdbcConfig));
+        JDBCConfiguration jdbcConfiguration = new JDBCConfigurationImpl();
+        jdbcConfiguration.fromProperties(finalProperties);
+        return jdbcConfiguration;
+    }
+
     private static Map<String, String> createConnectionProperties(JDBCConfig jdbcConfig) {
         String connectionProperties = "DriverClassName=" + jdbcConfig.getDriver() + "," + "Url=" + jdbcConfig.getURL()
                 + "?autoReconnect=true," + "Username=" + jdbcConfig.getUser() + "," + "Password="
diff --git a/modules/ide-integration/src/main/resources/META-INF/persistence.xml b/modules/ide-integration/src/main/resources/META-INF/persistence.xml
index 7ace098..9f6fe1e 100644
--- a/modules/ide-integration/src/main/resources/META-INF/persistence.xml
+++ b/modules/ide-integration/src/main/resources/META-INF/persistence.xml
@@ -79,6 +79,7 @@
         <class>org.apache.airavata.registry.core.entities.appcatalog.ParsingTemplateInputEntity</class>
         <class>org.apache.airavata.registry.core.entities.appcatalog.ParserConnectorInputEntity</class>
         <class>org.apache.airavata.registry.core.entities.appcatalog.ParserConnectorEntity</class>
+        <class>org.apache.airavata.registry.core.entities.appcatalog.ComputeResourceReservationEntity</class>
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
     </persistence-unit>
     <persistence-unit name="replicacatalog_data_new">
diff --git a/modules/ide-integration/src/main/resources/database_scripts/init/03-appcatalog-migrations.sql b/modules/ide-integration/src/main/resources/database_scripts/init/03-appcatalog-migrations.sql
new file mode 100644
index 0000000..a07c0f0
--- /dev/null
+++ b/modules/ide-integration/src/main/resources/database_scripts/init/03-appcatalog-migrations.sql
@@ -0,0 +1,10 @@
+use app_catalog;
+
+-- AIRAVATA-3126
+CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
+    (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
+)ENGINE=InnoDB DEFAULT CHARSET=latin1;
+CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL
+)ENGINE=InnoDB DEFAULT CHARSET=latin1;
+CREATE INDEX I_CMPTN_Q_RESERVATION_ID ON COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID);
+ALTER TABLE COMPUTE_RESOURCE_RESERVATION ADD CONSTRAINT FK_COMPUTE_RESOURCE_RESERVATION FOREIGN KEY (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_COMPUTE_RESOURCE_PREFERENCE (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE;
diff --git a/modules/registry/registry-core/README.md b/modules/registry/registry-core/README.md
new file mode 100644
index 0000000..0a9de7f
--- /dev/null
+++ b/modules/registry/registry-core/README.md
@@ -0,0 +1,13 @@
+
+# migration.sql
+
+- copy to appcatalog-derby.sql. if changing a column, make the change to the create table statement directly.
+- copy to appcatalog-mysql.sql, translating as needed
+- copy mysql version to release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql. Add IF NOT EXISTS so it is re-runnable. Name foreign keys.
+- copy same mysql version to ide-integration 0*-migrations.sql
+
+# ide-integration
+
+- file is stored in airavata/migration.sql
+- probably want to start with the derby one generated by the unit tests though
+- need to add new Entity classes to ide-integration/.../persistence.xml
diff --git a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/ComputeResourceReservationEntity.java
similarity index 52%
copy from modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java
copy to modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/ComputeResourceReservationEntity.java
index 1241144..3948098 100644
--- a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java
+++ b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/ComputeResourceReservationEntity.java
@@ -19,86 +19,103 @@
  */
 package org.apache.airavata.registry.core.entities.appcatalog;
 
-import org.apache.openjpa.persistence.jdbc.ForeignKey;
-import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
+import java.io.Serializable;
+import java.sql.Timestamp;
+import java.util.List;
 
 import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
 import javax.persistence.Column;
+import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.Id;
-import javax.persistence.IdClass;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import java.io.Serializable;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
 
 /**
- * The persistent class for the grp_ssh_acc_prov_config database table.
+ * The persistent class for the COMPUTE_RESOURCE_RESERVATION database table.
  */
 @Entity
-@Table(name = "GRP_SSH_ACC_PROV_CONFIG")
-@IdClass(GroupSSHAccountProvisionerConfigPK.class)
-public class GroupSSHAccountProvisionerConfig implements Serializable{
+@Table(name = "COMPUTE_RESOURCE_RESERVATION")
+public class ComputeResourceReservationEntity implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @Id
-    @Column(name = "RESOURCE_ID")
-    private String resourceId;
+    @Column(name = "RESERVATION_ID")
+    private String reservationId;
 
-    @Id
-    @Column(name = "GROUP_RESOURCE_PROFILE_ID")
-    private String groupResourceProfileId;
+    @Column(name = "RESERVATION_NAME", nullable = false)
+    private String reservationName;
 
-    @Id
-    @Column(name = "CONFIG_NAME")
-    private String configName;
+    @Column(name = "START_TIME", nullable = false)
+    private Timestamp startTime;
+
+    @Column(name = "END_TIME", nullable = false)
+    private Timestamp endTime;
 
-    @Column(name = "CONFIG_VALUE")
-    private String configValue;
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name="COMPUTE_RESOURCE_RESERVATION_QUEUE", joinColumns = @JoinColumn(name="RESERVATION_ID"))
+    @Column(name = "QUEUE_NAME", nullable = false)
+    private List<String> queueNames;
 
-    @ManyToOne(targetEntity = GroupComputeResourcePrefEntity.class, cascade= CascadeType.MERGE)
+    // TODO: FK queue table to BatchQueueEntity?
+
+    @ManyToOne(targetEntity = GroupComputeResourcePrefEntity.class)
     @JoinColumns({
-            @JoinColumn(name = "RESOURCE_ID", referencedColumnName = "RESOURCE_ID", nullable = false),
-            @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", referencedColumnName = "GROUP_RESOURCE_PROFILE_ID", nullable = false)
+            @JoinColumn(name = "RESOURCE_ID", referencedColumnName = "RESOURCE_ID", nullable = false, updatable = false),
+            @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", referencedColumnName = "GROUP_RESOURCE_PROFILE_ID", nullable = false, updatable = false)
     })
     @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
     private GroupComputeResourcePrefEntity groupComputeResourcePref;
 
-    public GroupSSHAccountProvisionerConfig() {
+    public ComputeResourceReservationEntity() {
+    }
+
+    public String getReservationId() {
+        return reservationId;
+    }
+
+    public void setReservationId(String reservationId) {
+        this.reservationId = reservationId;
     }
 
-    public String getResourceId() {
-        return resourceId;
+    public String getReservationName() {
+        return reservationName;
     }
 
-    public void setResourceId(String resourceId) {
-        this.resourceId = resourceId;
+    public void setReservationName(String reservationName) {
+        this.reservationName = reservationName;
     }
 
-    public String getGroupResourceProfileId() {
-        return groupResourceProfileId;
+    public Timestamp getStartTime() {
+        return startTime;
     }
 
-    public void setGroupResourceProfileId(String groupResourceProfileId) {
-        this.groupResourceProfileId = groupResourceProfileId;
+    public void setStartTime(Timestamp startTime) {
+        this.startTime = startTime;
     }
 
-    public String getConfigName() {
-        return configName;
+    public Timestamp getEndTime() {
+        return endTime;
     }
 
-    public void setConfigName(String configName) {
-        this.configName = configName;
+    public void setEndTime(Timestamp endTime) {
+        this.endTime = endTime;
     }
 
-    public String getConfigValue() {
-        return configValue;
+    public List<String> getQueueNames() {
+        return queueNames;
     }
 
-    public void setConfigValue(String configValue) {
-        this.configValue = configValue;
+    public void setQueueNames(List<String> queueNames) {
+        this.queueNames = queueNames;
     }
 
     public GroupComputeResourcePrefEntity getGroupComputeResourcePref() {
diff --git a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupComputeResourcePrefEntity.java b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupComputeResourcePrefEntity.java
index 8260764..22e0673 100644
--- a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupComputeResourcePrefEntity.java
+++ b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupComputeResourcePrefEntity.java
@@ -35,6 +35,7 @@ import javax.persistence.IdClass;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
 import javax.persistence.Table;
 import java.io.Serializable;
 import java.sql.Timestamp;
@@ -108,7 +109,11 @@ public class GroupComputeResourcePrefEntity implements Serializable {
     @OneToMany(targetEntity = GroupSSHAccountProvisionerConfig.class, mappedBy = "groupComputeResourcePref", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
     private List<GroupSSHAccountProvisionerConfig> groupSSHAccountProvisionerConfigs;
 
-    @ManyToOne(targetEntity = GroupResourceProfileEntity.class)
+    @OneToMany(targetEntity = ComputeResourceReservationEntity.class, mappedBy = "groupComputeResourcePref", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
+    @OrderBy("startTime ASC")
+    private List<ComputeResourceReservationEntity> reservations;
+
+    @ManyToOne(targetEntity = GroupResourceProfileEntity.class, cascade = CascadeType.PERSIST)
     @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", nullable = false, updatable = false)
     @ForeignKey(deleteAction = ForeignKeyAction.CASCADE)
     private  GroupResourceProfileEntity groupResourceProfile;
@@ -260,6 +265,14 @@ public class GroupComputeResourcePrefEntity implements Serializable {
         this.groupSSHAccountProvisionerConfigs = groupSSHAccountProvisionerConfigs;
     }
 
+    public List<ComputeResourceReservationEntity> getReservations() {
+        return reservations;
+    }
+
+    public void setReservations(List<ComputeResourceReservationEntity> reservations) {
+        this.reservations = reservations;
+    }
+
     public GroupResourceProfileEntity getGroupResourceProfile() {
         return groupResourceProfile;
     }
diff --git a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java
index 1241144..c913d1d 100644
--- a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java
+++ b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/entities/appcatalog/GroupSSHAccountProvisionerConfig.java
@@ -58,7 +58,7 @@ public class GroupSSHAccountProvisionerConfig implements Serializable{
     @Column(name = "CONFIG_VALUE")
     private String configValue;
 
-    @ManyToOne(targetEntity = GroupComputeResourcePrefEntity.class, cascade= CascadeType.MERGE)
+    @ManyToOne(targetEntity = GroupComputeResourcePrefEntity.class)
     @JoinColumns({
             @JoinColumn(name = "RESOURCE_ID", referencedColumnName = "RESOURCE_ID", nullable = false),
             @JoinColumn(name = "GROUP_RESOURCE_PROFILE_ID", referencedColumnName = "GROUP_RESOURCE_PROFILE_ID", nullable = false)
diff --git a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/AbstractRepository.java b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/AbstractRepository.java
index 3c82bef..acbd3fb 100644
--- a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/AbstractRepository.java
+++ b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/AbstractRepository.java
@@ -48,8 +48,16 @@ public abstract class AbstractRepository<T, E, Id> {
     }
 
     public T update(T t) {
+        return mergeEntity(mapToEntity(t));
+    }
+
+    protected E mapToEntity(T t) {
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        return mapper.map(t, dbEntityGenericClass);
+    }
+
+    protected T mergeEntity(E entity) {
         Mapper mapper = ObjectMapperSingleton.getInstance();
-        E entity = mapper.map(t, dbEntityGenericClass);
         E persistedCopy = execute(entityManager -> entityManager.merge(entity));
         return mapper.map(persistedCopy, thriftGenericClass);
     }
diff --git a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepository.java b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepository.java
index 7266b3d..670b40f 100644
--- a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepository.java
+++ b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepository.java
@@ -19,11 +19,14 @@
  */
 package org.apache.airavata.registry.core.repositories.appcatalog;
 
+import org.apache.airavata.common.utils.AiravataUtils;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.BatchQueueResourcePolicy;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.ComputeResourcePolicy;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupResourceProfile;
 import org.apache.airavata.model.commons.airavata_commonsConstants;
+import org.apache.airavata.registry.core.entities.appcatalog.ComputeResourceReservationEntity;
+import org.apache.airavata.registry.core.entities.appcatalog.GroupComputeResourcePrefEntity;
 import org.apache.airavata.registry.core.entities.appcatalog.GroupComputeResourcePrefPK;
 import org.apache.airavata.registry.core.entities.appcatalog.GroupResourceProfileEntity;
 import org.apache.airavata.registry.core.utils.DBConstants;
@@ -60,6 +63,13 @@ public class GroupResourceProfileRepository extends AppCatAbstractRepository<Gro
                 if (groupComputeResourcePreference.getGroupSSHAccountProvisionerConfigs() != null) {
                     groupComputeResourcePreference.getGroupSSHAccountProvisionerConfigs().forEach(gssh -> gssh.setGroupResourceProfileId(groupResourceProfileId));
                 }
+                if (groupComputeResourcePreference.getReservations() != null) {
+                    groupComputeResourcePreference.getReservations().forEach(reservation -> {
+                        if (reservation.getReservationId().trim().isEmpty() || reservation.getReservationId().equals(airavata_commonsConstants.DEFAULT_ID)) {
+                            reservation.setReservationId(AiravataUtils.getId(reservation.getReservationName()));
+                        }
+                    });
+                }
             }
         }
         if (groupResourceProfile.getBatchQueueResourcePolicies() != null) {
@@ -84,10 +94,27 @@ public class GroupResourceProfileRepository extends AppCatAbstractRepository<Gro
 
         updatedGroupResourceProfile.setUpdatedTime(System.currentTimeMillis());
         updateChildren(updatedGroupResourceProfile, updatedGroupResourceProfile.getGroupResourceProfileId());
-        GroupResourceProfile groupResourceProfile = update(updatedGroupResourceProfile);
+        GroupResourceProfileEntity groupResourceProfileEntity = mapToEntity(updatedGroupResourceProfile);
+        updateChildrenEntities(groupResourceProfileEntity);
+        GroupResourceProfile groupResourceProfile = mergeEntity(groupResourceProfileEntity);
         return groupResourceProfile.getGroupResourceProfileId();
     }
 
+    private void updateChildrenEntities(GroupResourceProfileEntity groupResourceProfileEntity) {
+        if (groupResourceProfileEntity.getComputePreferences() != null) {
+            for (GroupComputeResourcePrefEntity groupComputeResourcePrefEntity : groupResourceProfileEntity.getComputePreferences()) {
+                // For some reason next line is needed to get OpenJPA to persist
+                // GroupResourceProfileEntity before GroupComputeResourcePrefEntity
+                groupComputeResourcePrefEntity.setGroupResourceProfile(groupResourceProfileEntity);
+                if (groupComputeResourcePrefEntity.getReservations() != null) {
+                    for (ComputeResourceReservationEntity reservationEntity : groupComputeResourcePrefEntity.getReservations()) {
+                        reservationEntity.setGroupComputeResourcePref(groupComputeResourcePrefEntity);
+                    }
+                }
+            }
+        }
+    }
+
     public GroupResourceProfile getGroupResourceProfile(String groupResourceProfileId) {
         GroupResourceProfile groupResourceProfile = get(groupResourceProfileId);
         return groupResourceProfile;
diff --git a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/utils/JPAUtil/AppCatalogJPAUtils.java b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/utils/JPAUtil/AppCatalogJPAUtils.java
index af62f58..77ea71f 100644
--- a/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/utils/JPAUtil/AppCatalogJPAUtils.java
+++ b/modules/registry/registry-core/src/main/java/org/apache/airavata/registry/core/utils/JPAUtil/AppCatalogJPAUtils.java
@@ -19,20 +19,50 @@
  */
 package org.apache.airavata.registry.core.utils.JPAUtil;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
 import org.apache.airavata.common.utils.JDBCConfig;
 import org.apache.airavata.common.utils.JPAUtils;
 import org.apache.airavata.registry.core.utils.AppCatalogJDBCConfig;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.meta.MappingTool;
+import org.apache.openjpa.lib.util.Options;
+import org.apache.openjpa.persistence.ArgumentException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class AppCatalogJPAUtils {
 
-    // TODO: we can rename this back to appcatalog_data once we completely replace the other appcatalog_data persistence context in airavata-registry-core
+    // TODO: we can rename this back to appcatalog_data once we completely replace
+    // the other appcatalog_data persistence context in airavata-registry-core
     private static final String PERSISTENCE_UNIT_NAME = "appcatalog_data_new";
     private static final JDBCConfig JDBC_CONFIG = new AppCatalogJDBCConfig();
-    private static final EntityManagerFactory factory = JPAUtils.getEntityManagerFactory(PERSISTENCE_UNIT_NAME, JDBC_CONFIG);
+    private static final EntityManagerFactory factory = JPAUtils.getEntityManagerFactory(PERSISTENCE_UNIT_NAME,
+            JDBC_CONFIG);
+    private static final Logger logger = LoggerFactory.getLogger(AppCatalogJPAUtils.class);
 
     public static EntityManager getEntityManager() {
-        return factory.createEntityManager();
+        try {
+            return factory.createEntityManager();
+        } catch (ArgumentException e) {
+            // TODO: refactor this
+            JDBCConfiguration jdbcConfiguration = JPAUtils.getJDBCConfiguration(JDBC_CONFIG);
+            Options options = new Options();
+            options.put("sqlFile", "migration.sql");
+            // If you want to generate the entire schema instead of just what is
+            // needed to bring the database up to date, use schemaAction=build
+            // options.put("schemaAction", "build");
+            options.put("foreignKeys", "true");
+            options.put("indexes", "true");
+            options.put("primaryKeys", "true");
+            try {
+                MappingTool.run(jdbcConfiguration, new String[] {}, options, null);
+            } catch (Exception mappingToolEx) {
+                logger.error("Failed to run MappingTool", mappingToolEx);
+                throw new RuntimeException("Failed to get EntityManager, then failed to run MappingTool to generate migration script", e);
+            }
+            throw new RuntimeException("Failed to get EntityManager, but successfully executed MappingTool to generate migration script (to file named migration.sql) in case the error was caused by the database schema being out of date with the mappings", e);
+        }
     }
 }
diff --git a/modules/registry/registry-core/src/main/resources/META-INF/persistence.xml b/modules/registry/registry-core/src/main/resources/META-INF/persistence.xml
index 7ace098..9f6fe1e 100644
--- a/modules/registry/registry-core/src/main/resources/META-INF/persistence.xml
+++ b/modules/registry/registry-core/src/main/resources/META-INF/persistence.xml
@@ -79,6 +79,7 @@
         <class>org.apache.airavata.registry.core.entities.appcatalog.ParsingTemplateInputEntity</class>
         <class>org.apache.airavata.registry.core.entities.appcatalog.ParserConnectorInputEntity</class>
         <class>org.apache.airavata.registry.core.entities.appcatalog.ParserConnectorEntity</class>
+        <class>org.apache.airavata.registry.core.entities.appcatalog.ComputeResourceReservationEntity</class>
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
     </persistence-unit>
     <persistence-unit name="replicacatalog_data_new">
diff --git a/modules/registry/registry-core/src/main/resources/appcatalog-derby.sql b/modules/registry/registry-core/src/main/resources/appcatalog-derby.sql
index 4bb49a0..3de22e2 100644
--- a/modules/registry/registry-core/src/main/resources/appcatalog-derby.sql
+++ b/modules/registry/registry-core/src/main/resources/appcatalog-derby.sql
@@ -618,6 +618,12 @@ CREATE TABLE GROUP_COMPUTE_RESOURCE_PREFERENCE
         FOREIGN KEY (GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_RESOURCE_PROFILE(GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE
 );
 
+CREATE TABLE COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
+    (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID));
+CREATE TABLE COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL);
+CREATE INDEX I_CMPTN_Q_RESERVATION_ID ON COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID);
+ALTER TABLE COMPUTE_RESOURCE_RESERVATION ADD FOREIGN KEY (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_COMPUTE_RESOURCE_PREFERENCE (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE;
+
 CREATE TABLE GRP_SSH_ACC_PROV_CONFIG
 (
         RESOURCE_ID VARCHAR(255) NOT NULL,
diff --git a/modules/registry/registry-core/src/main/resources/appcatalog-mysql.sql b/modules/registry/registry-core/src/main/resources/appcatalog-mysql.sql
index b24c433..75a8f14 100644
--- a/modules/registry/registry-core/src/main/resources/appcatalog-mysql.sql
+++ b/modules/registry/registry-core/src/main/resources/appcatalog-mysql.sql
@@ -611,6 +611,14 @@ CREATE TABLE GROUP_COMPUTE_RESOURCE_PREFERENCE
         FOREIGN KEY (GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_RESOURCE_PROFILE(GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE
 )ENGINE=InnoDB DEFAULT CHARSET=latin1;
 
+CREATE TABLE COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
+    (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
+)ENGINE=InnoDB DEFAULT CHARSET=latin1;
+CREATE TABLE COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL
+)ENGINE=InnoDB DEFAULT CHARSET=latin1;
+CREATE INDEX I_CMPTN_Q_RESERVATION_ID ON COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID);
+ALTER TABLE COMPUTE_RESOURCE_RESERVATION ADD CONSTRAINT FK_COMPUTE_RESOURCE_RESERVATION FOREIGN KEY (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_COMPUTE_RESOURCE_PREFERENCE (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE;
+
 CREATE TABLE GRP_SSH_ACC_PROV_CONFIG
 (
         RESOURCE_ID VARCHAR(255) NOT NULL,
diff --git a/modules/registry/registry-core/src/test/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepositoryTest.java b/modules/registry/registry-core/src/test/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepositoryTest.java
index 6c0be31..f10575f 100644
--- a/modules/registry/registry-core/src/test/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepositoryTest.java
+++ b/modules/registry/registry-core/src/test/java/org/apache/airavata/registry/core/repositories/appcatalog/GroupResourceProfileRepositoryTest.java
@@ -19,6 +19,7 @@
  */
 package org.apache.airavata.registry.core.repositories.appcatalog;
 
+import org.apache.airavata.common.utils.AiravataUtils;
 import org.apache.airavata.model.appcatalog.computeresource.BatchQueue;
 import org.apache.airavata.model.appcatalog.computeresource.ComputeResourceDescription;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.*;
@@ -30,7 +31,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
@@ -45,6 +48,11 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
     private GroupResourceProfileRepository groupResourceProfileRepository;
     private String gatewayId = "TEST_GATEWAY";
     private String groupResourceProfileId = null;
+    private String resourceId1 = null;
+    private String resourceId2 = null;
+
+    private final String QUEUE1_NAME = "queue1";
+    private final String QUEUE2_NAME = "queue2";
 
     public GroupResourceProfileRepositoryTest() {
         super(Database.APP_CATALOG);
@@ -52,8 +60,10 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         groupResourceProfileRepository = new GroupResourceProfileRepository();
     }
 
-    @Test
-    public void GroupResourceProfileRepositoryTest() throws AppCatalogException {
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
         ComputeResourceDescription description = new ComputeResourceDescription();
 
         description.setHostName("localhost");
@@ -64,14 +74,14 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         description.setIpAddresses(ipdaresses);
 
         BatchQueue batchQueue1 = new BatchQueue();
-        batchQueue1.setQueueName("queue1");
+        batchQueue1.setQueueName(QUEUE1_NAME);
         batchQueue1.setQueueDescription("que1Desc1");
         batchQueue1.setMaxRunTime(10);
         batchQueue1.setMaxNodes(4);
         batchQueue1.setMaxJobsInQueue(1);
 
         BatchQueue batchQueue2 = new BatchQueue();
-        batchQueue2.setQueueName("queue2");
+        batchQueue2.setQueueName(QUEUE2_NAME);
         batchQueue2.setQueueDescription("que1Desc2");
         batchQueue2.setMaxRunTime(10);
         batchQueue2.setMaxNodes(4);
@@ -82,7 +92,7 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         batchQueueList.add(batchQueue2);
         description.setBatchQueues(batchQueueList);
 
-        String resourceId1 = computeResourceRepository.addComputeResource(description);
+        this.resourceId1 = computeResourceRepository.addComputeResource(description);
 
         ComputeResourceDescription cm2 = new ComputeResourceDescription();
         cm2.setHostName("localhost2");
@@ -107,9 +117,11 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         cmbatchQueueList.add(cm_batchQueue2);
         cm2.setBatchQueues(cmbatchQueueList);
 
-        String resourceId2 = computeResourceRepository.addComputeResource(cm2);
+        this.resourceId2 = computeResourceRepository.addComputeResource(cm2);
+    }
 
-        ComputeResourceDescription computeResourceDescription = computeResourceRepository.getComputeResource(resourceId2);
+    @Test
+    public void GroupResourceProfileRepositoryTest() throws AppCatalogException {
 
         GroupResourceProfile groupResourceProfile = new GroupResourceProfile();
         groupResourceProfile.setGatewayId(gatewayId);
@@ -121,9 +133,24 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         groupAccountSSHProvisionerConfig.setConfigName("configName");
         groupAccountSSHProvisionerConfig.setConfigValue("configvalue");
 
+        ComputeResourceReservation reservation1 = new ComputeResourceReservation();
+        reservation1.setReservationName("test-reservation1");
+        reservation1.setStartTime(AiravataUtils.getCurrentTimestamp().getTime());
+        reservation1.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 100000);
+        reservation1.addToQueueNames(QUEUE1_NAME);
+        reservation1.addToQueueNames(QUEUE2_NAME);
+
+        ComputeResourceReservation reservation2 = new ComputeResourceReservation();
+        reservation2.setReservationName("test-reservation2");
+        reservation2.setStartTime(AiravataUtils.getCurrentTimestamp().getTime() + 200000);
+        reservation2.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 300000);
+        reservation2.addToQueueNames(QUEUE1_NAME);
+
         GroupComputeResourcePreference groupComputeResourcePreference1 = new GroupComputeResourcePreference();
         groupComputeResourcePreference1.setComputeResourceId(resourceId1);
         groupComputeResourcePreference1.addToGroupSSHAccountProvisionerConfigs(groupAccountSSHProvisionerConfig);
+        groupComputeResourcePreference1.addToReservations(reservation1);
+        groupComputeResourcePreference1.addToReservations(reservation2);
 
         GroupComputeResourcePreference groupComputeResourcePreference2 = new GroupComputeResourcePreference();
         groupComputeResourcePreference2.setComputeResourceId(resourceId2);
@@ -196,6 +223,12 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
 
         assertTrue(groupResourceProfileRepository.getGroupComputeResourcePreference(resourceId1,groupResourceProfileId) != null);
         assertTrue(groupResourceProfileRepository.getGroupComputeResourcePreference(resourceId1,groupResourceProfileId).getGroupSSHAccountProvisionerConfigs().size() == 1);
+        // verify reservation1
+        assertEquals(2, groupResourceProfileRepository.getGroupComputeResourcePreference(resourceId1,groupResourceProfileId).getReservations().size());
+        ComputeResourceReservation retrievedReservation1 = groupResourceProfileRepository.getGroupComputeResourcePreference(resourceId1, groupResourceProfileId).getReservations().get(0);
+        assertEquals(reservation1.getReservationName(), retrievedReservation1.getReservationName());
+        assertEquals(reservation1.getStartTime(), retrievedReservation1.getStartTime());
+        assertEquals(reservation1.getEndTime(), retrievedReservation1.getEndTime());
 
         ComputeResourcePolicy getComputeResourcePolicy = groupResourceProfileRepository.getComputeResourcePolicy(computeResourcePolicyId1);
         assertTrue(getComputeResourcePolicy.getAllowedBatchQueues().get(0).equals("queue1"));
@@ -246,8 +279,6 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         assertEquals(1, retrievedGroupResourceProfile4.getComputePreferencesSize());
 
         groupResourceProfileRepository.removeGroupResourceProfile(groupResourceProfileId);
-        computeResourceRepository.removeComputeResource(resourceId1);
-        computeResourceRepository.removeComputeResource(resourceId2);
 
     }
 
@@ -269,4 +300,212 @@ public class GroupResourceProfileRepositoryTest extends TestBase {
         long creationTimeAfterUpdate = groupResourceProfileRepository.getGroupResourceProfile(groupResourceProfileId).getCreationTime();
         Assert.assertEquals("creationTime should be the same after update", creationTime, creationTimeAfterUpdate);
     }
+
+    @Test
+    public void testRemovingReservation() throws AppCatalogException {
+
+        GroupResourceProfile groupResourceProfile = new GroupResourceProfile();
+        groupResourceProfile.setGatewayId(gatewayId);
+        groupResourceProfile.setGroupResourceProfileName("TEST_GROUP_PROFILE_NAME");
+
+        ComputeResourceReservation reservation1 = new ComputeResourceReservation();
+        reservation1.setReservationName("test-reservation1");
+        reservation1.setStartTime(AiravataUtils.getCurrentTimestamp().getTime());
+        reservation1.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 100000);
+        reservation1.addToQueueNames(QUEUE1_NAME);
+        reservation1.addToQueueNames(QUEUE2_NAME);
+
+        ComputeResourceReservation reservation2 = new ComputeResourceReservation();
+        reservation2.setReservationName("test-reservation2");
+        reservation2.setStartTime(AiravataUtils.getCurrentTimestamp().getTime() + 200000);
+        reservation2.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 300000);
+        reservation2.addToQueueNames(QUEUE1_NAME);
+
+        GroupComputeResourcePreference groupComputeResourcePreference1 = new GroupComputeResourcePreference();
+        groupComputeResourcePreference1.setComputeResourceId(resourceId1);
+        groupComputeResourcePreference1.addToReservations(reservation1);
+        groupComputeResourcePreference1.addToReservations(reservation2);
+
+        groupResourceProfile.addToComputePreferences(groupComputeResourcePreference1);
+
+        String groupResourceProfileId = groupResourceProfileRepository.addGroupResourceProfile(groupResourceProfile);
+
+        // Remove one of the reservations
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(2, retrievedReservations.size());
+            retrievedReservations.remove(1);
+
+            groupResourceProfileRepository.updateGroupResourceProfile(retrievedGroupResourceProfile);
+        }
+
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(1, retrievedReservations.size());
+            assertEquals(reservation1.getReservationName(), retrievedReservations.get(0).getReservationName());
+        }
+
+    }
+
+    @Test
+    public void testUpdatingReservation() throws AppCatalogException {
+
+        GroupResourceProfile groupResourceProfile = new GroupResourceProfile();
+        groupResourceProfile.setGatewayId(gatewayId);
+        groupResourceProfile.setGroupResourceProfileName("TEST_GROUP_PROFILE_NAME");
+
+        ComputeResourceReservation reservation1 = new ComputeResourceReservation();
+        reservation1.setReservationName("test-reservation1");
+        reservation1.setStartTime(AiravataUtils.getCurrentTimestamp().getTime());
+        reservation1.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 100000);
+        reservation1.addToQueueNames(QUEUE1_NAME);
+        reservation1.addToQueueNames(QUEUE2_NAME);
+
+        ComputeResourceReservation reservation2 = new ComputeResourceReservation();
+        reservation2.setReservationName("test-reservation2");
+        reservation2.setStartTime(AiravataUtils.getCurrentTimestamp().getTime() + 200000);
+        reservation2.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 300000);
+        reservation2.addToQueueNames(QUEUE1_NAME);
+
+        GroupComputeResourcePreference groupComputeResourcePreference1 = new GroupComputeResourcePreference();
+        groupComputeResourcePreference1.setComputeResourceId(resourceId1);
+        groupComputeResourcePreference1.addToReservations(reservation1);
+        groupComputeResourcePreference1.addToReservations(reservation2);
+
+        groupResourceProfile.addToComputePreferences(groupComputeResourcePreference1);
+
+        String groupResourceProfileId = groupResourceProfileRepository.addGroupResourceProfile(groupResourceProfile);
+
+        // Update one of the reservations
+        long newStartTime = AiravataUtils.getCurrentTimestamp().getTime() + 1000*1000;
+        long newEndTime = AiravataUtils.getCurrentTimestamp().getTime() + 2*1000*1000;
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(2, retrievedReservations.size());
+            // push into future, should sort second on next retrieval
+            retrievedReservations.get(0).setStartTime(newStartTime);
+            retrievedReservations.get(0).setEndTime(newEndTime);
+
+            groupResourceProfileRepository.updateGroupResourceProfile(retrievedGroupResourceProfile);
+        }
+
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(2, retrievedReservations.size());
+            // first reservation should now sort second
+            ComputeResourceReservation reservation = retrievedReservations.get(1);
+            assertEquals(reservation1.getReservationName(), reservation.getReservationName());
+            assertEquals(newStartTime, reservation.getStartTime());
+            assertEquals(newEndTime, reservation.getEndTime());
+        }
+
+    }
+
+    @Test
+    public void testAddingQueueToReservation() throws AppCatalogException {
+
+        GroupResourceProfile groupResourceProfile = new GroupResourceProfile();
+        groupResourceProfile.setGatewayId(gatewayId);
+        groupResourceProfile.setGroupResourceProfileName("TEST_GROUP_PROFILE_NAME");
+
+        ComputeResourceReservation reservation1 = new ComputeResourceReservation();
+        reservation1.setReservationName("test-reservation1");
+        reservation1.setStartTime(AiravataUtils.getCurrentTimestamp().getTime());
+        reservation1.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 100000);
+        reservation1.addToQueueNames(QUEUE1_NAME);
+
+        GroupComputeResourcePreference groupComputeResourcePreference1 = new GroupComputeResourcePreference();
+        groupComputeResourcePreference1.setComputeResourceId(resourceId1);
+        groupComputeResourcePreference1.addToReservations(reservation1);
+
+        groupResourceProfile.addToComputePreferences(groupComputeResourcePreference1);
+
+        String groupResourceProfileId = groupResourceProfileRepository.addGroupResourceProfile(groupResourceProfile);
+
+        // add queue to the reservation
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(1, retrievedReservations.size());
+            ComputeResourceReservation reservation = retrievedReservations.get(0);
+            assertEquals(1, reservation.getQueueNamesSize());
+            reservation.addToQueueNames(QUEUE2_NAME);
+
+            groupResourceProfileRepository.updateGroupResourceProfile(retrievedGroupResourceProfile);
+        }
+
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(1, retrievedReservations.size());
+            ComputeResourceReservation reservation = retrievedReservations.get(0);
+            assertEquals(new HashSet<>(Arrays.asList(QUEUE1_NAME, QUEUE2_NAME)), new HashSet<>(reservation.getQueueNames()));
+        }
+
+    }
+
+    @Test
+    public void testRemovingQueueFromReservation() throws AppCatalogException {
+
+        GroupResourceProfile groupResourceProfile = new GroupResourceProfile();
+        groupResourceProfile.setGatewayId(gatewayId);
+        groupResourceProfile.setGroupResourceProfileName("TEST_GROUP_PROFILE_NAME");
+
+        ComputeResourceReservation reservation1 = new ComputeResourceReservation();
+        reservation1.setReservationName("test-reservation1");
+        reservation1.setStartTime(AiravataUtils.getCurrentTimestamp().getTime());
+        reservation1.setEndTime(AiravataUtils.getCurrentTimestamp().getTime() + 100000);
+        reservation1.addToQueueNames(QUEUE1_NAME);
+        reservation1.addToQueueNames(QUEUE2_NAME);
+
+        GroupComputeResourcePreference groupComputeResourcePreference1 = new GroupComputeResourcePreference();
+        groupComputeResourcePreference1.setComputeResourceId(resourceId1);
+        groupComputeResourcePreference1.addToReservations(reservation1);
+
+        groupResourceProfile.addToComputePreferences(groupComputeResourcePreference1);
+
+        String groupResourceProfileId = groupResourceProfileRepository.addGroupResourceProfile(groupResourceProfile);
+
+        // add queue to the reservation
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(1, retrievedReservations.size());
+            ComputeResourceReservation reservation = retrievedReservations.get(0);
+            assertEquals(new HashSet<>(Arrays.asList(QUEUE1_NAME, QUEUE2_NAME)), new HashSet<>(reservation.getQueueNames()));
+            reservation.unsetQueueNames();
+            reservation.addToQueueNames(QUEUE1_NAME);
+
+            groupResourceProfileRepository.updateGroupResourceProfile(retrievedGroupResourceProfile);
+        }
+
+        {
+            GroupResourceProfile retrievedGroupResourceProfile = groupResourceProfileRepository
+                    .getGroupResourceProfile(groupResourceProfileId);
+            List<ComputeResourceReservation> retrievedReservations = retrievedGroupResourceProfile
+                    .getComputePreferences().get(0).getReservations();
+            assertEquals(1, retrievedReservations.size());
+            ComputeResourceReservation reservation = retrievedReservations.get(0);
+            assertEquals(new HashSet<>(Arrays.asList(QUEUE1_NAME)), new HashSet<>(reservation.getQueueNames()));
+        }
+
+    }
 }
diff --git a/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql b/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
index 839c2e1..480b545 100644
--- a/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
+++ b/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
@@ -19,3 +19,12 @@
 --
 
 use app_catalog;
+
+-- AIRAVATA-3126
+CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
+    (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
+)ENGINE=InnoDB DEFAULT CHARSET=latin1;
+CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL
+)ENGINE=InnoDB DEFAULT CHARSET=latin1;
+CREATE INDEX IF NOT EXISTS I_CMPTN_Q_RESERVATION_ID ON COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID);
+ALTER TABLE COMPUTE_RESOURCE_RESERVATION ADD CONSTRAINT FK_COMPUTE_RESOURCE_RESERVATION FOREIGN KEY IF NOT EXISTS (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_COMPUTE_RESOURCE_PREFERENCE (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE;
diff --git a/thrift-interface-descriptions/data-models/resource-catalog-models/group_resource_profile_model.thrift b/thrift-interface-descriptions/data-models/resource-catalog-models/group_resource_profile_model.thrift
index 0f4b950..868db38 100644
--- a/thrift-interface-descriptions/data-models/resource-catalog-models/group_resource_profile_model.thrift
+++ b/thrift-interface-descriptions/data-models/resource-catalog-models/group_resource_profile_model.thrift
@@ -34,6 +34,14 @@ struct GroupAccountSSHProvisionerConfig {
     4: optional string configValue
 }
 
+struct ComputeResourceReservation {
+    1: required string reservationId = airavata_commons.DEFAULT_ID,
+    2: required string reservationName,
+    3: required list<string> queueNames,
+    4: required i64 startTime,
+    5: required i64 endTime,
+}
+
 struct GroupComputeResourcePreference {
     1: required string computeResourceId,
     2: required string groupResourceProfileId = airavata_commons.DEFAULT_ID,
@@ -52,7 +60,8 @@ struct GroupComputeResourcePreference {
     15: optional i64 reservationEndTime,
     16: optional string sshAccountProvisioner,
     17: optional list<GroupAccountSSHProvisionerConfig> groupSSHAccountProvisionerConfigs,
-    18: optional string sshAccountProvisionerAdditionalInfo
+    18: optional string sshAccountProvisionerAdditionalInfo,
+    19: optional list<ComputeResourceReservation> reservations,
 }
 
 struct ComputeResourcePolicy {
@@ -104,4 +113,4 @@ struct GroupResourceProfile {
     7: optional i64 creationTime,
     8: optional i64 updatedTime,
     9: optional string defaultCredentialStoreToken
-}
\ No newline at end of file
+}


[airavata] 04/04: Merge branch 'AIRAVATA-3126--Implement-compute-resource-reservation-addition' into develop

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit b801135da78a5001ee467c8587d4df58baf4ce8f
Merge: cd0f271 3fb981b
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Mar 25 15:45:59 2020 -0400

    Merge branch 'AIRAVATA-3126--Implement-compute-resource-reservation-addition' into develop

 .../appcatalog/groupresourceprofile/ttypes.py      | 217 +++++-
 .../ComputeResourcePolicy.java                     |  32 +-
 .../ComputeResourceReservation.java                | 820 +++++++++++++++++++++
 .../GroupComputeResourcePreference.java            | 189 ++++-
 .../groupresourceprofile/GroupResourceProfile.java | 108 +--
 airavata-api/airavata-model-utils/pom.xml          |   6 +
 .../util/GroupComputeResourcePreferenceUtil.java   |  44 ++
 .../GroupComputeResourcePreferenceUtilTest.java    | 116 +++
 .../airavata/helix/impl/task/TaskContext.java      |   9 +
 .../org/apache/airavata/common/utils/JPAUtils.java |  13 +
 .../src/main/resources/META-INF/persistence.xml    |   1 +
 .../init/03-appcatalog-migrations.sql              |   9 +
 modules/registry/registry-core/README.md           |  13 +
 ....java => ComputeResourceReservationEntity.java} |  93 ++-
 .../appcatalog/GroupComputeResourcePrefEntity.java |  15 +-
 .../GroupSSHAccountProvisionerConfig.java          |   2 +-
 .../core/repositories/AbstractRepository.java      |  10 +-
 .../appcatalog/GroupResourceProfileRepository.java |  29 +-
 .../core/utils/JPAUtil/AppCatalogJPAUtils.java     |  40 +-
 .../src/main/resources/META-INF/persistence.xml    |   1 +
 .../src/main/resources/appcatalog-derby.sql        |   6 +
 .../src/main/resources/appcatalog-mysql.sql        |   8 +
 .../GroupResourceProfileRepositoryTest.java        | 257 ++++++-
 .../next/DeltaScripts/appCatalog_schema_delta.sql  |   9 +
 .../group_resource_profile_model.thrift            |  13 +-
 25 files changed, 1882 insertions(+), 178 deletions(-)

diff --cc modules/ide-integration/src/main/resources/database_scripts/init/03-appcatalog-migrations.sql
index 4022bf3,a07c0f0..f6978cb
--- a/modules/ide-integration/src/main/resources/database_scripts/init/03-appcatalog-migrations.sql
+++ b/modules/ide-integration/src/main/resources/database_scripts/init/03-appcatalog-migrations.sql
@@@ -1,3 -1,10 +1,12 @@@
  use app_catalog;
  
 +ALTER TABLE APPLICATION_INPUT ADD COLUMN OVERRIDE_FILENAME VARCHAR(255);
++
+ -- AIRAVATA-3126
+ CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
+     (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
+ )ENGINE=InnoDB DEFAULT CHARSET=latin1;
+ CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL
+ )ENGINE=InnoDB DEFAULT CHARSET=latin1;
+ CREATE INDEX I_CMPTN_Q_RESERVATION_ID ON COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID);
+ ALTER TABLE COMPUTE_RESOURCE_RESERVATION ADD CONSTRAINT FK_COMPUTE_RESOURCE_RESERVATION FOREIGN KEY (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_COMPUTE_RESOURCE_PREFERENCE (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE;
diff --cc modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
index b9f4385,c25b3b1..6286a56
--- a/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
+++ b/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
@@@ -20,21 -20,11 +20,30 @@@
  
  use app_catalog;
  
 +-- AIRAVATA-3276 Replace JSON configuration: "toggle": ["isRequired"] ->
 +-- "isRequired": true. Toggling requiredToAddedToCommandLine no longer needed.
 +
 +-- replace toggle with is isRequired
 +update APPLICATION_INPUT
 +set METADATA = REGEXP_REPLACE(METADATA, '"toggle": \\[[^}]+\\]', CONCAT('"isRequired": ', IF(IS_REQUIRED=1, 'true', 'false')))
 +-- showOptions has "toggle" but not "isRequired"
 +where METADATA rlike '"showOptions": {"toggle": \\[[^}]+\\]'
 +  and NOT METADATA rlike '"showOptions": {.*"isRequired": (true|false)'
 +;
 +
 +-- remove toggle since isRequired is already there
 +update APPLICATION_INPUT
 +set METADATA = REGEXP_REPLACE(METADATA, '(, )?"toggle": \\[[^}]+\\](, )?', '')
 +-- showOptions has BOTH "toggle" and "isRequired"
 +where METADATA rlike '"showOptions": {"toggle": \\[[^}]+\\]'
 +  and METADATA rlike '"showOptions": {.*"isRequired": (true|false)'
 +;
++
+ -- AIRAVATA-3126
+ CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
+     (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL DEFAULT 0, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL DEFAULT 0, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
+ )ENGINE=InnoDB DEFAULT CHARSET=latin1;
+ CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL
+ )ENGINE=InnoDB DEFAULT CHARSET=latin1;
+ CREATE INDEX IF NOT EXISTS I_CMPTN_Q_RESERVATION_ID ON COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID);
+ ALTER TABLE COMPUTE_RESOURCE_RESERVATION ADD CONSTRAINT FK_COMPUTE_RESOURCE_RESERVATION FOREIGN KEY IF NOT EXISTS (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) REFERENCES GROUP_COMPUTE_RESOURCE_PREFERENCE (RESOURCE_ID, GROUP_RESOURCE_PROFILE_ID) ON DELETE CASCADE;


[airavata] 02/04: AIRAVATA-3126 Update logic to get active reservation

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit d698f9b57efa7aad900bca7deb1a6fad648d7202
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Sun Mar 8 16:32:32 2020 -0400

    AIRAVATA-3126 Update logic to get active reservation
---
 airavata-api/airavata-model-utils/pom.xml          |   6 ++
 .../util/GroupComputeResourcePreferenceUtil.java   |  44 ++++++++
 .../GroupComputeResourcePreferenceUtilTest.java    | 116 +++++++++++++++++++++
 .../airavata/helix/impl/task/TaskContext.java      |   9 ++
 4 files changed, 175 insertions(+)

diff --git a/airavata-api/airavata-model-utils/pom.xml b/airavata-api/airavata-model-utils/pom.xml
index 67eeaed..51bace8 100644
--- a/airavata-api/airavata-model-utils/pom.xml
+++ b/airavata-api/airavata-model-utils/pom.xml
@@ -43,6 +43,12 @@
             <artifactId>airavata-data-models</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 
diff --git a/airavata-api/airavata-model-utils/src/main/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtil.java b/airavata-api/airavata-model-utils/src/main/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtil.java
new file mode 100644
index 0000000..58731e9
--- /dev/null
+++ b/airavata-api/airavata-model-utils/src/main/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtil.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+package org.apache.airavata.model.util;
+
+import org.apache.airavata.model.appcatalog.groupresourceprofile.ComputeResourceReservation;
+import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
+
+public class GroupComputeResourcePreferenceUtil {
+
+    public static ComputeResourceReservation getActiveReservationForQueue(
+            GroupComputeResourcePreference groupComputeResourcePreference, String queueName) {
+
+        long now = System.currentTimeMillis();
+        if (groupComputeResourcePreference.getReservationsSize() > 0) {
+            for (ComputeResourceReservation reservation : groupComputeResourcePreference.getReservations()) {
+
+                if (reservation.getQueueNames().contains(queueName) && now > reservation.getStartTime()
+                        && now < reservation.getEndTime()) {
+                    return reservation;
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/airavata-api/airavata-model-utils/src/test/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtilTest.java b/airavata-api/airavata-model-utils/src/test/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtilTest.java
new file mode 100644
index 0000000..7f9bedf
--- /dev/null
+++ b/airavata-api/airavata-model-utils/src/test/java/org/apache/airavata/model/util/GroupComputeResourcePreferenceUtilTest.java
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+package org.apache.airavata.model.util;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.airavata.model.appcatalog.groupresourceprofile.ComputeResourceReservation;
+import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * GroupComputeResourcePreferenceUtilTest
+ */
+public class GroupComputeResourcePreferenceUtilTest {
+
+    @Test
+    public void testGetActiveReservationForQueue() {
+
+        final GroupComputeResourcePreference pref = new GroupComputeResourcePreference();
+        final ComputeResourceReservation res1 = new ComputeResourceReservation("id1", "res1",
+                Arrays.asList("cpu", "gpu"), System.currentTimeMillis() - 10000, System.currentTimeMillis() + 10000);
+        pref.addToReservations(res1);
+
+        final ComputeResourceReservation result = GroupComputeResourcePreferenceUtil.getActiveReservationForQueue(pref,
+                "cpu");
+
+        Assert.assertSame(res1, result);
+    }
+
+    @Test
+    public void testGetActiveReservationForQueueWhenNoReservations() {
+
+        final GroupComputeResourcePreference pref = new GroupComputeResourcePreference();
+
+        final ComputeResourceReservation result = GroupComputeResourcePreferenceUtil.getActiveReservationForQueue(pref,
+                "cpu");
+
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testGetActiveReservationForQueueWhenReservationIsExpired() {
+
+        final GroupComputeResourcePreference pref = new GroupComputeResourcePreference();
+        final ComputeResourceReservation res1 = new ComputeResourceReservation("id1", "res1",
+                Arrays.asList("cpu", "gpu"), System.currentTimeMillis() - 20000, System.currentTimeMillis() - 10000);
+        pref.addToReservations(res1);
+
+        final ComputeResourceReservation result = GroupComputeResourcePreferenceUtil.getActiveReservationForQueue(pref,
+                "cpu");
+
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testGetActiveReservationForQueueWhenReservationActiveButWrongQueue() {
+
+        final GroupComputeResourcePreference pref = new GroupComputeResourcePreference();
+        final ComputeResourceReservation res1 = new ComputeResourceReservation("id1", "res1",
+                Arrays.asList("cpu", "gpu"), System.currentTimeMillis() - 10000, System.currentTimeMillis() + 10000);
+        pref.addToReservations(res1);
+
+        final ComputeResourceReservation result = GroupComputeResourcePreferenceUtil.getActiveReservationForQueue(pref,
+                "thirdqueue");
+
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void testGetActiveReservationWithRandomOrder() {
+
+        final GroupComputeResourcePreference pref = new GroupComputeResourcePreference();
+        final ComputeResourceReservation res1 = new ComputeResourceReservation("id1", "res1",
+                Arrays.asList("cpu", "gpu"), System.currentTimeMillis() - 10000, System.currentTimeMillis() + 10000);
+        // expired
+        final ComputeResourceReservation res2 = new ComputeResourceReservation("id2", "res2",
+                Arrays.asList("cpu", "gpu"), System.currentTimeMillis() - 20000, System.currentTimeMillis() - 10000);
+        // future
+        final ComputeResourceReservation res3 = new ComputeResourceReservation("id3", "res3",
+                Arrays.asList("cpu", "gpu"), System.currentTimeMillis() + 10000, System.currentTimeMillis() + 20000);
+        // wrong queue
+        final ComputeResourceReservation res4 = new ComputeResourceReservation("id3", "res3",
+                Arrays.asList("shared", "compute"), System.currentTimeMillis() + 10000, System.currentTimeMillis() + 20000);
+        final List<ComputeResourceReservation> reservations = Arrays.asList(res1, res2, res3, res4);
+
+        Collections.shuffle(reservations);
+        pref.setReservations(reservations);
+
+        final ComputeResourceReservation result = GroupComputeResourcePreferenceUtil.getActiveReservationForQueue(pref,
+                "cpu");
+
+        Assert.assertSame(res1, result);
+    }
+}
diff --git a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java
index ab323b0..e57fa1e 100644
--- a/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java
+++ b/modules/airavata-helix/helix-spectator/src/main/java/org/apache/airavata/helix/impl/task/TaskContext.java
@@ -33,6 +33,7 @@ import org.apache.airavata.model.appcatalog.computeresource.ResourceJobManager;
 import org.apache.airavata.model.appcatalog.computeresource.SSHJobSubmission;
 import org.apache.airavata.model.appcatalog.gatewayprofile.GatewayResourceProfile;
 import org.apache.airavata.model.appcatalog.gatewayprofile.StoragePreference;
+import org.apache.airavata.model.appcatalog.groupresourceprofile.ComputeResourceReservation;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
 import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupResourceProfile;
 import org.apache.airavata.model.appcatalog.storageresource.StorageResourceDescription;
@@ -53,6 +54,7 @@ import org.apache.airavata.model.status.TaskState;
 import org.apache.airavata.model.status.TaskStatus;
 import org.apache.airavata.model.task.TaskModel;
 import org.apache.airavata.model.user.UserProfile;
+import org.apache.airavata.model.util.GroupComputeResourcePreferenceUtil;
 import org.apache.airavata.registry.api.RegistryService;
 import org.apache.airavata.service.profile.user.cpi.UserProfileService;
 import org.apache.airavata.service.security.AiravataSecurityManager;
@@ -646,6 +648,7 @@ public class TaskContext {
             start = userComputeResourcePreference.getReservationStartTime();
             end = userComputeResourcePreference.getReservationEndTime();
         } else {
+            // TODO: remove this once we've migrated to groupComputeResourcePreference.getReservations()
             reservation = groupComputeResourcePreference.getReservation();
             start = groupComputeResourcePreference.getReservationStartTime();
             end = groupComputeResourcePreference.getReservationEndTime();
@@ -656,6 +659,12 @@ public class TaskContext {
                 return reservation;
             }
         }
+        String queueName = getQueueName();
+        ComputeResourceReservation computeResourceReservation = GroupComputeResourcePreferenceUtil
+                .getActiveReservationForQueue(groupComputeResourcePreference, queueName);
+        if (computeResourceReservation != null) {
+            return computeResourceReservation.getReservationName();
+        }
         return null;
     }
 


[airavata] 03/04: AIRAVATA-3126 Prevent MariaDB ON UPDATE CURRENT_TIMESTAMP

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit 3fb981b8e945fc7bae16f3d5071c807ebca8e93c
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Mar 25 15:40:42 2020 -0400

    AIRAVATA-3126 Prevent MariaDB ON UPDATE CURRENT_TIMESTAMP
    
    Need `DEFAULT 0` to prevent `ON UPDATE CURRENT_TIMESTAMP` behavior for first
    TIMESTAMP in table.
---
 .../next/DeltaScripts/appCatalog_schema_delta.sql                       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql b/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
index 480b545..c25b3b1 100644
--- a/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
+++ b/modules/registry/release-migration-scripts/next/DeltaScripts/appCatalog_schema_delta.sql
@@ -22,7 +22,7 @@ use app_catalog;
 
 -- AIRAVATA-3126
 CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION -- ComputeResourceReservationEntity
-    (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
+    (RESERVATION_ID VARCHAR(255) NOT NULL, END_TIME TIMESTAMP NOT NULL DEFAULT 0, RESERVATION_NAME VARCHAR(255) NOT NULL, START_TIME TIMESTAMP NOT NULL DEFAULT 0, RESOURCE_ID VARCHAR(255) NOT NULL, GROUP_RESOURCE_PROFILE_ID VARCHAR(255) NOT NULL, PRIMARY KEY (RESERVATION_ID)
 )ENGINE=InnoDB DEFAULT CHARSET=latin1;
 CREATE TABLE IF NOT EXISTS COMPUTE_RESOURCE_RESERVATION_QUEUE (RESERVATION_ID VARCHAR(255), QUEUE_NAME VARCHAR(255) NOT NULL
 )ENGINE=InnoDB DEFAULT CHARSET=latin1;