#!/usr/bin/python
#
# Script to retrieve extended information about VIFs that are
# needed by the controller.  This is called by the "vif" script,
# which is run when virtual interfaces are added and removed.

# Copyright (C) 2009 Nicira Networks, Inc.
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is,
# without warranty of any kind.

import sys
import XenAPI
import xen.lowlevel.xs

# Query XenStore for the opaque reference of this vif
def get_vif_ref(domid, devid):
	xenstore = xen.lowlevel.xs.xs()
	t = xenstore.transaction_start()
	vif_ref = xenstore.read(t, '/xapi/%s/private/vif/%s/ref' % (domid, devid))
	xenstore.transaction_end(t)
	return vif_ref

# Query XAPI for the information we need using the vif's opaque reference
def dump_vif_info(domid, devid, vif_ref):
	session = XenAPI.xapi_local()
	session.xenapi.login_with_password("root", "")
	try: 
		vif_rec = session.xenapi.VIF.get_record(vif_ref)
		net_rec = session.xenapi.network.get_record(vif_rec["network"])
		vm_uuid = session.xenapi.VM.get_uuid(vif_rec["VM"])

		# Data to allow vNetManager to associate VIFs with xapi data
		vif_info = []
		vif_info.append(('xs-network-uuid', net_rec["uuid"]))
		vif_info.append(('xs-vif-mac', vif_rec["MAC"]))
		vif_info.append(('xs-vif-uuid', vif_rec["uuid"]))
		vif_info.append(('xs-vm-uuid', vm_uuid))
		for key, value in vif_info:
			print("-- iface-set-external-id vif%s.%s %s %s"
			      % (domid, devid, key, value))

		# vNetManager needs to know the network UUID(s) associated with
		# each datapath.  Normally interface-reconfigure adds them, but
		# interface-reconfigure never gets called for internal networks
		# (xapi does the addbr ioctl internally), so we have to do it
		# here instead for internal networks.  This is only acceptable
		# because xapi is lazy about creating internal networks: it
		# only creates one just before it adds the first vif to it.
		# There may still be a brief delay between the initial
		# ovs-vswitchd connection to vNetManager and setting this
		# configuration variable, but vNetManager can tolerate that.
		if not net_rec['PIFs']:
			bridge = net_rec['bridge']

			xs_network_uuid = net_rec['uuid']
			print("-- br-set-external-id %s %s %s"
			      % (bridge, "xs-network-uuids", xs_network_uuid))

			xs_network_name = net_rec['name_label']
			print("-- br-set-external-id %s %s %s"
			      % (bridge, "xs-network-names", xs_network_name))
	finally:
		session.xenapi.session.logout()
	
if __name__ == '__main__':
	if len(sys.argv) != 3:
		sys.stderr.write("ERROR: %s <domid> <devid>\n" % sys.argv[0])
		sys.exit(1)

	domid = sys.argv[1]
	devid = sys.argv[2]

	vif_ref = get_vif_ref(domid, devid)
	if not vif_ref:
		sys.stderr.write("ERROR: Could not find interface vif%s.%s\n" 
		                 % (domid, devid))
		sys.exit(1)

	dump_vif_info(domid, devid, vif_ref)
	sys.exit(0)
