mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
263 lines
6.0 KiB
Python
Executable File
263 lines
6.0 KiB
Python
Executable File
#!/usr/bin/python
|
|
#
|
|
# 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()
|
|
|