# 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 .utilities import bash from .cloudException import CloudRuntimeException, CloudInternalException import logging import os import re import subprocess class networkConfig: class devInfo: def __init__(self, macAddr, ipAddr, netmask, gateway, type, name): self.name = name self.macAdrr = macAddr self.ipAddr = ipAddr self.netmask = netmask self.gateway = gateway self.type = type self.name = name #dhcp or static self.method = None @staticmethod def listNetworks(): devs = os.listdir("/sys/class/net/") devs = list(filter(networkConfig.isBridge, devs)) return devs @staticmethod def getDefaultNetwork(): cmd = bash("route -n|awk \'/^0.0.0.0/ {print $2,$8}\'") if not cmd.isSuccess(): logging.debug("Failed to get default route") raise CloudRuntimeException("Failed to get default route") result = cmd.getStdout().split(" ") gateway = result[0] dev = result[1] pdi = networkConfig.getDevInfo(dev) logging.debug("Found default network device:%s"%pdi.name) pdi.gateway = gateway return pdi @staticmethod def createBridge(dev, brName): if not networkConfig.isBridgeSupported(): logging.debug("bridge is not supported") return False if networkConfig.isBridgeEnslavedWithDevices(brName): logging.debug("bridge: %s has devices enslaved"%brName) return False cmds = "" if not networkConfig.isBridge(brName): cmds = "ip link add name %s type bridge ;"%brName cmds += "ifconfig %s up;"%brName cmds += "ip link set dev %s master %s"%(dev, brName) return bash(cmds).isSuccess() @staticmethod def isBridgeEnslavedWithDevices(brName): if not networkConfig.isBridge(brName): return False if not os.listdir("/sys/class/net/%s/brif"%brName): return False return True @staticmethod def isBridgeSupported(): if os.path.exists("/proc/sys/net/bridge"): return True return bash("modprobe -b bridge").isSuccess() @staticmethod def isNetworkDev(devName): return os.path.exists("/sys/class/net/%s" % devName) @staticmethod def isBridgePort(devName): return os.path.exists("/sys/class/net/%s/brport" % devName) @staticmethod def isBridge(devName): return os.path.exists("/sys/class/net/%s/bridge" % devName) @staticmethod def isOvsBridge(devName): cmd = bash("which ovs-vsctl") if not cmd.isSuccess(): return False try: return 0==subprocess.check_call(("ovs-vsctl", "br-exists", devName)) except subprocess.CalledProcessError: return False @staticmethod def getBridge(devName): bridgeName = None if os.path.exists("/sys/class/net/%s/brport/bridge"%devName): realPath = os.path.realpath("/sys/class/net/%s/brport/bridge"%devName) bridgeName = realPath.split("/")[-1] return bridgeName @staticmethod def getEnslavedDev(br, brPort): if not networkConfig.isBridgeEnslavedWithDevices(br): return None for dev in os.listdir("/sys/class/net/%s/brif"%br): br_port = int(open("/sys/class/net/%s/brif/%s/port_no"%(br,dev)).readline().strip("\n"), 16) if br_port == brPort: return dev return None @staticmethod def getDevInfo(dev): if not networkConfig.isNetworkDev(dev): logging.debug("dev: " + dev + " is not a network device") raise CloudInternalException("dev: " + dev + " is not a network device") netmask = None ipAddr = None macAddr = None cmd = bash("ifconfig " + dev) if not cmd.isSuccess(): logging.debug("Failed to get address from ifconfig") raise CloudInternalException("Failed to get network info by ifconfig %s"%dev) for line in cmd.getLines(): if line.find("HWaddr") != -1: macAddr = line.split("HWaddr ")[1].strip(" ") elif line.find("inet ") != -1: m = re.search("addr:(.*)\ *Bcast:(.*)\ *Mask:(.*)", line) if m is not None: ipAddr = m.group(1).rstrip(" ") netmask = m.group(3).rstrip(" ") if networkConfig.isBridgePort(dev): type = "brport" elif networkConfig.isBridge(dev) or networkConfig.isOvsBridge(dev): type = "bridge" else: type = "dev" return networkConfig.devInfo(macAddr, ipAddr, netmask, None, type, dev)