diff options
Diffstat (limited to 'xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync')
-rwxr-xr-x | xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync deleted file mode 100755 index bff85464b..000000000 --- a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync +++ /dev/null @@ -1,404 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2009, 2010, 2011, 2012, 2013, 2020 Nicira, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# A daemon to monitor the external_ids columns of the Bridge and -# Interface OVSDB tables for changes that require interrogating XAPI. -# Its responsibilities include: -# -# - Set the "bridge-id" key in the Bridge table. -# - Set the "iface-id" key in the Interface table. -# - Set the fail-mode on internal bridges. - -import argparse -import os -import sys -import time - -import XenAPI - -import ovs.daemon -import ovs.db.idl -import ovs.dirs -import ovs.unixctl -import ovs.unixctl.server - -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): - global exiting - exiting = True - conn.reply(None) - - -def unixctl_flush_cache(conn, unused_argv, unused_aux): - global flush_cache - flush_cache = True - conn.reply(None) - - -# Set up a session to interact with XAPI. -# -# On system start-up, OVS comes up before XAPI, so we can't log into the -# session until later. Try to do this on-demand, since we won't -# actually do anything interesting until XAPI is up. -def init_session(): - global session - if session is not None: - return True - - try: - session = XenAPI.xapi_local() - session.xenapi.login_with_password("", "") - except XenAPI.Failure as e: - session = None - vlog.warn("Couldn't login to XAPI (%s)" % e) - return False - - return True - - -def get_network_by_bridge(br_name): - if not init_session(): - vlog.warn("Failed to get bridge id %s because" - " XAPI session could not be initialized" % br_name) - return None - - recs = session.xenapi.network.get_all_records_where( - 'field "bridge"="%s"' % br_name) - if len(recs) > 0: - return next(iter(recs.values())) - - 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 -# 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, xs_vif_uuid): - 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 - - if not init_session(): - vlog.warn("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: - vlog.warn("Could not find XAPI entry for VIF %s" % if_name) - return xs_vif_uuid - - -# By default, the "vm-id" external id in the Interface table is the -# same as "xs-vm-uuid". This may be overridden by defining a -# "nicira-vm-id" key in the "other_config" field of the VM -# record of XAPI. -def get_vm_id(if_name, xs_vm_uuid): - if not if_name.startswith("vif") and not if_name.startswith("tap"): - # Treat whatever was passed into 'xs_vm_uuid' as a default - # value for non-VIFs. - return xs_vm_uuid - - if not init_session(): - vlog.warn("Failed to get vm id for interface id %s because" - " XAPI session could not be initialized" % if_name) - return xs_vm_uuid - - try: - vm = session.xenapi.VM.get_by_uuid(xs_vm_uuid) - rec = session.xenapi.VM.get_record(vm) - return rec['other_config'].get('nicira-vm-id', xs_vm_uuid) - except XenAPI.Failure: - vlog.warn("Could not find XAPI entry for VIF %s" % if_name) - return xs_vm_uuid - - -def set_or_delete(d, key, value): - if value is None: - if key in d: - del d[key] - return True - else: - if d.get(key) != value: - d[key] = value - return True - return False - - -def set_external_id(row, key, value): - row.verify("external_ids") - external_ids = row.external_ids - if set_or_delete(external_ids, key, value): - row.external_ids = external_ids - - -# XenServer does not call interface-reconfigure on internal networks, -# which is where the fail-mode would normally be set. -def update_fail_mode(row): - rec = get_network_by_bridge(row.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' - - row.verify("fail_mode") - if row.fail_mode != fail_mode: - row.fail_mode = fail_mode - - -def update_in_band_mgmt(row): - rec = get_network_by_bridge(row.name) - if not rec: - return - - dib = rec['other_config'].get('vswitch-disable-in-band') - - row.verify("other_config") - other_config = row.other_config - if dib and dib not in ['true', 'false']: - vlog.warn('"%s" isn\'t a valid setting for ' - "other_config:disable-in-band on %s" % (dib, row.name)) - elif set_or_delete(other_config, 'disable-in-band', dib): - row.other_config = other_config - - -def main(): - global flush_cache, xapi_down - - parser = argparse.ArgumentParser() - parser.add_argument("database", metavar="DATABASE", - help="A socket on which ovsdb-server is listening.") - parser.add_argument("--root-prefix", metavar="DIR", default='', - help="Use DIR as alternate root directory" - " (for testing).") - - ovs.vlog.add_args(parser) - ovs.daemon.add_args(parser) - args = parser.parse_args() - ovs.vlog.handle_args(args) - ovs.daemon.handle_args(args) - - remote = args.database - schema_helper = ovs.db.idl.SchemaHelper() - schema_helper.register_columns("Bridge", ["name", "external_ids", - "other_config", "fail_mode"]) - schema_helper.register_columns("Interface", ["name", "external_ids"]) - idl = ovs.db.idl.Idl(remote, schema_helper) - - ovs.daemon.daemonize() - - 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.server.UnixctlServer.create(None) - if error: - ovs.util.ovs_fatal(error, "could not create unixctl server", vlog) - - # This daemon is usually started before XAPI, but to complete our - # tasks, we need it. Wait here until it's up. - cookie_file = args.root_prefix + "/var/run/xapi_init_complete.cookie" - while not os.path.exists(cookie_file): - time.sleep(1) - - bridges = {} # Map from bridge name to nicira-bridge-id - iface_ids = {} # Map from xs-vif-uuid to iface-id - vm_ids = {} # Map from xs-vm-uuid to vm-id - seqno = idl.change_seqno # Sequence number when we last processed the db - while True: - unixctl_server.run() - if exiting: - break - - idl.run() - 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 = {} - iface_ids = {} - vm_ids = {} - flush_cache = False - seqno = idl.change_seqno - - txn = ovs.db.idl.Transaction(idl) - - new_bridges = {} - for row in idl.tables["Bridge"].rows.values(): - bridge_id = bridges.get(row.name) - if bridge_id is None: - # Configure the new bridge. - update_fail_mode(row) - update_in_band_mgmt(row) - - # 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: - new_bridges[row.name] = bridge_id - bridges = new_bridges - - iface_by_name = {} - for row in idl.tables["Interface"].rows.values(): - iface_by_name[row.name] = row - - new_iface_ids = {} - new_vm_ids = {} - for row in idl.tables["Interface"].rows.values(): - # Match up paired vif and tap devices. - if row.name.startswith("vif"): - vif = row - tap = iface_by_name.get("tap%s" % row.name[3:]) - elif row.name.startswith("tap"): - tap = row - vif = iface_by_name.get("vif%s" % row.name[3:]) - else: - tap = vif = None - - # Several tap external-ids need to be copied from the vif. - if row == tap and vif: - keys = ["attached-mac", - "xs-network-uuid", - "xs-vif-uuid", - "xs-vm-uuid"] - for k in keys: - set_external_id(row, k, vif.external_ids.get(k)) - - # Map from xs-vif-uuid to iface-id. - # - # (A tap's xs-vif-uuid comes from its vif. That falls out - # naturally from the copy loop above.) - xvu = row.external_ids.get("xs-vif-uuid") - if xvu: - iface_id = (new_iface_ids.get(xvu) - or iface_ids.get(xvu) - or get_iface_id(row.name, xvu)) - new_iface_ids[xvu] = iface_id - else: - # No xs-vif-uuid therefore no iface-id. - iface_id = None - set_external_id(row, "iface-id", iface_id) - - # Map from xs-vm-uuid to vm-id. - xvmu = row.external_ids.get("xs-vm-uuid") - if xvmu: - vm_id = (new_vm_ids.get(xvmu) - or vm_ids.get(xvmu) - or get_vm_id(row.name, xvmu)) - new_vm_ids[xvmu] = vm_id - else: - vm_id = None - set_external_id(row, "vm-id", vm_id) - - # When there's a vif and a tap, the tap is active (used for - # traffic). When there's just a vif, the vif is active. - # - # A tap on its own shouldn't happen, and we don't know - # anything about other kinds of devices, so we don't use - # an iface-status for those devices at all. - if vif and tap: - set_external_id(tap, "iface-status", "active") - set_external_id(vif, "iface-status", "inactive") - elif vif: - set_external_id(vif, "iface-status", "active") - else: - set_external_id(row, "iface-status", None) - iface_ids = new_iface_ids - vm_ids = new_vm_ids - - txn.add_comment("ovs-xapi-sync: Updating records from XAPI") - txn.commit_block() - - unixctl_server.close() - idl.close() - - -if __name__ == '__main__': - try: - main() - except SystemExit: - # Let system.exit() calls complete normally - raise - except: - vlog.exception("traceback") - sys.exit(ovs.daemon.RESTART_EXIT_CODE) |