-#!/usr/bin/python
-# Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks
+#! /usr/bin/env python
+# Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
import XenAPI
import ovs.dirs
-from ovs.db import error
-from ovs.db import types
import ovs.daemon
import ovs.db.idl
import ovs.unixctl
+import ovs.unixctl.server
+import six
vlog = ovs.vlog.Vlog("ovs-xapi-sync")
session = None
flush_cache = False
exiting = False
+xapi_down = False
def unixctl_exit(conn, unused_argv, unused_aux):
try:
session = XenAPI.xapi_local()
session.xenapi.login_with_password("", "")
- except XenAPI.Failure, e:
+ except XenAPI.Failure as e:
session = None
vlog.warn("Couldn't login to XAPI (%s)" % e)
return False
" 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:
- return rec
+ recs = session.xenapi.network.get_all_records_where(
+ 'field "bridge"="%s"' % br_name)
+ if len(recs) > 0:
+ return next(six.itervalues(recs))
return None
+# There are possibilities when multiple xs-network-uuids are set for a bridge.
+# In cases like that, we should choose the bridge-id associated with the bridge
+# name.
+def get_single_bridge_id(bridge_ids, br_name, default=None):
+ global xapi_down
+
+ rec = get_network_by_bridge(br_name)
+ if rec and rec['uuid'] in bridge_ids:
+ return rec['uuid']
+
+ vlog.warn("Failed to get a single bridge id from Xapi.")
+ xapi_down = True
+ return default
+
+
# 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
def main():
- global flush_cache
+ global flush_cache, xapi_down
parser = argparse.ArgumentParser()
parser.add_argument("database", metavar="DATABASE",
ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, None)
ovs.unixctl.command_register("flush-cache", "", 0, 0, unixctl_flush_cache,
None)
- error, unixctl_server = ovs.unixctl.UnixctlServer.create(None)
+ error, unixctl_server = ovs.unixctl.server.UnixctlServer.create(None)
if error:
ovs.util.ovs_fatal(error, "could not create unixctl server", vlog)
while True:
unixctl_server.run()
if exiting:
- break;
+ break
idl.run()
- if not flush_cache and seqno == idl.change_seqno:
+ if not xapi_down and not flush_cache and seqno == idl.change_seqno:
poller = ovs.poller.Poller()
unixctl_server.wait(poller)
idl.wait(poller)
poller.block()
continue
+ if xapi_down:
+ vlog.warn("Xapi is probably down. Retry again after a second.")
+ time.sleep(1)
+ xapi_down = False
+
if flush_cache:
vlog.info("Flushing cache as the result of unixctl.")
bridges = {}
txn = ovs.db.idl.Transaction(idl)
new_bridges = {}
- for row in idl.tables["Bridge"].rows.itervalues():
- if row.name in bridges:
- nbd = bridges[row.name]
- else:
- # New bridge.
+ for row in six.itervalues(idl.tables["Bridge"].rows):
+ bridge_id = bridges.get(row.name)
+ if bridge_id is None:
+ # Configure the new bridge.
update_fail_mode(row)
update_in_band_mgmt(row)
- nbd = get_bridge_id(row.name)
- bridge_id = nbd
- if bridge_id is None:
- bridge_id = row.external_ids.get("xs-network-uuids")
+ # Get the correct bridge_id, if we can.
+ bridge_id = get_bridge_id(row.name)
+ if bridge_id is None:
+ xs_network_uuids = row.external_ids.get("xs-network-uuids")
+ if xs_network_uuids:
+ bridge_ids = xs_network_uuids.split(";")
+ if len(bridge_ids) == 1:
+ bridge_id = bridge_ids[0]
+ else:
+ bridge_id = get_single_bridge_id(bridge_ids,
+ row.name)
+ set_external_id(row, "bridge-id", bridge_id)
if bridge_id is not None:
- set_external_id(row, "bridge-id", bridge_id.split(";")[0])
-
- new_bridges[row.name] = nbd
+ new_bridges[row.name] = bridge_id
bridges = new_bridges
iface_by_name = {}
- for row in idl.tables["Interface"].rows.itervalues():
+ for row in six.itervalues(idl.tables["Interface"].rows):
iface_by_name[row.name] = row
new_iface_ids = {}
new_vm_ids = {}
- for row in idl.tables["Interface"].rows.itervalues():
+ for row in six.itervalues(idl.tables["Interface"].rows):
# Match up paired vif and tap devices.
if row.name.startswith("vif"):
vif = row