ovs-xapi-sync: Make pychecker-able.
[sliver-openvswitch.git] / xenserver / usr_share_openvswitch_scripts_ovs-xapi-sync
index 4d030fd..57dc2e3 100755 (executable)
@@ -38,14 +38,7 @@ import ovs.util
 import ovs.daemon
 import ovs.db.idl
 
-s_log     = logging.getLogger("ovs-xapi-sync")
-l_handler = logging.handlers.RotatingFileHandler(
-        "/var/log/openvswitch/ovs-xapi-sync.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)
-
+s_log = logging.getLogger("ovs-xapi-sync")
 vsctl="/usr/bin/ovs-vsctl"
 session = None
 force_run = False
@@ -99,7 +92,7 @@ def get_bridge_id(br_name, default=None):
 # "nicira-iface-id" key in the "other_config" field of the VIF
 # record of XAPI.
 def get_iface_id(if_name, xs_vif_uuid):
-    if not if_name.startswith("vif"):
+    if not if_name.startswith("vif") and not if_name.startswith("tap"):
         # Treat whatever was passed into 'xs_vif_uuid' as a default
         # value for non-VIFs.
         return xs_vif_uuid
@@ -118,14 +111,18 @@ def get_iface_id(if_name, xs_vif_uuid):
         return xs_vif_uuid
 
 def call_vsctl(args):
-    cmd = [vsctl, "--timeout=30", "-vANY:console:emer"] + args
+    cmd = [vsctl, "--timeout=30", "-vANY:console:off"] + 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 + '"'
-    call_vsctl(["set", table, record, col])
+    if value:
+        col = 'external-ids:"%s"="%s"' % (key, value)
+        call_vsctl(["set", table, record, col])
+    else:
+        call_vsctl(["remove", table, record, "external-ids", key])
+
 
 # XenServer does not call interface-reconfigure on internal networks,
 # which is where the fail-mode would normally be set.
@@ -148,6 +145,24 @@ def update_fail_mode(name):
 
     call_vsctl(["set", "bridge", name, "fail_mode=" + fail_mode])
 
+def update_in_band_mgmt(name):
+    rec = get_network_by_bridge(name)
+
+    if not rec:
+        return
+
+    dib = rec['other_config'].get('vswitch-disable-in-band')
+    if not dib:
+        call_vsctl(['remove', 'bridge', name, 'other_config',
+                    'disable-in-band'])
+    elif dib in ['true', 'false']:
+        call_vsctl(['set', 'bridge', name,
+                    'other_config:disable-in-band=' + dib])
+    else:
+        s_log.warning('"' + dib + '"'
+                      "isn't a valid setting for other_config:disable-in-band on " +
+                      name)
+
 def update_bridge_id(name, ids):
     id = get_bridge_id(name, ids.get("xs-network-uuids"))
 
@@ -158,11 +173,17 @@ def update_bridge_id(name, ids):
 
     if ids.get("bridge-id") != primary_id:
         set_external_id("Bridge", name, "bridge-id", primary_id)
+        ids["bridge-id"] = primary_id
 
-def update_iface_id(name, ids):
+def update_iface(name, ids):
     id = get_iface_id(name, ids.get("xs-vif-uuid"))
     if ids.get("iface-id") != id and id:
         set_external_id("Interface", name, "iface-id", id)
+        ids["iface-id"] = id
+
+    status = ids.get("iface-status")
+    if status:
+        set_external_id("Interface", name, "iface-status", status)
 
 def keep_table_columns(schema, table_name, column_types):
     table = schema.tables.get(table_name)
@@ -211,9 +232,37 @@ def handler(signum, frame):
     if (signum == signal.SIGHUP):
         force_run = True
 
+def update_tap_from_vif(idl, tap_name, vif_name):
+    ifaces = idl.data["Interface"]
+    tap = None
+    vif = None
+
+    for i in ifaces.values():
+        name = i.name.as_scalar().strip('"')
+        if name == tap_name:
+            tap = i
+        elif name == vif_name:
+            vif = i
+
+    if vif and tap:
+        vxid = vif.external_ids
+        txid = tap.external_ids
+
+        keys = ["attached-mac", "xs-network-uuid", "xs-vif-uuid", "xs-vm-uuid"]
+        for k in keys:
+            if vxid.get(k) != txid.get(k):
+                set_external_id("Interface", tap_name, k, vxid.get(k))
+
 def main(argv):
     global force_run
 
+    l_handler = logging.handlers.RotatingFileHandler(
+            "/var/log/openvswitch/ovs-xapi-sync.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)
+
     try:
         options, args = getopt.gnu_getopt(
             argv[1:], 'h', ['help'] + ovs.daemon.LONG_OPTIONS)
@@ -234,8 +283,6 @@ def main(argv):
                          "(use --help for help)\n" % ovs.util.PROGRAM_NAME)
         sys.exit(1)
 
-    ovs.daemon.die_if_already_running()
-
     remote = args[0]
     idl = ovs.db.idl.Idl(remote, "Open_vSwitch", monitor_uuid_schema_cb)
 
@@ -267,18 +314,43 @@ 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")
-            new_bridges[name] = {"xs-network-uuids": xs_network_uuids}
+            bridge_id = rec.external_ids.get("bridge-id")
+            new_bridges[name] = {"xs-network-uuids": xs_network_uuids,
+                                 "bridge-id": bridge_id}
 
         new_interfaces = {}
         for rec in idl.data["Interface"].itervalues():
             name = rec.name.as_scalar()
             xs_vif_uuid = rec.external_ids.get("xs-vif-uuid")
-            new_interfaces[name] = {"xs-vif-uuid": xs_vif_uuid}
+            iface_id = rec.external_ids.get("iface-id")
+            new_interfaces[name] = {"xs-vif-uuid": xs_vif_uuid,
+                                    "iface-id": iface_id}
+
+            if name.startswith("vif"):
+                new_interfaces[name]["iface-status"] = "active"
+
+        #Tap devices take their xs-vif-uuid from their corresponding vif and
+        #cause that vif to be labled inactive.
+        for name in new_interfaces:
+            if not name.startswith("tap"):
+                continue
+
+            vif = name.replace("tap", "vif", 1)
+
+            if vif in new_interfaces:
+                xs_vif_uuid = new_interfaces[vif]["xs-vif-uuid"]
+                new_interfaces[name]["xs-vif-uuid"] = xs_vif_uuid
+
+                new_interfaces[vif]["iface-status"] = "inactive"
+                new_interfaces[name]["iface-status"] = "active"
+
+                update_tap_from_vif(idl, name, vif)
 
         if bridges != new_bridges:
             for name,ids in new_bridges.items():
                 if name not in bridges:
                     update_fail_mode(name)
+                    update_in_band_mgmt(name)
 
                 if (name not in bridges) or (bridges[name] != ids):
                     update_bridge_id(name, ids)
@@ -288,7 +360,7 @@ def main(argv):
         if interfaces != new_interfaces:
             for name,ids in new_interfaces.items():
                 if (name not in interfaces) or (interfaces[name] != ids):
-                    update_iface_id(name, ids)
+                    update_iface(name, ids)
             interfaces = new_interfaces
 
 if __name__ == '__main__':