aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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()