idl: Convert python daemons to utilize SchemaHelper.
[sliver-openvswitch.git] / debian / ovs-monitor-ipsec
old mode 100644 (file)
new mode 100755 (executable)
index 444b234..87a1491
@@ -37,11 +37,19 @@ from ovs.db import types
 import ovs.util
 import ovs.daemon
 import ovs.db.idl
+import ovs.unixctl
 import ovs.vlog
 
 vlog = ovs.vlog.Vlog("ovs-monitor-ipsec")
 root_prefix = ''                # Prefix for absolute file names, for testing.
 setkey = "/usr/sbin/setkey"
+exiting = False
+
+
+def unixctl_exit(conn, unused_argv, unused_aux):
+    global exiting
+    exiting = True
+    conn.reply(None)
 
 
 # Class to configure the racoon daemon, which handles IKE negotiation
@@ -216,13 +224,10 @@ path certificate "%s";
 
         # The peer's certificate comes to us in PEM format as a string.
         # Write that string to a file for Racoon to use.
-        peer_cert_file = "%s/ovs-%s.pem" % (self.cert_dir, host)
-        f = open(root_prefix + peer_cert_file, "w")
+        f = open(root_prefix + vals["peer_cert_file"], "w")
         f.write(vals["peer_cert"])
         f.close()
 
-        vals["peer_cert_file"] = peer_cert_file
-
         self.cert_hosts[host] = vals
         self.commit()
 
@@ -347,49 +352,6 @@ class IPsec:
             self.entries.remove(remote_ip)
 
 
-def keep_table_columns(schema, table_name, column_types):
-    table = schema.tables.get(table_name)
-    if not table:
-        raise error.Error("schema has no %s table" % table_name)
-
-    new_columns = {}
-    for column_name, column_type in column_types.iteritems():
-        column = table.columns.get(column_name)
-        if not column:
-            raise error.Error("%s table schema lacks %s column"
-                              % (table_name, column_name))
-        if column.type != column_type:
-            raise error.Error("%s column in %s table has type \"%s\", "
-                              "expected type \"%s\""
-                              % (column_name, table_name,
-                                 column.type.toEnglish(),
-                                 column_type.toEnglish()))
-        new_columns[column_name] = column
-    table.columns = new_columns
-    return table
-
-
-def prune_schema(schema):
-    string_type = types.Type(types.BaseType(types.StringType))
-    optional_ssl_type = types.Type(types.BaseType(types.UuidType,
-        ref_table_name='SSL'), None, 0, 1)
-    string_map_type = types.Type(types.BaseType(types.StringType),
-                                 types.BaseType(types.StringType),
-                                 0, sys.maxint)
-
-    new_tables = {}
-    new_tables["Interface"] = keep_table_columns(
-        schema, "Interface", {"name": string_type,
-                              "type": string_type,
-                              "options": string_map_type})
-    new_tables["Open_vSwitch"] = keep_table_columns(
-        schema, "Open_vSwitch", {"ssl": optional_ssl_type})
-    new_tables["SSL"] = keep_table_columns(
-        schema, "SSL", {"certificate": string_type,
-                        "private_key": string_type})
-    schema.tables = new_tables
-
-
 def update_ipsec(ipsec, interfaces, new_interfaces):
     for name, vals in interfaces.iteritems():
         if name not in new_interfaces:
@@ -399,11 +361,13 @@ def update_ipsec(ipsec, interfaces, new_interfaces):
         orig_vals = interfaces.get(name)
         if orig_vals:
             # Configuration for this host already exists.  Check if it's
-            # changed.
-            if vals == orig_vals:
-                continue
-            else:
+            # changed.  We use set difference, since we want to ignore
+            # any local additions to "orig_vals" that we've made
+            # (e.g. the "peer_cert_file" key).
+            if set(vals.items()) - set(orig_vals.items()):
                 ipsec.del_entry(vals["local_ip"], vals["remote_ip"])
+            else:
+                continue
 
         try:
             ipsec.add_entry(vals["local_ip"], vals["remote_ip"], vals)
@@ -413,9 +377,10 @@ def update_ipsec(ipsec, interfaces, new_interfaces):
 
 def get_ssl_cert(data):
     for ovs_rec in data["Open_vSwitch"].rows.itervalues():
-        ssl = ovs_rec.ssl
-        if ssl and ssl.certificate and ssl.private_key:
-            return (ssl.certificate, ssl.private_key)
+        if ovs_rec.ssl:
+            ssl = ovs_rec.ssl[0]
+            if ssl.certificate and ssl.private_key:
+                return (ssl.certificate, ssl.private_key)
 
     return None
 
@@ -436,22 +401,34 @@ def main():
     ovs.daemon.handle_args(args)
 
     global root_prefix
-    root_prefix = args.root_prefix
+    if args.root_prefix:
+        root_prefix = args.root_prefix
 
     remote = args.database
-    schema_file = "%s/vswitch.ovsschema" % ovs.dirs.PKGDATADIR
-    schema = ovs.db.schema.DbSchema.from_json(ovs.json.from_file(schema_file))
-    prune_schema(schema)
-    idl = ovs.db.idl.Idl(remote, schema)
+    schema_helper = ovs.db.idl.SchemaHelper()
+    schema_helper.register_columns("Interface", ["name", "type", "options"])
+    schema_helper.register_columns("Open_vSwitch", ["ssl"])
+    schema_helper.register_columns("SSL", ["certificate", "private_key"])
+    idl = ovs.db.idl.Idl(remote, schema_helper)
 
     ovs.daemon.daemonize()
 
+    ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, None)
+    error, unixctl_server = ovs.unixctl.UnixctlServer.create(None)
+    if error:
+        ovs.util.ovs_fatal(error, "could not create unixctl server", vlog)
+
     ipsec = IPsec()
 
     interfaces = {}
     while True:
+        unixctl_server.run()
+        if exiting:
+            break
+
         if not idl.run():
             poller = ovs.poller.Poller()
+            unixctl_server.wait(poller)
             idl.wait(poller)
             poller.block()
             continue
@@ -463,6 +440,7 @@ def main():
             if rec.type == "ipsec_gre":
                 name = rec.name
                 options = rec.options
+                peer_cert_name = "ovs-%s.pem" % (options.get("remote_ip"))
                 entry = {
                     "remote_ip": options.get("remote_ip"),
                     "local_ip": options.get("local_ip", "0.0.0.0/0"),
@@ -470,6 +448,7 @@ def main():
                     "private_key": options.get("private_key"),
                     "use_ssl_cert": options.get("use_ssl_cert"),
                     "peer_cert": options.get("peer_cert"),
+                    "peer_cert_file": Racoon.cert_dir + "/" + peer_cert_name,
                     "psk": options.get("psk")}
 
                 if entry["peer_cert"] and entry["psk"]:
@@ -496,6 +475,9 @@ def main():
             update_ipsec(ipsec, interfaces, new_interfaces)
             interfaces = new_interfaces
 
+    unixctl_server.close()
+    idl.close()
+
 
 if __name__ == '__main__':
     try: