Skip to content

Commit 1655e79

Browse files
authored
Fix tape full verify (#2327)
1 parent 118f8a4 commit 1655e79

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

ESSArch_Core/storage/backends/tape.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,14 @@ def post_mark_as_full(cls, storage_medium):
278278
"""Called after a medium has been successfully marked as full"""
279279

280280
logger = logging.getLogger('essarch.storage.backends.tape')
281-
drive = str(storage_medium.drive)
281+
drive = storage_medium.tape_drive
282282

283283
logger.debug('Release lock for drive {} and storage medium {} ({})'.format(
284-
drive.pk, storage_medium.medium_id, str(storage_medium.pk)))
284+
drive.pk, storage_medium.medium_id, storage_medium.pk))
285285
cache.delete_pattern(drive.get_lock_key())
286286

287287
logger.debug('Queueing unmount of storage medium {} ({})'.format(
288-
storage_medium.medium_id, str(storage_medium.pk)))
288+
storage_medium.medium_id, storage_medium.pk))
289289
rq, _ = RobotQueue.objects.get_or_create(
290290
user=User.objects.get(username='system'),
291291
storage_medium=storage_medium,
@@ -295,5 +295,5 @@ def post_mark_as_full(cls, storage_medium):
295295

296296
while RobotQueue.objects.filter(id=rq.id).exists():
297297
logger.debug('Wait for the unmount request to complete for storage medium {} ({})'.format(
298-
storage_medium.medium_id, str(storage_medium.pk)))
298+
storage_medium.medium_id, storage_medium.pk))
299299
time.sleep(1)

ESSArch_Core/storage/models.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
import os
44
import pickle
5+
import shutil
56
import tarfile
67
import uuid
78
from datetime import timedelta
@@ -382,7 +383,8 @@ def _create_storage_medium(self):
382383

383384
if storage_type == TAPE:
384385
slot = TapeSlot.objects.filter(status=20, storage_medium__isnull=True,
385-
medium_id__startswith=self.target).exclude(medium_id__exact='').first()
386+
medium_id__startswith=self.target
387+
).exclude(medium_id__exact='').natural_sort().first()
386388
if slot is None:
387389
raise ValueError("No tape available for allocation")
388390
medium = StorageMedium.objects.create(medium_id=slot.medium_id, storage_target=self, status=20,
@@ -669,12 +671,13 @@ def deactivate(self) -> None:
669671
def mark_as_full(self):
670672
logger = logging.getLogger('essarch.storage.models')
671673
logger.debug('Marking storage medium as full: "{}"'.format(str(self.pk)))
674+
logger.info('Storage medium is full, start to verify: "{}"'.format(self.medium_id))
672675
objs = self.storage.annotate(
673676
content_location_value_int=Cast('content_location_value', models.IntegerField())
674677
).order_by('content_location_value_int')
675678

676679
if objs.count() > 3:
677-
objs = [objs.first(), objs[objs.count() / 2], objs.last()]
680+
objs = [objs.first(), objs[int(objs.count() / 2)], objs.last()]
678681

679682
try:
680683
for obj in objs:
@@ -684,11 +687,15 @@ def mark_as_full(self):
684687
logger.exception('Failed to verify storage medium: "{}"'.format(str(self.pk)))
685688
raise
686689
else:
690+
verifydir = Path.objects.get(entity='verify').value
691+
tmppath = os.path.join(verifydir, self.storage_target.target)
692+
shutil.rmtree(tmppath)
687693
self.status = 30
688694
storage_backend = self.storage_target.get_storage_backend()
689695
storage_backend.post_mark_as_full(self)
690696
finally:
691697
self.save(update_fields=['status'])
698+
logger.info('Storage medium is full, content verified success: "{}"'.format(self.medium_id))
692699

693700
class Meta:
694701
permissions = (
@@ -985,7 +992,7 @@ def verify(self):
985992
drive.last_change = timezone.now()
986993
drive.save(update_fields=['last_change'])
987994

988-
filename = os.path.join(tmppath, self.ip.object_identifier_value + '.tar'),
995+
filename = os.path.join(tmppath, self.ip.object_identifier_value + '.tar')
989996
algorithm = self.ip.get_message_digest_algorithm_display()
990997
options = {'expected': self.ip.message_digest, 'algorithm': algorithm}
991998

@@ -1084,6 +1091,11 @@ def __str__(self):
10841091
return self.device
10851092

10861093

1094+
class TapeSlotQueryset(models.QuerySet):
1095+
def natural_sort(self):
1096+
return natural_sort(self, 'medium_id')
1097+
1098+
10871099
class TapeSlot(models.Model):
10881100
STATUS_CHOICES = (
10891101
(0, 'Inactive'),
@@ -1103,6 +1115,8 @@ class TapeSlot(models.Model):
11031115
robot = models.ForeignKey('Robot', models.PROTECT, related_name='tape_slots')
11041116
status = models.IntegerField(choices=STATUS_CHOICES, default=20)
11051117

1118+
objects = TapeSlotQueryset.as_manager()
1119+
11061120
@classmethod
11071121
@transaction.atomic
11081122
@retry(retry=retry_if_exception_type(RequestException), reraise=True, stop=stop_after_attempt(5),

requirements/base.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
asgiref==3.8.1
2-
boto3==1.34.160
2+
boto3==1.35.11
33
celery[tblib]==5.4.0
44
cffi==1.17.0
55
channels==4.1.0
@@ -9,7 +9,7 @@ click==8.1.3
99
cryptography==42.0.8
1010
daphne==4.1.2
1111
dj-rest-auth[with_social]==6.0.0
12-
django==5.0.8
12+
django==5.0.9
1313
django-allauth==0.61.1
1414
django-cors-headers==4.4.0
1515
django-countries-plus==2.2.0

0 commit comments

Comments
 (0)