Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions coldfront/config/local_settings.py.sample
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ SESSION_COOKIE_SECURE = False
# Sessions should last for one hour.
SESSION_COOKIE_AGE = 60 * 60

# ------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# myBRC settings
# ------------------------------------------------------------------------------
#------------------------------------------------------------------------------

# The ID of the Site object to use (probably 1).
SITE_ID = 1
Expand Down
6 changes: 5 additions & 1 deletion coldfront/core/allocation/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,11 @@ def __init__(self, *args, **kwargs):
not isinstance(self.computing_allowance, ComputingAllowance)):
self.computing_allowance = ComputingAllowance(
self.computing_allowance)
self.interface = ComputingAllowanceInterface()
self.interface = (
# Short-circuit to avoid instantiating ComputingAllowanceInterface
# if possible.
kwargs.pop('computing_allowance_interface', None) or
ComputingAllowanceInterface())
super().__init__(*args, **kwargs)

def label_from_instance(self, obj):
Expand Down
29 changes: 25 additions & 4 deletions coldfront/core/project/forms_/new_project_forms/request_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ class SavioProjectAllocationPeriodForm(forms.Form):

def __init__(self, *args, **kwargs):
computing_allowance = kwargs.pop('computing_allowance', None)
computing_allowance_interface = (
# Short-circuit to avoid instantiating ComputingAllowanceInterface
# if possible.
kwargs.pop('computing_allowance_interface', None) or
ComputingAllowanceInterface())
super().__init__(*args, **kwargs)
if computing_allowance is not None:
computing_allowance = ComputingAllowance(computing_allowance)
Expand All @@ -60,6 +65,7 @@ def __init__(self, *args, **kwargs):
queryset = AllocationPeriod.objects.none()
self.fields['allocation_period'] = AllocationPeriodChoiceField(
computing_allowance=computing_allowance,
computing_allowance_interface=computing_allowance_interface,
label='Allocation Period',
queryset=queryset,
required=True)
Expand Down Expand Up @@ -164,6 +170,11 @@ class SavioProjectExistingPIForm(forms.Form):
def __init__(self, *args, **kwargs):
self.computing_allowance = kwargs.pop('computing_allowance', None)
self.allocation_period = kwargs.pop('allocation_period', None)
self.interface = (
# Short-circuit to avoid instantiating ComputingAllowanceInterface
# if possible.
kwargs.pop('computing_allowance_interface', None) or
ComputingAllowanceInterface())
super().__init__(*args, **kwargs)
if self.computing_allowance is not None:
self.computing_allowance = ComputingAllowance(
Expand Down Expand Up @@ -196,7 +207,8 @@ def disable_pi_choices(self):
disable_user_pks.update(
project_pi_pks(
computing_allowance=resource,
project_status_names=project_status_names))
project_status_names=project_status_names,
computing_allowance_interface=self.interface))
new_project_request_status_names = list(
non_denied_new_project_request_statuses().values_list(
'name', flat=True))
Expand All @@ -212,7 +224,8 @@ def disable_pi_choices(self):
pis_with_renewal_requests_pks(
self.allocation_period,
computing_allowance=resource,
request_status_names=renewal_request_status_names))
request_status_names=renewal_request_status_names,
computing_allowance_interface=self.interface))

if flag_enabled('LRC_ONLY'):
# On LRC, PIs must be LBL employees.
Expand Down Expand Up @@ -528,7 +541,11 @@ class SavioProjectPooledProjectSelectionForm(forms.Form):

def __init__(self, *args, **kwargs):
self.computing_allowance = kwargs.pop('computing_allowance', None)
self.interface = ComputingAllowanceInterface()
self.interface = (
# Short-circuit to avoid instantiating ComputingAllowanceInterface
# if possible.
kwargs.pop('computing_allowance_interface', None) or
ComputingAllowanceInterface())
super().__init__(*args, **kwargs)

f = Q(status__name__in=['Pending - Add', 'New', 'Active'])
Expand Down Expand Up @@ -587,7 +604,11 @@ class SavioProjectDetailsForm(forms.Form):

def __init__(self, *args, **kwargs):
self.computing_allowance = kwargs.pop('computing_allowance', None)
self.interface = ComputingAllowanceInterface()
self.interface = (
# Short-circuit to avoid instantiating ComputingAllowanceInterface
# if possible.
kwargs.pop('computing_allowance_interface', None) or
ComputingAllowanceInterface())
super().__init__(*args, **kwargs)
if self.computing_allowance is not None:
self.computing_allowance = ComputingAllowance(
Expand Down
12 changes: 10 additions & 2 deletions coldfront/core/project/utils_/new_project_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ def pis_with_new_project_requests_pks(allocation_period,
f).values_list('pi__pk', flat=True))


