2012-04-23 22:32:16 +01:00

264 lines
6.0 KiB
Python

#!/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()