mirror of https://github.com/apache/cloudstack.git
418 lines
14 KiB
Python
Executable File
418 lines
14 KiB
Python
Executable File
from OvmCommonModule import *
|
|
import traceback
|
|
import time
|
|
import re
|
|
|
|
logger = OvmLogger("OvmNetwork")
|
|
|
|
class Filter:
|
|
class Network:
|
|
IFNAME_LO = r'(lo)'
|
|
IFNAME_BRIDGE = r'(xenbr\d+|vlan\d+)'
|
|
IFNAME_PIF = r'(eth\d+$|bond\d+$)'
|
|
IFNAME_VLAN = r'(eth\d+.\d+$|bond\d+.\d+$)'
|
|
|
|
|
|
class Parser(object):
|
|
'''
|
|
classdocs
|
|
'''
|
|
def findall(self, pattern, samples):
|
|
"""
|
|
@param pattern: search pattern
|
|
@param result: Parser line execution result
|
|
@return : list of search
|
|
find result of Parser which has same pattern
|
|
findall Parser find all pattern in a string
|
|
"""
|
|
result = []
|
|
for line in samples:
|
|
items = re.findall(pattern, line)
|
|
for item in items:
|
|
result.append(item)
|
|
return result
|
|
|
|
def checkPattern(self, pattern, cmd_result):
|
|
"""
|
|
@param pattern: search pattern
|
|
@param cmd_result: Parser line execution result
|
|
@return : True (if pattern is occurred)
|
|
"""
|
|
for line in cmd_result:
|
|
items = re.findall(pattern, line)
|
|
if len(items) > 0:
|
|
return True
|
|
return False
|
|
|
|
def search(self, cmd_result, pattern):
|
|
return None
|
|
|
|
class OvmVlanDecoder(json.JSONDecoder):
|
|
def decode(self, jStr):
|
|
deDict = asciiLoads(jStr)
|
|
vlan = OvmVlan()
|
|
setAttrFromDict(vlan, 'vid', deDict, int)
|
|
setAttrFromDict(vlan, 'pif', deDict)
|
|
return vlan
|
|
|
|
class OvmVlanEncoder(json.JSONEncoder):
|
|
def default(self, obj):
|
|
if not isinstance(obj, OvmVlan): raise Exception("%s is not instance of OvmVlan"%type(obj))
|
|
dct = {}
|
|
safeDictSet(obj, dct, 'name')
|
|
safeDictSet(obj, dct, 'vid')
|
|
safeDictSet(obj, dct, 'pif')
|
|
return dct
|
|
|
|
def toOvmVlan(jStr):
|
|
return json.loads(jStr, cls=OvmVlanDecoder)
|
|
|
|
def fromOvmVlan(vlan):
|
|
return normalizeToGson(json.dumps(vlan, cls=OvmVlanEncoder))
|
|
|
|
class OvmBridgeDecoder(json.JSONDecoder):
|
|
def decode(self, jStr):
|
|
deDic = asciiLoads(jStr)
|
|
bridge = OvmBridge()
|
|
setAttrFromDict(bridge, 'name', deDic)
|
|
setAttrFromDict(bridge, 'attach', deDic)
|
|
return bridge
|
|
|
|
class OvmBridgeEncoder(json.JSONEncoder):
|
|
def default(self, obj):
|
|
if not isinstance(obj, OvmBridge): raise Exception("%s is not instance of OvmBridge"%type(obj))
|
|
dct = {}
|
|
safeDictSet(obj, dct, 'name')
|
|
safeDictSet(obj, dct, 'attach')
|
|
safeDictSet(obj, dct, 'interfaces')
|
|
return dct
|
|
|
|
def toOvmBridge(jStr):
|
|
return json.loads(jStr, cls=OvmBridgeDecoder)
|
|
|
|
def fromOvmBridge(bridge):
|
|
return normalizeToGson(json.dumps(bridge, cls=OvmBridgeEncoder))
|
|
|
|
class OvmInterface(OvmObject):
|
|
name = ''
|
|
|
|
class OvmVlan(OvmInterface):
|
|
vid = 0
|
|
pif = ''
|
|
|
|
class OvmBridge(OvmInterface):
|
|
attach = ''
|
|
interfaces = []
|
|
|
|
|
|
class OvmNetwork(OvmObject):
|
|
'''
|
|
Network
|
|
'''
|
|
|
|
@property
|
|
def pifs(self):
|
|
return self._getInterfaces("pif")
|
|
|
|
@property
|
|
def vlans(self):
|
|
return self._getInterfaces("vlan")
|
|
|
|
@property
|
|
def bridges(self):
|
|
return self._getInterfaces("bridge")
|
|
|
|
def __init__(self):
|
|
self.Parser = Parser()
|
|
|
|
def _createVlan(self, vlan):
|
|
"""
|
|
@param jsonString : parameter from client side
|
|
@return : succ xxxxx
|
|
ex. jsonString => {vid:100, pif:eth0}
|
|
ex. return =>
|
|
"""
|
|
|
|
#Pre-condition
|
|
#check Physical Interface Name
|
|
if vlan.pif not in self.pifs.keys():
|
|
msg = "Physical Interface(%s) does not exist" % vlan.pif
|
|
logger.debug(self._createVlan, msg)
|
|
raise Exception(msg)
|
|
|
|
#Pre-condition
|
|
#check Vlan Interface Name
|
|
ifName = "%s.%s" % (vlan.pif, vlan.vid)
|
|
if ifName in self.vlans.keys():
|
|
msg = "Vlan Interface(%s) already exist, return it" % ifName
|
|
logger.debug(self._createVlan, msg)
|
|
return self.vlans[ifName]
|
|
|
|
doCmd(['vconfig', 'add', vlan.pif, vlan.vid])
|
|
self.bringUP(ifName)
|
|
logger.debug(self._createVlan, "Create vlan %s successfully"%ifName)
|
|
return self.vlans[ifName]
|
|
|
|
def _deleteVlan(self, name):
|
|
if name not in self.vlans.keys():
|
|
raise Exception("No vlan device %s found"%name)
|
|
|
|
vlan = self.vlans[name]
|
|
self.bringDown(vlan.name)
|
|
doCmd(['vconfig', 'rem', vlan.name])
|
|
logger.debug(self._deleteVlan, "Delete vlan %s successfully"%vlan.name)
|
|
|
|
|
|
def _createBridge(self, bridge):
|
|
"""
|
|
@return : success
|
|
ex. {bridge:xapi100, attach:eth0.100}
|
|
create bridge interface, and attached it
|
|
cmd 1: brctl addbr bridge
|
|
cmd 2: brctl addif brdige attach
|
|
"""
|
|
|
|
if "xenbr" not in bridge.name and "vlan" not in bridge.name:
|
|
raise Exception("Invalid bridge name %s. Bridge name must be in partten xenbr/vlan, e.g. xenbr0"%bridge.name)
|
|
|
|
#pre-condition
|
|
#check Bridge Interface Name
|
|
if bridge.name in self.bridges.keys():
|
|
msg = "Bridge(%s) already exist, return it" % bridge.name
|
|
logger.debug(self._createBridge, msg)
|
|
return self.bridges[bridge.name]
|
|
|
|
#pre-condition
|
|
#check attach must exist
|
|
#possible to attach in PIF or VLAN
|
|
if bridge.attach not in self.vlans.keys() and bridge.attach not in self.pifs.keys():
|
|
msg = "%s is not either pif or vlan" % bridge.attach
|
|
logger.error(self._createBridge, msg)
|
|
raise Exception(msg)
|
|
|
|
doCmd(['brctl', 'addbr', bridge.name])
|
|
doCmd(['brctl', 'addif', bridge.name, bridge.attach])
|
|
self.bringUP(bridge.name)
|
|
logger.debug(self._createBridge, "Create bridge %s on %s successfully"%(bridge.name, bridge.attach))
|
|
return self.bridges[bridge.name]
|
|
|
|
def _getBridges(self):
|
|
return self.bridges.keys()
|
|
|
|
def _getVlans(self):
|
|
return self.vlans.keys()
|
|
|
|
def _deleteBridge(self, name):
|
|
if name not in self.bridges.keys():
|
|
raise Exception("Can not find bridge %s"%name)
|
|
|
|
bridge = self.bridges[name]
|
|
if bridge.attach in bridge.interfaces: bridge.interfaces.remove(bridge.attach)
|
|
if len(bridge.interfaces) != 0:
|
|
logger.debug(self._deleteBridge, "There are still some interfaces(%s) on bridge %s"%(bridge.interfaces, bridge.name))
|
|
return False
|
|
self.bringDown(bridge.name)
|
|
doCmd(['brctl', 'delbr', bridge.name])
|
|
logger.debug(self._deleteBridge, "Delete bridge %s successfully"%bridge.name)
|
|
return True
|
|
|
|
def _getInterfaces(self, type):
|
|
"""
|
|
@param type : ["pif", "bridge", "tap"]
|
|
@return : dictionary of Interface Objects
|
|
get All Interfaces based on type
|
|
"""
|
|
devices = os.listdir('/sys/class/net')
|
|
ifs = {}
|
|
if type == "pif":
|
|
devs = self.Parser.findall(Filter.Network.IFNAME_PIF, devices)
|
|
for dev in set(devs):
|
|
ifInst = OvmInterface()
|
|
ifInst.name = dev
|
|
ifs[dev] = ifInst
|
|
|
|
elif type == "vlan":
|
|
devs = self.Parser.findall(Filter.Network.IFNAME_VLAN, devices)
|
|
for dev in set(devs):
|
|
ifInst = OvmVlan()
|
|
ifInst.name = dev
|
|
(pif, vid) = dev.split('.')
|
|
ifInst.pif = pif
|
|
ifInst.vid = vid
|
|
ifs[dev] = ifInst
|
|
|
|
elif type == "bridge":
|
|
devs = self.Parser.findall(Filter.Network.IFNAME_BRIDGE, devices)
|
|
for dev in set(devs):
|
|
ifInst = OvmBridge()
|
|
ifInst.name = dev
|
|
devs = os.listdir(join('/sys/class/net', dev, 'brif'))
|
|
ifInst.interfaces = devs
|
|
attches = self.Parser.findall(Filter.Network.IFNAME_PIF, devs) + self.Parser.findall(Filter.Network.IFNAME_VLAN, devs)
|
|
if len(attches) > 1: raise Exception("Multiple PIF on bridge %s (%s)"%(dev, attches))
|
|
elif len(attches) == 0: ifInst.attach = "null"
|
|
elif len(attches) == 1: ifInst.attach = attches[0]
|
|
ifs[dev] = ifInst
|
|
|
|
return ifs
|
|
|
|
def bringUP(self, ifName):
|
|
doCmd(['ifconfig', ifName, 'up'])
|
|
|
|
def bringDown(self, ifName):
|
|
doCmd(['ifconfig', ifName, 'down'])
|
|
|
|
@staticmethod
|
|
def createBridge(jStr):
|
|
try:
|
|
network = OvmNetwork()
|
|
network._createBridge(toOvmBridge(jStr))
|
|
return SUCC()
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.createBridge, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.createBridge), errmsg)
|
|
|
|
@staticmethod
|
|
def deleteBridge(name):
|
|
try:
|
|
network = OvmNetwork()
|
|
network._deleteBridge(name)
|
|
return SUCC()
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.deleteBridge, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.deleteBridge), errmsg)
|
|
|
|
@staticmethod
|
|
def getAllBridges():
|
|
try:
|
|
network = OvmNetwork()
|
|
rs = toGson(network._getBridges())
|
|
logger.debug(OvmNetwork.getAllBridges, rs)
|
|
return rs
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.getAllBridges, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getAllBridges), errmsg)
|
|
|
|
@staticmethod
|
|
def getBridgeByIp(ip):
|
|
try:
|
|
routes = doCmd(['ip', 'route']).split('\n')
|
|
brName = None
|
|
for r in routes:
|
|
if ip in r and "xenbr" in r or "vlan" in r:
|
|
brName = r.split(' ')[2]
|
|
break
|
|
if not brName: raise Exception("Cannot find bridge with IP %s"%ip)
|
|
logger.debug(OvmNetwork.getBridgeByIp, "bridge:%s, ip:%s"%(brName, ip))
|
|
return toGson({"bridge":brName})
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.getBridgeByIp, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getBridgeByIp), errmsg)
|
|
|
|
@staticmethod
|
|
def getVlans():
|
|
try:
|
|
network = OvmNetwork()
|
|
rs = toGson(network._getVlans())
|
|
logger.debug(OvmNetwork.getVlans, rs)
|
|
return rs
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.getVlans, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getVlans), errmsg)
|
|
|
|
@staticmethod
|
|
def createVlan(jStr):
|
|
try:
|
|
network = OvmNetwork()
|
|
vlan = network._createVlan(toOvmVlan(jStr))
|
|
rs = fromOvmVlan(vlan)
|
|
logger.debug(OvmNetwork.createVlan, rs)
|
|
return rs
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.createVlan, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.createVlan), errmsg)
|
|
|
|
@staticmethod
|
|
def createVlanBridge(bridgeDetails, vlanDetails):
|
|
try:
|
|
network = OvmNetwork()
|
|
v = toOvmVlan(vlanDetails)
|
|
b = toOvmBridge(bridgeDetails)
|
|
vlan = network._createVlan(v)
|
|
b.attach = vlan.name
|
|
network._createBridge(b)
|
|
return SUCC()
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.createVlanBridge, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.createVlanBridge), errmsg)
|
|
|
|
@staticmethod
|
|
def deleteVlanBridge(name):
|
|
try:
|
|
network = OvmNetwork()
|
|
if name not in network.bridges.keys():
|
|
logger.debug(OvmNetwork.deleteVlanBridge, "No bridge %s found"%name)
|
|
return SUCC()
|
|
|
|
bridge = network.bridges[name]
|
|
vlanName = bridge.attach
|
|
if network._deleteBridge(name):
|
|
if vlanName != "null":
|
|
network._deleteVlan(vlanName)
|
|
else:
|
|
logger.warning(OvmNetwork.deleteVlanBridge, "Bridge %s has no vlan device"%name)
|
|
return SUCC()
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.deleteVlanBridge, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.deleteVlanBridge), errmsg)
|
|
|
|
@staticmethod
|
|
def getBridgeDetails(name):
|
|
try:
|
|
network = OvmNetwork()
|
|
if name not in network.bridges.keys():
|
|
raise Exception("No bridge %s found"%name)
|
|
bridge = network.bridges[name]
|
|
rs = fromOvmBridge(bridge)
|
|
logger.debug(OvmNetwork.getBridgeDetails, rs)
|
|
return rs
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.getBridgeDetails, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.getBridgeDetails), errmsg)
|
|
|
|
@staticmethod
|
|
def deleteVlan(name):
|
|
try:
|
|
network = OvmNetwork()
|
|
network._deleteVlan(name)
|
|
return SUCC()
|
|
except Exception, e:
|
|
errmsg = fmt_err_msg(e)
|
|
logger.error(OvmNetwork.deleteVlan, errmsg)
|
|
raise XmlRpcFault(toErrCode(OvmNetwork, OvmNetwork.deleteVlan), errmsg)
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
OvmNetwork.getBridgeDetails(sys.argv[1])
|
|
#=======================================================================
|
|
# txt = json.dumps({"vid":104, "pif":"eth0"})
|
|
# txt2 = json.dumps({"name":"xapi3", "attach":"eth0.104"})
|
|
# print nw.createVlan(txt)
|
|
# print nw.createBridge(txt2)
|
|
#
|
|
# nw.deleteBridge("xapi3")
|
|
# nw.deleteVlan("eth0.104")
|
|
#=======================================================================
|
|
|
|
except Exception, e:
|
|
print e
|