Skip to content

Commit

Permalink
Merge pull request #565 from ucb-rit/develop
Browse files Browse the repository at this point in the history
Support MyLRC PCA SU increase; enhance admin UI capabilities
  • Loading branch information
matthew-li authored Aug 29, 2023
2 parents 1cec511 + 8f53b7d commit 34e473e
Show file tree
Hide file tree
Showing 77 changed files with 1,346 additions and 327 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ WORKDIR /vagrant/coldfront_app/coldfront/

CMD ./manage.py initial_setup \
&& ./manage.py add_accounting_defaults \
&& ./manage.py create_allocation_periods \
&& ./manage.py add_allowance_defaults \
&& ./manage.py add_directory_defaults \
&& ./manage.py create_allocation_periods \
&& ./manage.py create_staff_group \
&& ./manage.py collectstatic --noinput \
&& ./manage.py runserver 0.0.0.0:80
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,18 @@ multiple files or directories to omit.
```
3. Build images. In the base directory, run:
```bash
docker build . -t coldfront
# Build an image to serve the website. Run ONE of the following, based on the deployment.
# MyBRC
docker build --build-arg PORTAL=mybrc . -t coldfront
# MyLRC
docker build --build-arg PORTAL=mylrc . -t coldfront

# Build an image to host the database.
docker build . -f Dockerfile.db -t coldfront_db

