mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			264 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python
 | |
| # Version @VERSION@
 | |
| #
 | |
| # A plugin for executing script needed by vmops cloud 
 | |
| 
 | |
| import os, sys, time
 | |
| import XenAPIPlugin
 | |
| sys.path.append("/opt/xensource/sm/")
 | |
| import util
 | |
| from util import CommandException
 | |
| import hostvmstats
 | |
| import socket
 | |
| import stat
 | |
| import base64
 | |
| import tempfile
 | |
| from os.path import exists as _exists
 | |
| from time import localtime as _localtime, asctime as _asctime
 | |
| 
 | |
| vSwitchDBPidFile = "/var/run/openvswitch/ovsdb-server.pid"
 | |
| vSwitchDBDaemonName = "ovsdb-server"
 | |
| vSwitchPidFile = "/var/run/openvswitch/ovs-vswitchd.pid"
 | |
| vsctlPath = "/usr/bin/ovs-vsctl"
 | |
| ofctlPath = "/usr/bin/ovs-ofctl"
 | |
| vSwitchDaemonName = "ovs-vswitchd"
 | |
| 
 | |
| logFile = "/var/log/ovstunnel.log"
 | |
| fLog = None
 | |
| 
 | |
| def echo(fn):
 | |
| 	def wrapped(*v, **k):
 | |
| 		name = fn.__name__
 | |
| 		util.SMlog("#### VMOPS enter  %s ####" % name )
 | |
| 		res = fn(*v, **k)
 | |
| 		util.SMlog("#### VMOPS exit  %s ####" % name )
 | |
| 		return res
 | |
| 	return wrapped
 | |
| 
 | |
| def open_log ():
 | |
| 	global fLog
 | |
| 
 | |
| 	try:
 | |
| 		if fLog == None:
 | |
| 			fLog = open (logFile, "a")
 | |
| 	except IOError, e:
 | |
| 		#print e
 | |
| 		pass
 | |
| 
 | |
| def pr (str):
 | |
| 	global fLog
 | |
| 
 | |
| 	if fLog != None:
 | |
| 		str = "[%s]:" % _asctime (_localtime()) + str + "\n"
 | |
| 		fLog.write (str)
 | |
| 
 | |
| def close_log ():
 | |
| 	global fLog
 | |
| 
 | |
| 	if fLog != None:
 | |
| 		fLog.close ()
 | |
| 
 | |
| def is_process_run (pidFile, name):
 | |
| 	try:
 | |
| 		fpid = open (pidFile, "r")
 | |
| 		pid = fpid.readline ()
 | |
| 		fpid.close ()
 | |
| 	except IOError, e:
 | |
| 		return -1
 | |
| 
 | |
| 	pid = pid[:-1]
 | |
| 	ps = os.popen ("ps -ae")
 | |
| 	for l in ps:
 | |
| 		if pid in l and name in l:
 | |
| 			ps.close ()
 | |
| 			return 0
 | |
| 
 | |
| 	ps.close ()
 | |
| 	return -2
 | |
| 
 | |
| def is_tool_exist (name):
 | |
| 	if _exists (name):
 | |
| 		return 0
 | |
| 	return -1
 | |
| 
 | |
| 
 | |
| def check_switch ():
 | |
| 	global result
 | |
| 
 | |
| 	ret = is_process_run (vSwitchDBPidFile, vSwitchDBDaemonName);
 | |
| 	if ret < 0:
 | |
| 		if ret == -1: return "NO_DB_PID_FILE"
 | |
| 		if ret == -2: return "DB_NOT_RUN"
 | |
| 
 | |
| 	ret = is_process_run (vSwitchPidFile, vSwitchDaemonName)
 | |
| 	if ret < 0:
 | |
| 		if ret == -1: return "NO_SWITCH_PID_FILE"
 | |
| 		if ret == -2: return "SWITCH_NOT_RUN"
 | |
| 
 | |
| 	if is_tool_exist (vsctlPath) < 0:
 | |
| 		return "NO_VSCTL"
 | |
