Merged [5645],[5646] and [5647] from olau@iola.dk:

Added support for notifying the RFC Editor upon draft approval

Added action to post to RFC Editor on non-IESG publication requests too

Fixed a bug that the CC on the announcement copy sent to IANA wasn't
cleared causing people on the CC to get duplicate emails
 - Legacy-Id: 5680
This commit is contained in:
Henrik Levkowetz 2013-04-21 15:53:16 +00:00
parent 231034879f
commit 53b1719860
7 changed files with 94 additions and 7 deletions

View file

@ -882,13 +882,13 @@ class ApproveBallotTestCase(django.test.TestCase):
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue("Send out the announcement" in q('.actions input[type=submit]')[0].get('value'))
self.assertTrue("send out the announcement" in q('.actions input[type=submit]')[0].get('value').lower())
self.assertEquals(len(q('.announcement pre:contains("Subject: Protocol Action")')), 1)
# approve
mailbox_before = len(outbox)
r = self.client.post(url, dict())
r = self.client.post(url, dict(skiprfceditorpost="1"))
self.assertEquals(r.status_code, 302)
draft = Document.objects.get(name=draft.name)
@ -897,6 +897,7 @@ class ApproveBallotTestCase(django.test.TestCase):
self.assertTrue("Protocol Action" in outbox[-2]['Subject'])
# the IANA copy
self.assertTrue("Protocol Action" in outbox[-1]['Subject'])
self.assertTrue(not outbox[-1]['CC'])
self.assertTrue("Protocol Action" in draft.message_set.order_by("-time")[0].subject)
def test_disapprove_ballot(self):
@ -981,7 +982,7 @@ class RequestPublicationTestCase(django.test.TestCase):
# approve
mailbox_before = len(outbox)
r = self.client.post(url, dict(subject=subject, body=body))
r = self.client.post(url, dict(subject=subject, body=body, skiprfceditorpost="1"))
self.assertEquals(r.status_code, 302)
draft = Document.objects.get(name=draft.name)
@ -991,6 +992,7 @@ class RequestPublicationTestCase(django.test.TestCase):
self.assertTrue("Document Action" in draft.message_set.order_by("-time")[0].subject)
# the IANA copy
self.assertTrue("Document Action" in outbox[-1]['Subject'])
self.assertTrue(not outbox[-1]['CC'])
class ExpireIDsTestCase(django.test.TestCase):
fixtures = ['names']

View file

