Skip to content

Commit 4157f7f

Browse files
Initial version of asking approval feature
Removed deprecated HomePageView
1 parent 7d9322b commit 4157f7f

File tree

7 files changed

+65
-47
lines changed

7 files changed

+65
-47
lines changed

DMOps/file_invalidation_server/fi_manager/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ class FileInvalidationRequests(models.Model):
1818
reason = models.TextField(blank=True, null=True)
1919
job_id = models.CharField(max_length=8,null=True,blank=True)
2020
logs = models.TextField()
21+
rse = models.TextField()
2122
global_invalidate_last_replicas = models.BooleanField(default=False)
23+
request_user = models.TextField()
24+
approve_user = models.TextField()
2225

2326
class Meta:
2427
managed = False

DMOps/file_invalidation_server/fi_manager/process_jobs.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,10 @@ def fetch_and_process():
7373

7474
delete_opts = client.V1DeleteOptions(propagation_policy='Foreground')
7575

76-
#batch_v1.delete_namespaced_job(
77-
# name=job_name,
78-
# namespace=namespace,
79-
# body=delete_opts)
80-
logger.info(f"Job {job_name} would be deleted but is being kept for dev purposes.")
76+
batch_v1.delete_namespaced_job(
77+
name=job_name,
78+
namespace=namespace,
79+
body=delete_opts)
8180

8281
def parse_job_logs(logs: str):
8382
if "Error running shell script" in logs:

DMOps/file_invalidation_server/fi_manager/templates/core/home.html

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from django.urls import path
2-
from .views import FileInvalidationRequestsView, FileQueryView
2+
from .views import FileInvalidationRequestsView, FileQueryView, InvalidationApproval
33

44

55
urlpatterns = [
66
path("upload/", FileInvalidationRequestsView.as_view(), name="file-upload"),
77
path("query/", FileQueryView.as_view(), name="file-query"),
8+
path("approve/<request_id:request_id>", InvalidationApproval.as_view(), name="invalidation-approval"),
89
]

DMOps/file_invalidation_server/fi_manager/tasks.py renamed to DMOps/file_invalidation_server/fi_manager/utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@
1212
src_dir = os.path.dirname(current_dir)
1313
yaml_path = os.path.join(src_dir, 'controllers', 'job.yaml')
1414

15+
def get_cern_username(request):
16+
return (
17+
request.META.get("HTTP_X_FORWARDED_PREFERRED_USERNAME")
18+
or request.META.get("HTTP_X_FORWARDED_USER")
19+
or request.META.get("REMOTE_USER")
20+
)
1521

16-
def process_invalidation(request_id, reason, dry_run=True,mode='global',rse=None,to_process='queued',global_invalidate_last_replicas=False):
22+
23+
def process_invalidation(request_id, reason, dry_run=True,mode='global',rse=None,to_process='approved',global_invalidate_last_replicas=False):
1724
file_records = FileInvalidationRequests.objects.filter(request_id=request_id,status=to_process)
1825
if file_records.count()==0:
1926
raise ValueError(f'There are no records in the db for the request_id: {request_id}')

DMOps/file_invalidation_server/fi_manager/views.py

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55
from .models import FileInvalidationRequests
66
import base64
77
from django.http import HttpResponse
8-
from .tasks import process_invalidation
8+
from .utils import process_invalidation, get_cern_username
99
from django.views.generic import TemplateView
1010
from django.db.models import Count, CharField, Value, F, Case, When
1111
from django.db.models.functions import StrIndex, Substr
1212
import logging
1313
import uuid
14-
dids_limit = 1000
1514

1615
class FileInvalidationRequestSerializer(serializers.Serializer):
1716
reason = serializers.CharField(required=True,help_text="Enter the reason for the file invalidation request.")
@@ -81,40 +80,32 @@ def post(self, request, *args, **kwargs):
8180

8281
file_lines = file_lines.splitlines()
8382
request_id = uuid.uuid4()
83+
logging.info({k: v for k, v in request.META.items() if k.startswith("HTTP_") or k == "REMOTE_USER"})
84+
user = get_cern_username(request)
8485

8586
cnt = 0
86-
if len(file_lines)>dids_limit:
87-
return Response({"message": f"Request aborted. The file exceeds DIDs limit ({len(file_lines)}>{dids_limit})"}, status=status.HTTP_400_BAD_REQUEST)
8887