| 
 | |
| 	if is_tool_exist (ofctlPath) < 0:
 | |
| 		return "NO_OFCTL"
 | |
| 
 | |
| 	return "SUCCESS"
 | |
| 
 | |
| def do_cmd (cmds, lines=False):
 | |
| 	cmd = ""
 | |
| 	for i in cmds:
 | |
| 		cmd += " "
 | |
| 		cmd += i
 | |
| 
 | |
| 	pr("do command '%s'" % cmd)
 | |
| 	f = os.popen (cmd)
 | |
| 	if lines == True:
 | |
| 		res = f.readlines ()
 | |
| 	else:
 | |
| 		res = f.readline ()
 | |
| 		res = res[:-1]
 | |
| 	f.close ()
 | |
| 
 | |
| 	if lines == False:
 | |
| 		pr("command output '%s'" % res)
 | |
| 	return res
 | |
| 
 | |
| ######################## GRE creation utils ##########################
 | |
| # UUID's format is 8-4-4-4-12
 | |
| def is_uuid (uuid):
 | |
| 	list = uuid.split ("-")
 | |
| 
 | |
| 	if len (list) != 5:
 | |
| 		return -1
 | |
| 
 | |
| 	if len (list[0]) != 8 or len (list[1]) != 4 \
 | |
| 	   or len (list[2]) != 4 or len (list[3]) != 4 \
 | |
| 	   or len (list[4]) != 12:
 | |
| 		   return -1
 | |
| 
 | |
| 	return 0
 | |
| 
 | |
| def set_flood_flow(bridge, inport):
 | |
| 	flow = "in_port=%s idle_timeout=0 hard_timeout=0 priority=10000 actions=flood" % inport
 | |
| 	add_flow(bridge, flow)
 | |
| 
 | |
| @echo
 | |
| def create_tunnel (session, args):
 | |
| 	bridge = args.pop("bridge")
 | |
| 	remoteIP = args.pop("remote_ip")
 | |
| 	greKey = args.pop("key")
 | |
| 	srcHost = args.pop("from")
 | |
| 	dstHost = args.pop("to")
 | |
| 
 | |
| 	res = check_switch()
 | |
| 	if res != "SUCCESS":
 | |
| 		return res
 | |
| 
 | |
| 	name = "%s-%s-%s-%s" % (bridge, srcHost, dstHost, greKey)
 | |
| 
 | |
| 	wait = [vsctlPath, "--timeout=30 wait-until bridge %s -- get bridge %s name" % \
 | |
| 			(bridge, bridge)]
 | |
| 	res = do_cmd(wait)
 | |
| 	if bridge not in res:
 | |
| 		pr("WARNIING:Can't find bridge %s for creating tunnel!" % bridge)
 | |
| 		result = "COMMAND_FAILED_NO_BRIDGE"
 | |
| 		return result
 | |
| 
 | |
| 	createInterface = [vsctlPath, "create interface", "name=%s" % name, \
 | |
| 			'type=gre options:remote_ip=%s options:key=%s' % (remoteIP, greKey)]
 | |
| 	ifaceUUID = do_cmd (createInterface)
 | |
| 	if is_uuid (ifaceUUID) < 0:
 | |
| 		pr("create interface failed, %s is not UUID" % ifaceUUID)
 | |
| 		result = "COMMAND_FAILED_CREATE_INTERFACE_FAILED"
 | |
| 		return result
 | |
| 
 | |
| 	createPort = [vsctlPath, "create port", "name=%s" % name, \
 | |
| 			"interfaces=[%s]" % ifaceUUID]
 | |
| 	portUUID = do_cmd (createPort)
 | |
| 	if is_uuid (portUUID) < 0:
 | |
| 		pr("create port failed, %s is not UUID" % portUUID)
 | |
| 		result = "COMMAND_FAILED_CREATE_PORT_FAILED"
 | |
| 		return result
 | |
| 
 | |
| 	addBridge = [vsctlPath, "add bridge %s" % bridge, "ports %s" % portUUID]
 | |