def project_pi_pks(computing_allowance=None, project_status_names=[]):
def project_pi_pks(computing_allowance=None, project_status_names=[],
computing_allowance_interface=None):
"""Return a list of primary keys of PI Users of Projects that match
the given filters.

Expand All @@ -91,6 +92,9 @@ def project_pi_pks(computing_allowance=None, project_status_names=[]):
allowance to filter with
- project_status_names (list[str]): A list of names of Project
statuses to filter with
- computing_allowance_interface (ComputingAllowanceInterface):
An optional ComputingAllowanceInterface instance to
perform lookups with

Returns:
- A list of integers representing primary keys of matching PIs.
Expand All @@ -101,9 +105,13 @@ def project_pi_pks(computing_allowance=None, project_status_names=[]):
cannot be retrieved.
"""
project_prefix = ''
if computing_allowance_interface is not None:
assert isinstance(
computing_allowance_interface, ComputingAllowanceInterface)
if computing_allowance is not None:
assert isinstance(computing_allowance, Resource)
interface = ComputingAllowanceInterface()
interface = (
computing_allowance_interface or ComputingAllowanceInterface())
project_prefix = interface.code_from_name(computing_allowance.name)
return set(
ProjectUser.objects.filter(
Expand Down
12 changes: 10 additions & 2 deletions coldfront/core/project/utils_/renewal_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ def non_denied_renewal_request_statuses():


def pis_with_renewal_requests_pks(allocation_period, computing_allowance=None,
request_status_names=[]):
request_status_names=[],
computing_allowance_interface=None):
"""Return a list of primary keys of PIs of allocation renewal
requests for the given AllocationPeriod that match the given filters.

Expand All @@ -243,6 +244,9 @@ def pis_with_renewal_requests_pks(allocation_period, computing_allowance=None,
allowance to filter with
- request_status_names (list[str]): A list of names of request
statuses to filter with
- computing_allowance_interface (ComputingAllowanceInterface):
An optional ComputingAllowanceInterface instance to
perform lookups with

Returns:
- A list of integers representing primary keys of matching PIs.
Expand All @@ -254,9 +258,13 @@ def pis_with_renewal_requests_pks(allocation_period, computing_allowance=None,
"""
assert isinstance(allocation_period, AllocationPeriod)
f = Q(allocation_period=allocation_period)
if computing_allowance_interface is not None:
assert isinstance(
computing_allowance_interface, ComputingAllowanceInterface)
if computing_allowance is not None:
assert isinstance(computing_allowance, Resource)
interface = ComputingAllowanceInterface()
interface = (
computing_allowance_interface or ComputingAllowanceInterface())
project_prefix = interface.code_from_name(computing_allowance.name)
f = f & Q(post_project__name__startswith=project_prefix)
if request_status_names:
Expand Down
14 changes: 14 additions & 0 deletions coldfront/core/project/views_/new_project_views/request_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from coldfront.core.resource.models import Resource
from coldfront.core.resource.utils import get_primary_compute_resource
from coldfront.core.resource.utils_.allowance_utils.computing_allowance import ComputingAllowance
from coldfront.core.resource.utils_.allowance_utils.interface import cached_computing_allowance_interface
from coldfront.core.resource.utils_.allowance_utils.interface import ComputingAllowanceInterface
from coldfront.core.user.models import UserProfile
from coldfront.core.user.utils import access_agreement_signed
Expand Down Expand Up @@ -178,6 +179,8 @@ def __init__(self, *args, **kwargs):
# Define a lookup table from form name to step number.
self.step_numbers_by_form_name = {
name: i for i, (name, _) in enumerate(self.FORMS)}
self.computing_allowance_interface = \
cached_computing_allowance_interface()

def test_func(self):
if self.request.user.is_superuser:
Expand Down Expand Up @@ -223,6 +226,17 @@ def get_form_kwargs(self, step=None):
step_name = step_names_by_step_number[step_number]
for key in required_keys_by_step_name[step_name]:
kwargs[key] = data.get(key, None)

step_names_requiring_computing_allowance_interface = {
'allocation_period',
'existing_pi',
'pooled_project_selection',
'details',
}
if step_name in step_names_requiring_computing_allowance_interface:
kwargs['computing_allowance_interface'] = \
self.computing_allowance_interface

return kwargs

def get_template_names(self):
Expand Down
24 changes: 24 additions & 0 deletions coldfront/core/resource/utils_/allowance_utils/interface.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from base64 import b64decode
from base64 import b64encode

from django.core.cache import cache

from coldfront.core.allocation.models import AllocationPeriod
from coldfront.core.resource.models import Resource
from coldfront.core.resource.models import ResourceType

import pickle


class ComputingAllowanceInterface(object):
"""A singleton that fetches computing allowances from the database
Expand Down Expand Up @@ -135,3 +142,20 @@ def service_units_from_name(self, name, is_timed=False,
class ComputingAllowanceInterfaceError(Exception):
"""An exception to be raised by the ComputingAllowanceInterface."""
pass


def cached_computing_allowance_interface():
"""Return an instance of ComputingAllowanceInterface. If one is
already in the cache, return it. Otherwise, create one, store it in
the cache, and return it."""
cache_key = 'computing_allowance_interface'
if cache_key in cache:
cache_value = cache.get(cache_key)
computing_allowance_interface = pickle.loads(
b64decode(cache_value.encode('utf-8')))
else:
computing_allowance_interface = ComputingAllowanceInterface()
cache_value = b64encode(
pickle.dumps(computing_allowance_interface)).decode('utf-8')
cache.set(cache_key, cache_value)
return computing_allowance_interface