xenserver: Remove support for XenServer versions older than 5.6 FP1.
[sliver-openvswitch.git] / xenserver / usr_share_openvswitch_scripts_ovs-external-ids
index 72ecb40..77283fe 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# Copyright (c) 2009, 2010 Nicira Networks
+# Copyright (c) 2009, 2010, 2011 Nicira Networks
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # A daemon to monitor the external_ids columns of the Bridge and
 # Interface OVSDB tables.  Its primary responsibility is to set the
 # "bridge-id" and "iface-id" keys in the Bridge and Interface tables,
-# respectively.  It also looks for the use of "network-uuids" in the
-# Bridge table and duplicates its value to the preferred "xs-network-uuids".
+# respectively.
 
 import getopt
+import logging, logging.handlers
 import os
 import signal
 import subprocess
 import sys
-import syslog
 import time
 
 import XenAPI
@@ -36,6 +35,14 @@ import ovs.util
 import ovs.daemon
 import ovs.db.idl
 
+s_log     = logging.getLogger("ovs-external-ids")
+l_handler = logging.handlers.RotatingFileHandler(
+        "/var/log/openvswitch/ovs-external-ids.log")
+l_formatter = logging.Formatter('%(filename)s: %(levelname)s: %(message)s')
+l_handler.setFormatter(l_formatter)
+s_log.addHandler(l_handler)
+s_log.setLevel(logging.INFO)
+
 vsctl="/usr/bin/ovs-vsctl"
 session = None
 force_run = False
@@ -55,64 +62,86 @@ def init_session():
         session.xenapi.login_with_password("", "")
     except:
         session = None
-        syslog.syslog(syslog.LOG_WARNING,
-                "ovs-external-ids: Couldn't login to XAPI")
+        s_log.warning("Couldn't login to XAPI")
         return False
 
     return True
 
-# By default, the "bridge-id" external id in the Bridge table is the
-# same as "xs-network-uuids".  This may be overridden by defining a
-# "nicira-bridge-id" key in the "other_config" field of the network
-# record of XAPI.
-def get_bridge_id(br_name, default=None):
+def get_network_by_bridge(br_name):
     if not init_session():
-        return default
+        s_log.warning("Failed to get bridge id %s because"
+                " XAPI session could not be initialized" % br_name)
+        return None
 
     for n in session.xenapi.network.get_all():
         rec = session.xenapi.network.get_record(n)
-        if rec['bridge'] != br_name:
-            continue
+        if rec['bridge'] == br_name:
+            return rec
+
+    return None
+
+# By default, the "bridge-id" external id in the Bridge table is the
+# same as "xs-network-uuids".  This may be overridden by defining a
+# "nicira-bridge-id" key in the "other_config" field of the network
+# record of XAPI.  If nicira-bridge-id is undefined returns default.
+# On error returns None.
+def get_bridge_id(br_name, default=None):
+    rec = get_network_by_bridge(br_name)
+    if rec:
         return rec['other_config'].get('nicira-bridge-id', default)
+    return None
 
 # By default, the "iface-id" external id in the Interface table is the
 # same as "xs-vif-uuid".  This may be overridden by defining a
 # "nicira-iface-id" key in the "other_config" field of the VIF
 # record of XAPI.
-def get_iface_id(if_name, default=None):
+def get_iface_id(if_name, xs_vif_uuid):
     if not if_name.startswith("vif"):
-        return default
-
-    domain,device = if_name.strip("vif").split(".")
+        # Treat whatever was passed into 'xs_vif_uuid' as a default
+        # value for non-VIFs.
+        return xs_vif_uuid
 
     if not init_session():
-        return default
-
-    for n in session.xenapi.VM.get_all():
-        if session.xenapi.VM.get_domid(n) == domain:
-            vifs = session.xenapi.VM.get_VIFs(n)
-            for vif in vifs:
-                rec = session.xenapi.VIF.get_record(vif)
-                if rec['device'] == device:
-                    return rec['other_config'].get('nicira-iface-id', default)
-    return None
+        s_log.warning("Failed to get interface id %s because"
+                " XAPI session could not be initialized" % if_name)
+        return xs_vif_uuid
 