| 	do_cmd (addBridge)
 | |
| 
 | |
| 	wait = [vsctlPath, "--timeout=30 wait-until port %s -- get port %s name" % \
 | |
| 			(name, name)]
 | |
| 	res = do_cmd(wait)
 | |
| 	if name in res:
 | |
| 		port = get_field_of_interface(name, "ofport");
 | |
| 		if port == "[]":
 | |
| 			return "COMMAND_FAILED_PORT_IS_[]"
 | |
| 
 | |
| 		noFlood = [ofctlPath, "mod-port %s %s noflood" % (bridge, \
 | |
| 			port)]
 | |
| 		do_cmd(noFlood)
 | |
| 
 | |
| 		set_flood_flow(bridge, port)
 | |
| 		pr("create tunnel successful(bridge=%s, remote_ip=%s, key=%s, from=%s, to=%s" % \
 | |
| 				(bridge, remoteIP, greKey, srcHost, dstHost))
 | |
| 		result = "SUCCESS:%s" % name
 | |
| 	else:
 | |
| 		pr("create gre tunnel failed")
 | |
| 		result = "COMMAND_FAILED_CREATE_TUNNEL_FAILED"
 | |
| 	
 | |
| 	return result
 | |
| ######################## End GRE creation utils ##########################
 | |
| 
 | |
| def del_all_flows(bridge):
 | |
| 	delFlow = [ofctlPath, "del-flows %s" % bridge]
 | |
| 	do_cmd(delFlow)
 | |
| 
 | |
| 	normalFlow = "priority=0 idle_timeout=0 hard_timeout=0 actions=normal"
 | |
| 	add_flow(bridge, normalFlow)
 | |
| 
 | |
| def del_flows(bridge, ofport):
 | |
| 	delFlow = [ofctlPath, 'del-flows %s "in_port=%s"' % (bridge, ofport)]
 | |
| 	do_cmd(delFlow)
 | |
| 
 | |
| def del_port(bridge, port):
 | |
| 	delPort = [vsctlPath, "del-port %s %s" % (bridge, port)]
 | |
| 	do_cmd(delPort)
 | |
| 
 | |
| @echo
 | |
| def destroy_tunnel(session, args):
 | |
| 	bridge = args.pop("bridge")
 | |
| 	inPort = args.pop("in_port")
 | |
| 
 | |
| 	# delete all gre ports on bridge
 | |
| 	if inPort == "[]":
 | |
| 		listPorts = [vsctlPath, "list-ports %s" % bridge]
 | |
| 		res = do_cmd(listPorts, True)
 | |
| 		for p in res:
 | |
| 			if bridge in p:
 | |
| 				del_port(bridge, p)
 | |
| 		del_all_flows(bridge)
 | |
| 	else:
 | |
| 		ofport = get_field_of_interface(inPort, "ofport")
 | |
| 		del_flows(bridge, ofport)
 | |
| 		del_port(bridge, inPort)
 | |
| 
 | |
| 	return "SUCCESS"
 | |
| 
 | |
| def get_field_of_interface(nameOruuid, field):
 | |
| 	listIface = [vsctlPath, "list interface", nameOruuid]
 | |
| 	res = do_cmd(listIface, True)
 | |
| 
 | |
| 	for i in res:
 | |
| 		if field in i:
 | |
| 			(x, r) = i.split(":")
 | |
| 			return r.lstrip().rstrip()
 | |
| 	return None
 | |
| 
 | |
| 
 | |
| def add_flow(bridge, flow):
 | |
| 	param = bridge + ' "%s"' % flow
 | |
| 	addflow = ["ovs-ofctl add-flow", param]
 | |
| 	do_cmd (addflow)
 | |
| 
 | |
| if __name__ == "__main__":
 | |
| 	open_log()
 | |
| 	XenAPIPlugin.dispatch({"create_tunnel":create_tunnel, "destroy_tunnel":destroy_tunnel})
 | |
| 	close_log()
 | |
| 
 |