diff options
-rw-r--r-- | scripts/PLAN | 32 | ||||
-rw-r--r-- | scripts/rpki/left_right.py | 83 | ||||
-rwxr-xr-x | scripts/rpkid.py | 59 |
3 files changed, 107 insertions, 67 deletions
diff --git a/scripts/PLAN b/scripts/PLAN index fc61268f..051adecf 100644 --- a/scripts/PLAN +++ b/scripts/PLAN @@ -101,3 +101,35 @@ objects and database objects, objects shown in green are only database objects, and left-right PDU objects not shown in that picture are just left-right PDUs. Or something close to this, details need checking. So this does look like some kind of mixin would be appropriate. + + + +Code to pull in an entire self_id context at once turned out to be +much too complicated. Replacement is more of a demand-paged design. +Need to be careful about making sure we save out all changes between +events, objects have a .sql_dirty attribute but I should also add a +Python set object into which we can insert any object that needs to be +saved when the current event exits. + +Haven't done anything about db.commit() and db.rollback() yet, for +that matter haven't yet whacked MySQL to enable those features. + +Hack du jour is rpki.left_right.data_obj.serve_copy_hook(). I've +implemented this for bsc objects, seems to work, haven't yet done (eg) +route_origin objects. + +left-right protocol needs boolean flags to reset array values like +bsc.signing_cert[]. Trivial hack, just haven't done it yet. + +Access to object data attributes really ought to be through accessor +methods so that the .set() method can set the sql_dirty flag +automagically. Not done yet. + +Hmm, do we really need .sql_dirty at all? Maybe just inserting the +object into the dirty set (above) would suffice? One less thing to +screw up. + +RelaxNG schemas probably ought to be internal rather than files with +magic names or config variables pointing at files. Makefile hack to +put a Python wrapper around a .rng file, and automatically convert +.rng to lxml internal form while we're at it? diff --git a/scripts/rpki/left_right.py b/scripts/rpki/left_right.py index c23b0581..7156dc99 100644 --- a/scripts/rpki/left_right.py +++ b/scripts/rpki/left_right.py @@ -55,9 +55,7 @@ class base_elt(object): lxml.etree.tostring(self.toXML(), pretty_print=True, encoding="us-ascii") class data_elt(base_elt, rpki.sql.sql_persistant): - """Virtual type for a left-right protocol message elements representing - top-level persistant data elements. - """ + """Virtual class for top-level left-right protocol data elements.""" def sql_decode(self, vals): rpki.sql.sql_persistant.sql_decode(self, vals) @@ -70,13 +68,68 @@ class data_elt(base_elt, rpki.sql.sql_persistant): d["peer_ta"] = self.peer_ta.get_DER() return d -def get_ta_DER(thing): - """None-tolerant wrapper around rpki.x509.X509.get_DER().""" - if thing is None: - return None - else: - return thing.get_DER() + def make_reply(self, r_pdu=None): + if r_pdu is None: + r_pdu = self.__class__() + r_pdu.self_id = self.self_id + setattr(r_pdu, self.sql_template.index, getattr(self, self.sql_template.index)) + r_pdu.action = self.action + r_pdu.type = "reply" + return r_pdu + + def serve_create(self, db, cur, r_msg): + r_pdu = self.make_reply() + self.sql_store(db, cur) + setattr(r_pdu, self.sql_template.index, getattr(self, self.sql_template.index)) + r_msg.append(r_pdu) + + def serve_copy_hook(self, db_pdu): + pass + + def serve_set(self, db, cur, r_msg): + db_pdu = self.sql_fetch(db, cur, getattr(self, self.sql_template.index)) + if db_pdu is not None: + for a in db_pdu.sql_template.columns[1:]: + v = getattr(self, a) + if v is not None: + setattr(db_pdu, a, v) + db_pdu.sql_dirty = True + self.serve_copy_hook(db_pdu) + db_pdu.sql_store(db, cur) + r_pdu = self.make_reply() + r_msg.append(r_pdu) + else: + r_msg.append(make_error_report(self)) + def serve_get(self, db, cur, r_msg): + r_pdu = self.sql_fetch(db, cur, getattr(self, self.sql_template.index)) + if r_pdu is not None: + self.make_reply(r_pdu) + r_msg.append(r_pdu) + else: + r_msg.append(make_error_report(self)) + + def serve_list(self, db, cur, r_msg): + for r_pdu in self.sql_fetch_all(db, cur): + self.make_reply(r_pdu) + r_msg.append(r_pdu) + + def serve_destroy(self, db, cur, r_msg): + db_pdu = self.sql_fetch(db, cur, getattr(self, self.sql_template.index)) + if db_pdu is not None: + db_pdu.sql_delete(db, cur) + r_msg.append(self.make_reply()) + else: + r_msg.append(make_error_report(self)) + + def serve_dispatch(self, db, cur, r_msg): + assert self.type == "query" + { "create" : self.serve_create, + "set" : self.serve_set, + "get" : self.serve_get, + "list" : self.serve_list, + "destroy" : self.serve_destroy }[self.action](db, cur, r_msg) + class extension_preference_elt(base_elt): """Container for extension preferences.""" @@ -126,6 +179,18 @@ class bsc_elt(data_elt): def sql_delete_hook(self, db, cur): cur.execute("DELETE FROM bsc_cert WHERE bsc_id = %s", self.bsc_id) + def serve_copy_hook(self, db_pdu): + if self.signing_cert is not None: + # + # If we had a flag telling us to reset the signing_cert list, we'd + # check for it here. For the moment, assume we always concatenate + # and never overwrite. + # + if False: + db_pdu.signing_cert = self.signing_cert + else: + db_pdu.signing_cert = db_pdu.signing_cert + self.signing_cert + def startElement(self, stack, name, attrs): """Handle <bsc/> element.""" if not name in ("signing_cert", "public_key", "pkcs10_cert_request"): diff --git a/scripts/rpkid.py b/scripts/rpkid.py index 6f0f06bf..94d98fed 100755 --- a/scripts/rpkid.py +++ b/scripts/rpkid.py @@ -17,57 +17,6 @@ def encode(msg, cms_key, cms_certs): return rpki.cms.encode(lxml.etree.tostring(msg, pretty_print=True, encoding="us-ascii", xml_declaration=True), cms_key, cms_certs) def left_right_handler(query, path): - - def make_reply(q_pdu, r_pdu=None): - if r_pdu is None: - r_pdu = q_pdu.__class__() - r_pdu.self_id = q_pdu.self_id - setattr(r_pdu, q_pdu.sql_template.index, getattr(q_pdu, q_pdu.sql_template.index)) - r_pdu.action = q_pdu.action - r_pdu.type = "reply" - return r_pdu - - def destroy_handler(q_pdu): - data = q_pdu.sql_fetch(db, cur, getattr(q_pdu, q_pdu.sql_template.index)) - if data is not None: - data.sql_delete(db, cur) - r_msg.append(make_reply(q_pdu)) - else: - r_msg.append(make_error_report(q_pdu)) - - def create_handler(q_pdu): - r_pdu = make_reply(q_pdu) - q_pdu.sql_store(db, cur) - setattr(r_pdu, q_pdu.sql_template.index, getattr(q_pdu, q_pdu.sql_template.index)) - r_msg.append(r_pdu) - - def get_handler(q_pdu): - r_pdu = q_pdu.sql_fetch(db, cur, getattr(q_pdu, q_pdu.sql_template.index)) - if r_pdu is not None: - make_reply(q_pdu, r_pdu) - r_msg.append(r_pdu) - else: - r_msg.append(make_error_report(q_pdu)) - - def set_handler(q_pdu): - data = q_pdu.sql_fetch(db, cur, getattr(q_pdu, q_pdu.sql_template.index)) - if data is not None: - for a in data.sql_template.columns[1:]: - v = getattr(q_pdu, a) - if v is not None: - setattr(data, a, v) - data.sql_dirty = True - data.sql_store(db, cur) - r_pdu = make_reply(q_pdu) - r_msg.append(r_pdu) - else: - r_msg.append(make_error_report(q_pdu)) - - def list_handler(q_pdu): - for r_pdu in q_pdu.sql_fetch_all(db, cur): - make_reply(q_pdu, r_pdu) - r_msg.append(r_pdu) - try: q_elt = decode(query, cms_ta_irbe) lr_rng.assertValid(q_elt) @@ -76,12 +25,7 @@ def left_right_handler(query, path): q_msg = saxer.result r_msg = rpki.left_right.msg() for q_pdu in q_msg: - assert isinstance(q_pdu, rpki.left_right.data_elt) and q_pdu.type == "query" - { "create" : create_handler, - "set" : set_handler, - "get" : get_handler, - "list" : list_handler, - "destroy" : destroy_handler }[q_pdu.action](q_pdu) + q_pdu.serve_dispatch(db, cur, r_msg) r_elt = r_msg.toXML() try: lr_rng.assertValid(r_elt) @@ -89,7 +33,6 @@ def left_right_handler(query, path): print lxml.etree.tostring(r_elt, pretty_print=True, encoding="us-ascii", xml_declaration=True) raise return 200, encode(r_elt, cms_key, cms_certs) - except Exception, data: if show_traceback: traceback.print_exc() |