8988
raw_file_message = ""
9089
already_serviced_files = ""
9190
for fn in file_lines:
9291
fn = fn.strip()
9392
fn = fn.replace('cms:/store','/store')
9493
obj = FileInvalidationRequests.objects.filter(file_name=fn).filter(dry_run=False).first()
95-
if '/RAW/' in fn:
96-
raw_file_message = raw_file_message +f'\nRequest aborted for file {fn}. File contains RAW data.'
97-
input_vals = {'request_id':request_id,'file_name':fn,'status':'aborted','mode':mode,'dry_run':dry_run,'reason':reason,'logs':f'Request aborted for file {fn}. File contains RAW data.'}
98-
file_record = FileInvalidationRequests.objects.create(**input_vals)
99-
elif obj:
94+
if obj:
10095
already_serviced_files = already_serviced_files + f'\nRequest was not created for file {fn} because it has already been submitted and it is currently in status: {obj.status}.'
10196
if obj.status=="in_progress":
10297
already_serviced_files = already_serviced_files + ' Please wait 30min for the CronJob to update it on the database'
98+
elif obj.status=="waiting_approval":
99+
already_serviced_files = already_serviced_files + ' Please ask DMOps to approve the invalidation.'
103100
else:
104-
input_vals = {'request_id':request_id,'file_name':fn,'status':'queued','mode':mode,'dry_run':dry_run,'reason':reason,'global_invalidate_last_replicas':global_invalidate_last_replicas}
101+
input_vals = {'request_id':request_id,'file_name':fn,'status':'waiting_approval','mode':mode,'dry_run':dry_run,'reason':reason,'global_invalidate_last_replicas':global_invalidate_last_replicas,'request_user':user, 'rse': rse}
105102
file_record = FileInvalidationRequests.objects.create(**input_vals)
106103
cnt += 1
107104

108-
logging.info(f'{cnt} of {len(file_lines)} files were created in the database with queued status.')
105+
logging.info(f'{cnt} of {len(file_lines)} files were created in the database with waiting_approval status.')
109106

110-
response_message = ""
111-
if cnt>0:
112-
logging.info(f'Processing request id {request_id}...')
113-
response_message = process_invalidation(request_id, reason,dry_run=dry_run,mode=mode,rse=rse,to_process='queued',global_invalidate_last_replicas=global_invalidate_last_replicas)
114-
else:
115-
return Response({"message": f"None of the files could be invalidated. {raw_file_message}, {already_serviced_files}"}, status=status.HTTP_400_BAD_REQUEST)
116107

117-
response_message = response_message + raw_file_message + already_serviced_files
108+
response_message = raw_file_message + already_serviced_files
118109

119110
return Response({"message": response_message,
120111
"redirect_url":f"https://file-invalidation.app.cern.ch/api/query/?request_id={request_id}",
@@ -174,9 +165,43 @@ def get(self, request, *args, **kwargs):
174165
)
175166

176167

177-
class HomePageView(TemplateView):
178-
template_name = 'core/home.html'
168+
class InvalidationApproval(APIView):
169+
170+
def get(self, request, request_id):
171+
files = FileInvalidationRequests.objects.filter(request_id=request_id)
172+
173+
return Response(
174+
[{"request_id": f.request_id, "file_name": f.file_name, "status": f.status,"mode":f.mode,"dry_run":f.dry_run,"reason":f.reason,"job_id":f.job_id,"logs":f.logs,"request_user":f.request_user} for f in files],
175+
status=status.HTTP_200_OK
176+
)
177+
178+
179+
def post(self, request, request_id):
180+
files = FileInvalidationRequests.objects.filter(request_id=request_id)
181+
182+
if not files.exists():
183+
return Response({"message":f"Files with request_id {request_id} not found"},
184+
status=status.HTTP_404_NOT_FOUND)
185+
186+
approval_user = get_cern_username(request)
187+
request_user = files.first().request_user
179188

180-
def get_context_data(self, **kwargs):
181-
context = super().get_context_data(**kwargs)
182-
return context
189+
if approval_user==request_user:
190+
return Response({"message":f"Approval user cannot be the same as request user"},
191+
status=status.HTTP_403_FORBIDDEN)
192+
193+
updated = files.update(status="approved",approval_user=approval_user)
194+
reason = updated.first().reason
195+
dry_run = updated.first().dry_run
196+
mode = updated.first().mode
197+
rse = updated.first().rse
198+
global_invalidate_last_replicas = updated.first().global_invalidate_last_replicas
199+
200+
try:
201+
response_message = process_invalidation(request_id, reason, dry_run=dry_run, mode=mode, rse=rse,to_process="approved",global_invalidate_last_replicas=global_invalidate_last_replicas)
202+
return Response({"message": response_message,
203+
"redirect_url":f"https://file-invalidation.app.cern.ch/api/query/?request_id={request_id}",
204+
"redirect_description":"View request_id details"}, status=status.HTTP_201_CREATED)
205+
206+
except Exception as e:
207+
return Response({"message":f"None of the files could be invalidated - {str(e)}"})

DMOps/file_invalidation_server/file_invalidation_server/urls.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
"""
1717
from django.contrib import admin
1818
from django.urls import path, include
19-
from fi_manager.views import HomePageView
2019

2120
urlpatterns = [
2221
path('admin/', admin.site.urls),
2322
path("api/", include("fi_manager.urls")),
24-
path("", HomePageView.as_view(), name='home')
2523
]

0 commit comments

Comments
 (0)