datatracker/ietf/idrfc/expire.py
2011-03-04 19:07:57 +00:00

249 lines
9.4 KiB
Python

# expiry of Internet Drafts
from django.conf import settings
from django.template.loader import render_to_string
from django.db.models import Q
import datetime, os, shutil, glob, re
from ietf.idtracker.models import InternetDraft, IDDates, IDStatus, IDState, DocumentComment
from ietf.utils.mail import send_mail
from ietf.idrfc.utils import log_state_changed, add_document_comment
from doc.models import Document, Event, save_document_in_history
from name.models import IesgDocStateName, DocStateName, DocInfoTagName
from person.models import Email
INTERNET_DRAFT_DAYS_TO_EXPIRE = 185
def in_id_expire_freeze(when=None):
if when == None:
when = datetime.datetime.now()
d = IDDates.objects.get(id=IDDates.SECOND_CUT_OFF).date
# for some reason, the old Perl code started at 9 am
second_cut_off = datetime.datetime.combine(d, datetime.time(9, 0))
d = IDDates.objects.get(id=IDDates.IETF_MONDAY).date
ietf_monday = datetime.datetime.combine(d, datetime.time(0, 0))
return second_cut_off <= when < ietf_monday
def get_expired_ids():
cut_off = datetime.date.today() - datetime.timedelta(days=InternetDraft.DAYS_TO_EXPIRE)
return InternetDraft.objects.filter(
revision_date__lte=cut_off,
status__status="Active",
review_by_rfc_editor=0).filter(
Q(idinternal=None) | Q(idinternal__cur_state__document_state_id__gte=42))
def get_expired_idsREDESIGN():
cut_off = datetime.date.today() - datetime.timedelta(days=INTERNET_DRAFT_DAYS_TO_EXPIRE)
docs = Document.objects.filter(state="active").exclude(tags="rfc-rev").filter(Q(iesg_state=None) | Q(iesg_state__order__gte=42))
for d in docs:
e = d.latest_event(type="new_revision")
if e and e.time.date() <= cut_off:
yield d
def send_expire_notice_for_id(doc):
doc.dunn_sent_date = datetime.date.today()
doc.save()
if not doc.idinternal:
return
request = None
to = u"%s <%s>" % doc.idinternal.job_owner.person.email()
send_mail(request, to,
"I-D Expiring System <ietf-secretariat-reply@ietf.org>",
u"I-D was expired %s" % doc.file_tag(),
"idrfc/id_expired_email.txt",
dict(doc=doc,
state=doc.idstate()))
def send_expire_notice_for_idREDESIGN(doc):
if not doc.ad:
return
state = doc.iesg_state.name if doc.iesg_state else "I-D Exists"
request = None
to = doc.ad.formatted_email()
send_mail(request, to,
"I-D Expiring System <ietf-secretariat-reply@ietf.org>",
u"I-D was expired %s" % doc.file_tag(),
"idrfc/id_expired_email.txt",
dict(doc=doc,
state=state,
))
def expire_id(doc):
def move_file(f):
src = os.path.join(settings.INTERNET_DRAFT_PATH, f)
dst = os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, f)
if os.path.exists(src):
shutil.move(src, dst)
move_file("%s-%s.txt" % (doc.filename, doc.revision_display()))
move_file("%s-%s.ps" % (doc.filename, doc.revision_display()))
move_file("%s-%s.pdf" % (doc.filename, doc.revision_display()))
new_revision = "%02d" % (int(doc.revision) + 1)
new_file = open(os.path.join(settings.INTERNET_DRAFT_PATH, "%s-%s.txt" % (doc.filename, new_revision)), 'w')
txt = render_to_string("idrfc/expire_text.txt",
dict(doc=doc,
authors=[a.person.email() for a in doc.authors.all()],
expire_days=InternetDraft.DAYS_TO_EXPIRE))
new_file.write(txt)
new_file.close()
doc.revision = new_revision
doc.expiration_date = datetime.date.today()
doc.last_modified_date = datetime.date.today()
doc.status = IDStatus.objects.get(status="Expired")
doc.save()
if doc.idinternal:
if doc.idinternal.cur_state_id != IDState.DEAD:
doc.idinternal.change_state(IDState.objects.get(document_state_id=IDState.DEAD), None)
log_state_changed(None, doc, "system")
add_document_comment(None, doc, "Document is expired by system")
def expire_idREDESIGN(doc):
system_email = Email.objects.get(address="(System)")
# clean up files
def move_file(f):
src = os.path.join(settings.INTERNET_DRAFT_PATH, f)
dst = os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, f)
if os.path.exists(src):
shutil.move(src, dst)
file_types = ['txt', 'ps', 'pdf']
for t in file_types:
move_file("%s-%s.%s" % (doc.name, doc.rev, t))
# make tombstone
new_revision = "%02d" % (int(doc.rev) + 1)
new_file = open(os.path.join(settings.INTERNET_DRAFT_PATH, "%s-%s.txt" % (doc.name, new_revision)), 'w')
txt = render_to_string("idrfc/expire_textREDESIGN.txt",
dict(doc=doc,
authors=[(e.get_name(), e.address) for e in doc.authors.all()],
expire_days=InternetDraft.DAYS_TO_EXPIRE))
new_file.write(txt)
new_file.close()
# now change the states
save_document_in_history(doc)
if doc.latest_event(type='started_iesg_process'):
dead_state = IesgDocStateName.objects.get(slug="dead")
if doc.iesg_state != dead_state:
prev = doc.iesg_state
doc.iesg_state = dead_state
log_state_changed(None, doc, system_email, prev)
e = Event(doc=doc, by=system_email)
e.type = "expired_document"
e.desc = "Document has expired"
e.save()
doc.rev = new_revision # FIXME: incrementing the revision like this is messed up
doc.state = DocStateName.objects.get(slug="expired")
doc.time = datetime.datetime.now()
doc.save()
def clean_up_id_files():
"""Move unidentified and old files out of the Internet Draft directory."""
cut_off = datetime.date.today() - datetime.timedelta(days=InternetDraft.DAYS_TO_EXPIRE)
pattern = os.path.join(settings.INTERNET_DRAFT_PATH, "draft-*.*")
files = []
filename_re = re.compile('^(.*)-(\d+)$')
for path in glob.glob(pattern):
basename = os.path.basename(path)
stem, ext = os.path.splitext(basename)
match = filename_re.search(stem)
if not match:
filename, revision = ("UNKNOWN", "00")
else:
filename, revision = match.groups()
def move_file_to(subdir):
shutil.move(path,
os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, subdir, basename))
try:
doc = InternetDraft.objects.get(filename=filename, revision=revision)
if doc.status_id == 3:
if ext != ".txt":
move_file_to("unknown_ids")
elif doc.status_id in (2, 4, 5, 6) and doc.expiration_date and doc.expiration_date < cut_off:
if os.path.getsize(path) < 1500:
move_file_to("deleted_tombstones")
# revert version after having deleted tombstone
doc.revision = "%02d" % (int(revision) - 1)
doc.expired_tombstone = True
doc.save()
else:
move_file_to("expired_without_tombstone")
except InternetDraft.DoesNotExist:
move_file_to("unknown_ids")
def clean_up_id_filesREDESIGN():
"""Move unidentified and old files out of the Internet Draft directory."""
cut_off = datetime.date.today() - datetime.timedelta(days=INTERNET_DRAFT_DAYS_TO_EXPIRE)
pattern = os.path.join(settings.INTERNET_DRAFT_PATH, "draft-*.*")
files = []
filename_re = re.compile('^(.*)-(\d+)$')
for path in glob.glob(pattern):
basename = os.path.basename(path)
stem, ext = os.path.splitext(basename)
match = filename_re.search(stem)
if not match:
filename, revision = ("UNKNOWN", "00")
else:
filename, revision = match.groups()
def move_file_to(subdir):
shutil.move(path,
os.path.join(settings.INTERNET_DRAFT_ARCHIVE_DIR, subdir, basename))
try:
doc = Document.objects.get(name=filename, rev=revision)
if doc.state_id == "rfc":
if ext != ".txt":
move_file_to("unknown_ids")
elif doc.state_id in ("expired", "auth-rm", "repl", "ietf-rm"):
e = doc.latest_event(type__in=('expired_document', 'new_revision', "completed_resurrect"))
expiration_date = e.time.date() if e and e.type == "expired_document" else None
if expiration_date and expiration_date < cut_off:
if os.path.getsize(path) < 1500:
move_file_to("deleted_tombstones")
# revert version after having deleted tombstone
doc.rev = "%02d" % (int(revision) - 1) # FIXME: messed up
doc.save()
doc.tags.add(DocInfoTagName.objects.get(slug='exp-tomb'))
else:
move_file_to("expired_without_tombstone")
except Document.DoesNotExist:
move_file_to("unknown_ids")
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
get_expired_ids = get_expired_idsREDESIGN
send_expire_notice_for_id = send_expire_notice_for_idREDESIGN
expire_id = expire_idREDESIGN
clean_up_id_files = clean_up_id_filesREDESIGN