@ -1008,7 +1008,7 @@ def approve_ballotREDESIGN(request, name):
# NOTE: according to Michelle Cotton <michelle.cotton@icann.org>
# (as per 2011-10-24) IANA is scraping these messages for
# information so would like to know beforehand if the format
# changes (perhaps RFC 6359 will change that)
# changes
announcement = approval_text + "\n\n" + ballot_writeup
if request.method == 'POST':
@ -1017,6 +1017,17 @@ def approve_ballotREDESIGN(request, name):
else:
new_state = State.objects.get(used=True, type="draft-iesg", slug="ann")
if new_state.slug == "ann" and not request.REQUEST.get("skiprfceditorpost"):
# start by notifying the RFC Editor
import ietf.sync.rfceditor
response, error = ietf.sync.rfceditor.post_approved_draft(ietf.sync.rfceditor.POST_APPROVED_DRAFT_URL, doc.name)
if error:
return render_to_response('doc/rfceditor_post_approved_draft_failed.html',
dict(name=doc.name,
response=response,
error=error),
context_instance=RequestContext(request))
# fixup document
close_open_ballots(doc, login)
@ -1064,7 +1075,7 @@ def approve_ballotREDESIGN(request, name):
msg.related_docs.add(doc)
return HttpResponseRedirect(doc.get_absolute_url())
return render_to_response('idrfc/approve_ballot.html',
dict(doc=doc,
action=action,

View file

@ -1088,6 +1088,17 @@ def request_publication(request, name):
if request.method == 'POST' and not request.POST.get("reset"):
form = PublicationForm(request.POST)
if form.is_valid():
if not request.REQUEST.get("skiprfceditorpost"):
# start by notifying the RFC Editor
import ietf.sync.rfceditor
response, error = ietf.sync.rfceditor.post_approved_draft(ietf.sync.rfceditor.POST_APPROVED_DRAFT_URL, doc.name)
if error:
return render_to_response('doc/rfceditor_post_approved_draft_failed.html',
dict(name=doc.name,
response=response,
error=error),
context_instance=RequestContext(request))
m.subject = form.cleaned_data["subject"]
m.body = form.cleaned_data["body"]
m.save()

View file

@ -277,6 +277,8 @@ IANA_SYNC_PASSWORD = "secret"
IANA_SYNC_CHANGES_URL = "https://datatracker.iana.org:4443/data-tracker/changes"
IANA_SYNC_PROTOCOLS_URL = "http://www.iana.org/protocols/"
RFC_EDITOR_SYNC_PASSWORD="secret"
# Liaison Statement Tool settings
LIAISON_UNIVERSAL_FROM = 'Liaison Statement Management Tool <lsmt@' + IETF_DOMAIN + '>'
LIAISON_ATTACH_PATH = '/a/www/ietf-datatracker/documents/LIAISON/'

View file

@ -1,4 +1,4 @@
import re, urllib2, json, email, socket
import re, urllib, urllib2, json, email, socket, base64
from xml.dom import pulldom, Node
from django.utils.http import urlquote
@ -12,6 +12,7 @@ from ietf.doc.utils import add_state_change_event
QUEUE_URL = "http://www.rfc-editor.org/queue2.xml"
INDEX_URL = "http://www.rfc-editor.org/rfc/rfc-index.xml"
POST_APPROVED_DRAFT_URL = "https://www.rfc-editor.org/sdev/jsonexp/jsonparser.php"
MIN_QUEUE_RESULTS = 10
MIN_INDEX_RESULTS = 5000
@ -445,3 +446,37 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None):
doc.save()
return results
def post_approved_draft(url, name):
"""Post an approved draft to the RFC Editor so they can retrieve
the data from the Datatracker and start processing it. Returns
response and error (empty string if no error)."""
request = urllib2.Request(url)
request.add_header("Content-type", "application/x-www-form-urlencoded")
request.add_header("Accept", "text/plain")
# HTTP basic auth
username = "dtracksync"
password = settings.RFC_EDITOR_SYNC_PASSWORD
request.add_header("Authorization", "Basic %s" % base64.encodestring("%s:%s" % (username, password)).replace("\n", ""))
text = error = ""
try:
f = urllib2.urlopen(request, data=urllib.urlencode({ 'approved_draft_name': name }), timeout=20)
text = f.read()
status_code = f.getcode()
f.close()
if status_code != 200:
raise Exception("Status code is not 200 OK (it's %s)." % status_code)
if text != "OK":
raise Exception("Response is not \"OK\".")
except Exception as e:
# catch everything so we don't leak exceptions, convert them
# into string instead
error = unicode(e)
return text, error

View file

@ -0,0 +1,26 @@
{# Copyright The IETF Trust 2007, All Rights Reserved #}
{% extends "base.html" %}
{% block title %}Posting Approved Draft to RFC Editor Failed{% endblock %}
{% block content %}
<h1>Posting Approved Draft to RFC Editor Failed</h1>
<p>Sorry, when trying to notify the RFC Editor through HTTP, we hit an
error.</p>
<p>We have not changed the draft state or sent the announcement
yet so if this is an intermittent error, you can go back and try
again.</p>
<p>The error was:</p>
<p><code>{{ error }}</code></p>
{% if response %}
<p>The response from the RFC Editor was:</p>
<p><code>{{ response|linebreaksbr }}</code></p>
{% endif %}
{% endblock %}

View file

@ -32,7 +32,7 @@ form.approve-ballot .announcement {
<div class="actions">
<a href="{% url doc_ballot_approvaltext name=doc.name %}">Back</a>
{% ifequal action "to_announcement_list" %}
<input type="submit" value="Send out the announcement and close ballot"/>
<input type="submit" value="Notify the RFC Editor, send out the announcement and close ballot"/>
{% endifequal %}
{% ifequal action "to_rfc_editor" %}
<input type="submit" value="Send message to the RFC Editor and close ballot"/>