diff options
author | Rob Austein <sra@hactrn.net> | 2009-09-09 04:00:31 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2009-09-09 04:00:31 +0000 |
commit | 5c478ade2f442786c5afa57659a93ec2291d40ed (patch) | |
tree | 6de0ac1055d81eee1aa50cfde62492737520003e | |
parent | 960282049fbd81c1cd26e86d3461b42ed35d80dd (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.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() |