blob: c60b1ecbd36a297ca814eaa688dc3627a80c95ae [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
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