diff options
-rw-r--r-- | rpkid/rpki/exceptions.py | 5 | ||||
-rw-r--r-- | rpkid/rpki/left_right.py | 29 | ||||
-rw-r--r-- | rpkid/rpki/publication.py | 20 | ||||
-rw-r--r-- | rpkid/rpki/rpki_engine.py | 19 |
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() |