aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2009-09-09 04:00:31 +0000
committerRob Austein <sra@hactrn.net>2009-09-09 04:00:31 +0000
commit5c478ade2f442786c5afa57659a93ec2291d40ed (patch)
tree6de0ac1055d81eee1aa50cfde62492737520003e
parent960282049fbd81c1cd26e86d3461b42ed35d80dd (diff)
Somewhat better handling of publication protocol exceptions and of
errors while attempting to delete repository objects that were never in the repository to begin with. This code is preliminary and may require refactoring later. svn path=/rpkid/rpki/exceptions.py; revision=2742
-rw-r--r--rpkid/rpki/exceptions.py5
-rw-r--r--rpkid/rpki/left_right.py29
-rw-r--r--rpkid/rpki/publication.py20
-rw-r--r--rpkid/rpki/rpki_engine.py19
4 files changed, 56 insertions, 17 deletions
diff --git a/rpkid/rpki/exceptions.py b/rpkid/rpki/exceptions.py
index eb55e702..f055cb53 100644
--- a/rpkid/rpki/exceptions.py
+++ b/rpkid/rpki/exceptions.py
@@ -293,3 +293,8 @@ class HandleTranslationError(RPKI_Exception):
"""
Internal error translating protocol handle -> SQL id.
"""
+
+class NoObjectAtURI(RPKI_Exception):
+ """
+ No object published at specified URI.
+ """
diff --git a/rpkid/rpki/left_right.py b/rpkid/rpki/left_right.py
index c64204b5..7a9ef4f2 100644
--- a/rpkid/rpki/left_right.py
+++ b/rpkid/rpki/left_right.py
@@ -580,8 +580,14 @@ class repository_elt(data_elt):
def done(r_cms):
try:
r_msg = rpki.publication.cms_msg.unwrap(r_cms, bpki_ta_path)
- if len(r_msg) != 1 or isinstance(r_msg[0], rpki.publication.report_error_elt):
- raise rpki.exceptions.BadPublicationReply, "Unexpected response from pubd: %s" % str(r_msg)
+ if len(r_msg) != 1: # Some day we may allow this, but not today
+ raise rpki.exceptions.BadPublicationReply, "Unexpected response from pubd: %r" % r_msg
+ if isinstance(r_msg[0], rpki.publication.report_error_elt):
+ t = rpki.exceptions.__dict__.get(r_msg[0].error_code)
+ if isinstance(t, type) and issubclass(t, rpki.exceptions.RPKI_Exception):
+ raise t, getattr(r_msg[0], "text", None)
+ else:
+ raise rpki.exceptions.BadPublicationReply, "Unexpected response from pubd: %s" % r_msg[0]
callback()
except (rpki.async.ExitNow, SystemExit):
raise
@@ -601,17 +607,26 @@ class repository_elt(data_elt):
"""
Publish one object in the repository.
"""
+ def fail(e):
+ rpki.log.warn("Publication of %r as %r failed: %s" % (obj, uri, e))
+ errback(e)
rpki.log.trace()
- rpki.log.info("Publishing %s as %s" % (repr(obj), repr(uri)))
- self.call_pubd(callback, errback, rpki.publication.obj2elt[type(obj)].make_pdu(action = "publish", uri = uri, payload = obj))
+ rpki.log.info("Publishing %r as %r" % (obj, uri))
+ self.call_pubd(callback, fail, rpki.publication.obj2elt[type(obj)].make_pdu(action = "publish", uri = uri, payload = obj))
- def withdraw(self, obj, uri, callback, errback):
+ def withdraw(self, obj, uri, callback, errback, allow_failure = False):
"""
Withdraw one object from the repository.
"""
+ def fail(e):
+ rpki.log.warn("Withdrawal of %r from %r failed: %s" % (obj, uri, e))
+ if allow_failure and isinstance(e, rpki.exceptions.NoObjectAtURI):
+ callback()
+ else:
+ errback(e)
rpki.log.trace()
- rpki.log.info("Withdrawing %s from at %s" % (repr(obj), repr(uri)))
- self.call_pubd(callback, errback, rpki.publication.obj2elt[type(obj)].make_pdu(action = "withdraw", uri = uri))
+ rpki.log.info("Withdrawing %r from %r" % (obj, uri))
+ self.call_pubd(callback, fail, rpki.publication.obj2elt[type(obj)].make_pdu(action = "withdraw", uri = uri))
class parent_elt(data_elt):
"""
diff --git a/rpkid/rpki/publication.py b/rpkid/rpki/publication.py
index c1dead45..4f50be26 100644
--- a/rpkid/rpki/publication.py
+++ b/rpkid/rpki/publication.py
@@ -32,7 +32,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-import base64, os
+import base64, os, errno
import rpki.resource_set, rpki.x509, rpki.sql, rpki.exceptions, rpki.xml_utils
import rpki.https, rpki.up_down, rpki.relaxng, rpki.sundial, rpki.log, rpki.roa
@@ -229,7 +229,14 @@ class publication_object_elt(rpki.xml_utils.base_elt, publication_namespace):
Withdraw an object.
"""
rpki.log.info("Withdrawing %r" % (self.uri,))
- os.remove(self.uri_to_filename())
+ filename = self.uri_to_filename()
+ try:
+ os.remove(filename)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ raise rpki.exceptions.NoObjectAtURI, "No object published at %r" % self.uri
+ else:
+ raise
def uri_to_filename(self):
"""
@@ -301,6 +308,15 @@ class report_error_elt(rpki.xml_utils.base_elt, publication_namespace):
self.text = str(e)
return self
+ def __str__(self):
+ s = ""
+ if getattr(self, "tag", None) is not None:
+ s += "[%s] " % self.tag
+ s += self.error_code
+ if getattr(self, "text", None) is not None:
+ s += ": " + self.text
+ return s
+
class msg(rpki.xml_utils.msg, publication_namespace):
"""
Publication PDU.
diff --git a/rpkid/rpki/rpki_engine.py b/rpkid/rpki/rpki_engine.py
index b32d5465..d4a5a3a0 100644
--- a/rpkid/rpki/rpki_engine.py
+++ b/rpkid/rpki/rpki_engine.py
@@ -366,7 +366,7 @@ class ca_obj(rpki.sql.sql_persistent):
if ski not in cert_map:
rpki.log.warn("Certificate in database missing from list_response, class %s, SKI %s, maybe parent certificate went away?"
% (repr(rc.class_name), ca_detail.latest_ca_cert.gSKI()))
- ca_detail.delete(self, parent.repository(), iterator, eb)
+ ca_detail.delete(self, parent.repository(), iterator, eb, allow_failure = True)
return
def cleanup():
@@ -604,25 +604,28 @@ class ca_detail_obj(rpki.sql.sql_persistent):
self.generate_crl(callback = did_crl, errback = errback)
- def delete(self, ca, repository, cb, eb):
+ def delete(self, ca, repository, cb, eb, allow_failure = False):
"""
Delete this ca_detail and all of the certs it issued.
+
+ If allow_failure is true, we clean up as much as we can but don't
+ raise an exception.
"""
def withdraw_one_child(iterator, child_cert):
- repository.withdraw(child_cert.cert, child_cert.uri(ca), iterator, eb)
+ repository.withdraw(child_cert.cert, child_cert.uri(ca), iterator, eb, allow_failure)
def child_certs_done():
rpki.async.iterator(self.roas(), withdraw_one_roa, withdraw_manifest)
def withdraw_one_roa(iterator, roa):
- roa.withdraw_roa(iterator, eb)
+ roa.withdraw_roa(iterator, eb, allow_failure = allow_failure)
def withdraw_manifest():
- repository.withdraw(self.latest_manifest, self.manifest_uri(ca), withdraw_crl, eb)
+ repository.withdraw(self.latest_manifest, self.manifest_uri(ca), withdraw_crl, eb, allow_failure)
def withdraw_crl():
- repository.withdraw(self.latest_crl, self.crl_uri(ca), done, eb)
+ repository.withdraw(self.latest_crl, self.crl_uri(ca), done, eb, allow_failure)
def done():
for cert in self.child_certs() + self.revoked_certs():
@@ -1262,7 +1265,7 @@ class roa_obj(rpki.sql.sql_persistent):
ca.parent().repository().publish(self.roa, self.roa_uri(), done, errback)
- def withdraw_roa(self, callback, errback, regenerate = False):
+ def withdraw_roa(self, callback, errback, regenerate = False, allow_failure = False):
"""
Withdraw ROA associated with this roa_obj.
@@ -1283,7 +1286,7 @@ class roa_obj(rpki.sql.sql_persistent):
def one():
rpki.log.debug("Withdrawing ROA and revoking its EE cert")
rpki.rpki_engine.revoked_cert_obj.revoke(cert = cert, ca_detail = ca_detail)
- ca_detail.ca().parent().repository().withdraw(roa, roa_uri, two, errback)
+ ca_detail.ca().parent().repository().withdraw(roa, roa_uri, two, errback, allow_failure)
def two():
self.gctx.sql.sweep()