# Build an image to serve an outgoing email server.
docker build . -f Dockerfile.email -t coldfront_email
```
Note: The above commands build images meant for a MyBRC instance. To build MyLRC images, include `--build-arg PORTAL=mylrc`.
4. Configure environment variables to be injected into containers by creating a `.env` file in the root directory (ignored by Git) or by setting them manually. The password should match those generated via `main.yml`
- `DB_NAME=cf_brc_db`: The name of the database can be customized (e.g., for a MyLRC instance, change it to `cf_lrc_db`).
- `DB_PASSWORD=root`: The password for the database admin user.
Expand All @@ -245,7 +252,7 @@ multiple files or directories to omit.
```
7. To load a database backup, run:
```bash
sh bootstrap/development/docker_load_database_backup.sh ${DB_NAME} ${PATH_TO_DUMP}
sh bootstrap/development/docker_load_database_backup.sh -k ${DB_NAME} ${PATH_TO_DUMP}
```
8. To start from scratch, deleting created volumes, run:
```bash
Expand Down
12 changes: 6 additions & 6 deletions bootstrap/ansible/playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -573,27 +573,27 @@
virtualenv: "{{ git_prefix }}/venv"
become_user: "{{ djangooperator }}"

- name: Run Django management command - add_allowance_defaults
- name: Run Django management command - create_allocation_periods
django_manage:
command: add_allowance_defaults
command: create_allocation_periods
app_path: "{{ git_prefix }}/{{ reponame }}"
settings: "config.settings"
pythonpath: "{{ git_prefix }}/{{ reponame }}/{{ djangoprojname }}"
virtualenv: "{{ git_prefix }}/venv"
become_user: "{{ djangooperator }}"

- name: Run Django management command - add_directory_defaults
- name: Run Django management command - add_allowance_defaults
django_manage:
command: add_directory_defaults
command: add_allowance_defaults
app_path: "{{ git_prefix }}/{{ reponame }}"
settings: "config.settings"
pythonpath: "{{ git_prefix }}/{{ reponame }}/{{ djangoprojname }}"
virtualenv: "{{ git_prefix }}/venv"
become_user: "{{ djangooperator }}"

- name: Run Django management command - create_allocation_periods
- name: Run Django management command - add_directory_defaults
django_manage:
command: create_allocation_periods
command: add_directory_defaults
app_path: "{{ git_prefix }}/{{ reponame }}"
settings: "config.settings"
pythonpath: "{{ git_prefix }}/{{ reponame }}/{{ djangoprojname }}"
Expand Down
2 changes: 1 addition & 1 deletion coldfront/api/utils/tests/test_api_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ def call_setup_commands():
call_command('add_resource_defaults')
call_command('add_allocation_defaults')
call_command('add_accounting_defaults')
call_command('create_allocation_periods')
call_command('add_allowance_defaults')
call_command('add_default_user_choices')
call_command('create_allocation_periods')
call_command('create_staff_group')
sys.stdout = sys.__stdout__

Expand Down
1 change: 1 addition & 0 deletions coldfront/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
path('project/', include('coldfront.core.project.urls')),
path('allocation/', include('coldfront.core.allocation.urls')),
path('jobs/', include('coldfront.core.statistics.urls')),
path('billing/', include('coldfront.core.billing.urls')),
# path('grant/', include('coldfront.core.grant.urls')),
# path('publication/', include('coldfront.core.publication.urls')),
# path('research-output/', include('coldfront.core.research_output.urls')),
Expand Down
20 changes: 18 additions & 2 deletions coldfront/core/allocation/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,24 @@
AllocationUserStatusChoice,
AttributeType, SecureDirRequest,
SecureDirAddUserRequest,
SecureDirRemoveUserRequest)

SecureDirRemoveUserRequest,
AllocationRenewalRequest,
AllocationAdditionRequestStatusChoice,
AllocationAdditionRequest,
SecureDirAddUserRequestStatusChoice,
SecureDirRemoveUserRequestStatusChoice,
SecureDirRequestStatusChoice,
ClusterAccessRequestStatusChoice,
ClusterAccessRequest, )

admin.site.register(AllocationRenewalRequest)
admin.site.register(AllocationAdditionRequestStatusChoice)
admin.site.register(AllocationAdditionRequest)
admin.site.register(SecureDirAddUserRequestStatusChoice)
admin.site.register(SecureDirRemoveUserRequestStatusChoice)
admin.site.register(SecureDirRequestStatusChoice)
admin.site.register(ClusterAccessRequestStatusChoice)
admin.site.register(ClusterAccessRequest)

@admin.register(AllocationStatusChoice)
class AllocationStatusChoiceAdmin(admin.ModelAdmin):
Expand Down
14 changes: 8 additions & 6 deletions coldfront/core/allocation/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,26 +286,28 @@ def __init__(self, *args, **kwargs):

def label_from_instance(self, obj):
computing_allowance = ComputingAllowance(self.computing_allowance)
num_service_units = self.allocation_value()
num_service_units = self.allocation_value(obj)
if computing_allowance.are_service_units_prorated():
num_service_units = prorated_allocation_amount(
num_service_units, utc_now_offset_aware(), obj)
return (
f'{obj.name} ({obj.start_date} - {obj.end_date}) '
f'({num_service_units} SUs)')

def allocation_value(self):
"""Return the default allocation value (Decimal) to use based on
the allocation type."""
def allocation_value(self, obj):
"""Return the allocation value (Decimal) to use based on the
allocation type and the AllocationPeriod."""
allowance_name = self.computing_allowance.name
if flag_enabled('BRC_ONLY'):
assert allowance_name in self._allowances_with_periods_brc()
return Decimal(
self.interface.service_units_from_name(allowance_name))
self.interface.service_units_from_name(
allowance_name, is_timed=True, allocation_period=obj))
elif flag_enabled('LRC_ONLY'):
assert allowance_name in self._allowances_with_periods_lrc()
return Decimal(
self.interface.service_units_from_name(allowance_name))
self.interface.service_units_from_name(
allowance_name, is_timed=True, allocation_period=obj))
return settings.ALLOCATION_MIN

@staticmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ def handle(self, *args, **options):
yearly_allowances.append(allowance)
num_service_units_by_allowance_name[allowance.name] = Decimal(
computing_allowance_interface.service_units_from_name(
allowance.name))
allowance.name, is_timed=True,
allocation_period=allocation_period))

allocation_period_start_utc = display_time_zone_date_to_utc_datetime(
allocation_period_start_date)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ def process_allocation_renewal_requests(self, allocation_period,
eligible_requests = model.objects.filter(
allocation_period=allocation_period, status__name='Approved')
self.process_requests(
model, runner_class, eligible_requests, skip_emails, dry_run)
allocation_period, model, runner_class, eligible_requests,
skip_emails, dry_run)

def process_new_project_requests(self, allocation_period, skip_emails,
dry_run):
Expand All @@ -242,14 +243,16 @@ def process_new_project_requests(self, allocation_period, skip_emails,
allocation_period=allocation_period,
status__name='Approved - Scheduled')
self.process_requests(
model, runner_class, eligible_requests, skip_emails, dry_run)

def process_requests(self, model, runner_class, requests, skip_emails,
dry_run):
"""Given a request model, a runner class for processing
instances of that model, and a queryset of instances to process,
run the runner on each instance. Optionally skip sending emails.
Optionally display updates instead of performing them."""
allocation_period, model, runner_class, eligible_requests,
skip_emails, dry_run)

def process_requests(self, allocation_period, model, runner_class, requests,
skip_emails, dry_run):
"""Given an AllocationPeriod, a request model, a runner class
for processing instances of that model, and a queryset of
instances to process, run the runner on each instance.
Optionally skip sending emails. Optionally display updates
instead of performing them."""
model_name = model.__name__
num_successes, num_failures = 0, 0

Expand All @@ -263,7 +266,8 @@ def process_requests(self, model, runner_class, requests, skip_emails,
data = {
'num_service_units': Decimal(
interface.service_units_from_name(
wrapper.get_name())),
wrapper.get_name(), is_timed=True,
allocation_period=allocation_period)),
'is_prorated': wrapper.are_service_units_prorated(),
}
cached_allowance_data[computing_allowance] = data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

from django.contrib.auth.models import User
from django.core import mail
from django.core.exceptions import ImproperlyConfigured
from django.core.management import call_command
from django.core.management.base import CommandError

from flags.state import flag_enabled

from coldfront.core.allocation.models import AllocationPeriod
from coldfront.core.allocation.models import AllocationRenewalRequest
from coldfront.core.allocation.models import AllocationRenewalRequestStatusChoice
Expand All @@ -17,6 +20,7 @@
from coldfront.core.project.utils_.renewal_utils import get_next_allowance_year_period
from coldfront.core.resource.models import Resource
from coldfront.core.resource.utils_.allowance_utils.constants import BRCAllowances
from coldfront.core.resource.utils_.allowance_utils.constants import LRCAllowances
from coldfront.core.resource.utils_.allowance_utils.interface import ComputingAllowanceInterface
from coldfront.core.utils.common import display_time_zone_current_date
from coldfront.core.utils.common import display_time_zone_date_to_utc_datetime
Expand All @@ -32,10 +36,19 @@ class TestApproveRenewalRequestsForAllocationPeriod(TestBase):
def setUp(self):
"""Set up test data."""
super().setUp()
computing_allowance = Resource.objects.get(name=BRCAllowances.FCA)
if flag_enabled('BRC_ONLY'):
self.computing_allowance_name = BRCAllowances.FCA
elif flag_enabled('LRC_ONLY'):
self.computing_allowance_name = LRCAllowances.PCA
else:
raise ImproperlyConfigured
computing_allowance = Resource.objects.get(
name=self.computing_allowance_name)
next_allocation_period = get_next_allowance_year_period()
self.num_service_units = Decimal(
ComputingAllowanceInterface().service_units_from_name(
computing_allowance.name))
computing_allowance.name, is_timed=True,
allocation_period=next_allocation_period))

@staticmethod
def call_command(allocation_period_id, dry_run=False):
Expand All @@ -52,8 +65,7 @@ def call_command(allocation_period_id, dry_run=False):
call_command(*args, **kwargs)
return out.getvalue(), err.getvalue()

@staticmethod
def create_request_and_supporting_objects(allocation_period):
def create_request_and_supporting_objects(self, allocation_period):
"""Create and return an AllocationRenewalRequest, a Project, a
requester, and a PI, under the given AllocationPeriod."""
project_name = 'fc_project'
Expand All @@ -77,7 +89,8 @@ def create_request_and_supporting_objects(allocation_period):
request = AllocationRenewalRequest.objects.create(
requester=requester,
pi=pi,
computing_allowance=Resource.objects.get(name=BRCAllowances.FCA),
computing_allowance=Resource.objects.get(
name=self.computing_allowance_name),
allocation_period=allocation_period,
status=AllocationRenewalRequestStatusChoice.objects.get(
name='Under Review'),
Expand All @@ -97,6 +110,9 @@ def test_allocation_period_nonexistent(self):
def test_allocation_period_not_allowance_year(self):
"""Test that an Allocation Period that does not represent an
allowance year raises an error."""
if flag_enabled('LRC_ONLY'):
# There are no such periods on LRC.
return
_id = AllocationPeriod.objects.exclude(
name__startswith='Allowance Year').first().id
with self.assertRaises(CommandError) as cm:
Expand All @@ -117,8 +133,9 @@ def test_allocation_period_already_started(self):
def test_requests_limited_by_conditions(self):
"""Test that a request is only considered if it meets the
following conditions: its status is 'Under Review', its
post_project is an FCA, its allocation_period is the given one,
and its request_time is before the start_date of the period."""
post_project is an FCA (BRC) or PCA (LRC), its allocation_period
is the given one, and its request_time is before the start_date
of the period."""
# A condition-meeting request should be included.
allocation_period = get_next_allowance_year_period()
_id = allocation_period.id
Expand Down Expand Up @@ -150,17 +167,26 @@ def test_requests_limited_by_conditions(self):
self.assertIn(expected_message, output)
self.assertFalse(error)

# Non-FCA/PCA project
# Non-FCA (BRC) or PCA (LRC) project
project = request.post_project
tmp_project_name = project.name
tmp_computing_allowance = request.computing_allowance
computing_allowance_interface = ComputingAllowanceInterface()
allowance_names = (
BRCAllowances.CO,
BRCAllowances.ICA,
BRCAllowances.PCA,
BRCAllowances.RECHARGE,
)

if flag_enabled('BRC_ONLY'):
allowance_names = (
BRCAllowances.CO,
BRCAllowances.ICA,
BRCAllowances.PCA,
BRCAllowances.RECHARGE,
)
elif flag_enabled('LRC_ONLY'):
allowance_names = (
LRCAllowances.LR,
LRCAllowances.RECHARGE,
)
else:
raise ImproperlyConfigured
for allowance_name in allowance_names:
prefix = computing_allowance_interface.code_from_name(
allowance_name)
Expand Down
Loading

0 comments on commit 34e473e

Please sign in to comment.