+    try:
+        vif = session.xenapi.VIF.get_by_uuid(xs_vif_uuid)
+        rec = session.xenapi.VIF.get_record(vif)
+        return rec['other_config'].get('nicira-iface-id', xs_vif_uuid)
+    except XenAPI.Failure:
+        s_log.warning("Could not find XAPI entry for VIF %s" % if_name)
+        return xs_vif_uuid
+
+def call_vsctl(args):
+    cmd = [vsctl, "--timeout=30", "-vANY:console:emer"] + args
+    exitcode = subprocess.call(cmd)
+    if exitcode != 0:
+        s_log.warning("Couldn't call ovs-vsctl")
 
 def set_external_id(table, record, key, value):
     col = 'external-ids:"' + key + '"="' + value + '"'
-    cmd = [vsctl, "--timeout=30", "-vANY:console:emer", "set", table, record, col]
-    exitcode = subprocess.call(cmd)
-    if exitcode != 0:
-        syslog.syslog(syslog.LOG_WARNING,
-                "ovs-external-ids: Couldn't call ovs-vsctl")
+    call_vsctl(["set", table, record, col])
 
-# XAPI on XenServer 5.6 uses the external-id "network-uuids" for internal
-# networks, but we now prefer "xs-network-uuids".  Look for its use and
-# write our preferred external-id.
-def update_network_uuids(name, ids):
-    if ids["network-uuids"] and not ids["xs-network-uuids"]:
-        set_external_id("Bridge", name, "xs-network-uuids",
-                ids["network-uuids"])
+def update_fail_mode(name):
+    rec = get_network_by_bridge(name)
+
+    if not rec:
+        return
+
+    fail_mode = rec['other_config'].get('vswitch-controller-fail-mode')
+
+    if not fail_mode:
+        pools = session.xenapi.pool.get_all()
+        if len(pools) == 1:
+            prec = session.xenapi.pool.get_record(pools[0])
+            fail_mode = prec['other_config'].get('vswitch-controller-fail-mode')
+
+    if fail_mode not in ['standalone', 'secure']:
+        fail_mode = 'standalone'
+
+    call_vsctl(["set", "bridge", name, "fail_mode=" + fail_mode])
 
 def update_bridge_id(name, ids):
     id = get_bridge_id(name, ids.get("xs-network-uuids"))
@@ -224,6 +253,7 @@ def main(argv):
             continue
 
         if force_run:
+            s_log.info("Forced to re-run as the result of a SIGHUP")
             bridges    = {}
             interfaces = {}
             force_run  = False
@@ -232,9 +262,7 @@ def main(argv):
         for rec in idl.data["Bridge"].itervalues():
             name = rec.name.as_scalar()
             xs_network_uuids = rec.external_ids.get("xs-network-uuids")
-            network_uuids = rec.external_ids.get("network-uuids")
-            new_bridges[name] = {"xs-network-uuids": xs_network_uuids,
-                                 "network-uuids": network_uuids}
+            new_bridges[name] = {"xs-network-uuids": xs_network_uuids}
 
         new_interfaces = {}
         for rec in idl.data["Interface"].itervalues():
@@ -244,10 +272,8 @@ def main(argv):
 
         if bridges != new_bridges:
             for name,ids in new_bridges.items():
-                # Network uuids shouldn't change in the life of a bridge,
-                # so only check for "network-uuids" on creation.
                 if name not in bridges:
-                    update_network_uuids(name, ids)
+                    update_fail_mode(name)
 
                 if (name not in bridges) or (bridges[name] != ids):
                     update_bridge_id(name, ids)
@@ -263,6 +289,9 @@ def main(argv):
 if __name__ == '__main__':
     try:
         main(sys.argv)
-    except error.Error, e:
-        sys.stderr.write("%s\n" % e)
-        sys.exit(1)
+    except SystemExit:
+        # Let system.exit() calls complete normally
+        raise
+    except:
+        s_log.exception("traceback")
+        sys.exit(ovs.daemon.RESTART_EXIT_CODE)