def test_docker_network(self): container_name = 'c1' br_name, br_ip = 'test-br', '192.168.150.1/24' c_ip, c_mask = '192.168.150.3', '24' c_pid, error = execute.exec_cmd( 'docker inspect --format={{.State.Pid}} ' + container_name) if c_pid.strip() and not error: self.__delete_container(container_name) execute.exec_cmd( 'docker run -d --name {0} --net=none interhui/alpine-ssh /usr/sbin/sshd -D' .format(container_name)) self.d.add_network(br_name, br_ip) self.d.connect(container_name, br_name, '{0}/{1}'.format(c_ip, c_mask)) result, _ = execute.exec_cmd( 'ping {0} -c 1 -q | grep packets'.format(c_ip)) self.assertTrue('0% packet loss' in result.strip()) self.d.disconnect(container_name, br_name) self.d.del_network(br_name) self.__delete_container(container_name)
def __ln_netns(self, c_pid): # Link container's netns execute.exec_cmd('rm -f /var/run/netns/{0}'.format(c_pid)) if not os.path.exists('/var/run/netns'): os.makedirs('/var/run/netns', 0755) execute.exec_cmd('ln -s /proc/{0}/ns/net /var/run/netns/{0}'.format(c_pid))
def __ln_netns(self, c_pid): # Link container's netns execute.exec_cmd('rm -f /var/run/netns/{0}'.format(c_pid)) if not os.path.exists('/var/run/netns'): os.makedirs('/var/run/netns', 0755) execute.exec_cmd( 'ln -s /proc/{0}/ns/net /var/run/netns/{0}'.format(c_pid))
def del_route(self, gw, dst_ip = None, if_name = None): if gw: dst_ip = 'default' if not dst_ip else dst_ip if_name = 'dev ' + if_name if if_name else '' if gw: _, error = execute.exec_cmd('{0} ip route del {1} via {2} {3}'.format(self.netns, dst_ip, gw, if_name)) else: _, error = execute.exec_cmd('{0} ip route del {1}'.format(self.netns, dst_ip)) return False if error else True else: raise ValueError('Gateway is None')
def dump_flow(self, br_name, flow_cond = None): if not br_name: raise ValueError('Bridge name is None') cmd = 'ovs-ofctl dump-flows {0} \"{1}\"'.format(br_name, flow_cond if flow_cond else '') result, error = execute.exec_cmd(cmd) flows = [] if not error: lines = result.split('\n') for l in lines: l = l.strip() if l != None and not l.startswith('NXST_FLOW'): if 'actions' in l: flow = {} i = l.index('actions') conition, action = l[:i], l[i:] if conition: for item in conition.split(','): item = item.strip() if '=' in item: k, v = item.split('=') flow[k] = v else: flow['protocol'] = item if action: k, v = action.split('=') flow[k] = v flows.append(flow) return flows else: return []
def show_br(self): brs, br = {}, '' cmd = 'ovs-vsctl show' result, error = execute.exec_cmd(cmd) if error: return {} for l in result.split('\n'): l = l.strip().replace('"', '') if l.startswith('Bridge '): br = l.lstrip('Bridge ') brs[br] = {} brs[br]['Controller'] = [] brs[br]['Port'] = {} brs[br]['fail_mode'] = '' else: if l.startswith('Controller '): brs[br]['Controller'].append(l.replace('Controller ', '')) elif l.startswith('fail_mode: '): brs[br]['fail_mode'] = l.replace('fail_mode: ', '') elif l.startswith('Port '): phy_port = l.replace('Port ', '') # e.g., br-eth0 brs[br]['Port'][phy_port] = {'vlan': '', 'type': ''} elif l.startswith('tag: '): brs[br]['Port'][phy_port]['vlan'] = l.replace('tag: ', '') elif l.startswith('Interface '): brs[br]['Port'][phy_port]['intf'] = \ l.replace('Interface ', '') elif l.startswith('type: '): brs[br]['Port'][phy_port]['type'] = l.replace('type: ', '') return brs
def add_if(self, if_name, if_type = None, mtu = 1500, args = None): if if_name: if_type = ' type ' + if_type if if_type else '' _, error = execute.exec_cmd('{0} ip link add name {1} mtu {2} {3} {4}'.format(self.netns, if_name, mtu, if_type, args if args else '')) return False if error else True else: raise ValueError('Interface name is None')
def del_port(self, br_name, port_name): if br_name and port_name: cmd = 'ovs-vsctl del-port {0} {1}'.format(br_name, port_name) _, error = execute.exec_cmd(cmd) return False if error else True else: raise ValueError('Bridge name or Port name is None')
def dump_flow(self, br_name, flow_cond=None): if not br_name: raise ValueError('Bridge name is None') cmd = 'ovs-ofctl dump-flows {0} \"{1}\"'.format( br_name, flow_cond if flow_cond else '') result, error = execute.exec_cmd(cmd) flows = [] if not error: lines = result.split('\n') for l in lines: l = l.strip() if l != None and not l.startswith('NXST_FLOW'): if 'actions' in l: flow = {} i = l.index('actions') conition, action = l[:i], l[i:] if conition: for item in conition.split(','): item = item.strip() if '=' in item: k, v = item.split('=') flow[k] = v else: flow['protocol'] = item if action: k, v = action.split('=') flow[k] = v flows.append(flow) return flows else: return []
def __get_container_pid(self, container_name): c_pid, error = execute.exec_cmd( 'docker inspect --format={{.State.Pid}} ' + container_name) if not c_pid or error: raise IOError('Get container {0} PID fail : {1}'.format( container_name, error)) return c_pid.strip()
def del_br(self, br_name): if br_name: cmd = 'ovs-vsctl --if-exists del-br {0}'.format(br_name) _, error = execute.exec_cmd(cmd) return False if error else True else: raise ValueError('Bridge name is None')
def set_if(self, if_name, key, value): if if_name: if not key or not value: raise ValueError('Key or Value is None') _, error = execute.exec_cmd('{0} ip link set {1} {2} {3}'.format(self.netns, if_name, key, value)) return False if error else True else: raise ValueError('Interface name is None')
def add_flow(self, br_name, flow): if not br_name: raise ValueError('Bridge name is None') if not flow: raise ValueError('Flow is None') cmd = 'ovs-ofctl add-flow {0} \"{1}\"'.format(br_name, flow) _, error = execute.exec_cmd(cmd) return False if error else True
def del_addr(self, if_name, ip_addr): if if_name: if not ip_addr: raise ValueError('Ip Address is None') _, error = execute.exec_cmd('{0} ip addr del {1} dev {2}'.format(self.netns, ip_addr, if_name)) return False if error else True else: raise ValueError('Interface name is None')
def __flow_rec(self, br_name ,flow_type, target_ip, target_port, params): if br_name: cmd = 'ovs-vsctl -- set Bridge {0} {1}=@f '.format(br_name, flow_type) cmd += '-- --id=@f create {0} targets=\\"{1}:{2}\\" '.format(flow_type, target_ip, target_port) cmd += self.__build_params(params) _, error = execute.exec_cmd(cmd) return False if error else True else: raise IOError('Bridge name is None')
def clear(self, table, record, columns): if not isinstance(columns, list) or not isinstance(columns, set): columns = [str(columns)] for column in columns: cmd = '{0} clear {1} {2} {3}'.format(self.cmd, table, record, column) _, error = execute.exec_cmd(cmd) if error: return False return True
def add_br(self, br_name, parent = None, vlan = None): if br_name: cmd = 'ovs-vsctl --may-exist add-br {0}'.format(br_name) if parent != None and vlan != None: cmd = '{0} {1} {2}'.format(cmd, parent, vlan) _, error = execute.exec_cmd(cmd) return False if error else True else: raise ValueError('Bridge name is None')
def add_port(self, br_name, port_name, iface = None): if br_name and port_name: cmd = 'ovs-vsctl add-port {0} {1}'.format(br_name, port_name) if iface != None: cmd = '{0} {1}'.format(cmd, iface) _, error = execute.exec_cmd(cmd) return False if error else True else: raise ValueError('Bridge name or Port name is None')
def get(self, table, record, column, key = None): cmd = '{0} get {1} {2} {3}{4}'.format(self.cmd, table, record, column, ':' + key if key else '') result, error = execute.exec_cmd(cmd) if not error: result = result.strip() if result.startswith('"') and result.endswith('"'): result = result[1:len(result) - 1] return result else: return None
def list_log(self): log_lst = {} cmd = 'ovs-appctl vlog/list' result, error = execute.exec_cmd(cmd) if not error: for l in result.split('\n'): items = [item for item in l.strip().split(' ') if item.strip()] if len(items) == 4: log_lst[items[0]] = {'console':items[1], 'syslog':items[2], 'file':items[3]} return log_lst
def get(self, table, record, column, key=None): cmd = '{0} get {1} {2} {3}{4}'.format(self.cmd, table, record, column, ':' + key if key else '') result, error = execute.exec_cmd(cmd) if not error: result = result.strip() if result.startswith('"') and result.endswith('"'): result = result[1:len(result) - 1] return result else: return None
def qos(self, port_name, max_rate, min_rate): if port_name: max_rate = (100 if not str(max_rate).isalnum() or max_rate < 0 else max_rate) * 1000 min_rate = (10 if not str(min_rate).isalnum() or min_rate < 0 else min_rate) * 1000 port_cmd = '-- set port {0} qos=@q'.format(port_name) qos_cmd = '-- --id=@q create qos type=linux-htb other-config:max-rate={0} queues=0=@q0'.format(max_rate) queue_cmd = '-- --id=@q0 create queue other-config:min-rate={0} other-config:max-rate={1}'.format(min_rate, max_rate) cmd = 'ovs-vsctl {0} {1} {2}'.format(port_cmd, qos_cmd, queue_cmd) _, error = execute.exec_cmd(cmd) return False if error else True else: raise ValueError('Port name is None')
def list(self, table, record = None): cmd = '{0} list {1} {2}'.format(self.cmd, table, record if record else '') result, error = execute.exec_cmd(cmd) objs = [] if not error: obj = {} for l in result.split('\n'): if not l.strip(): objs.append(obj) obj = {} else: if ':' in l: key, value = l.split(':', 1) obj[key.strip()] = value.strip() return objs
def list_log(self): log_lst = {} cmd = 'ovs-appctl vlog/list' result, error = execute.exec_cmd(cmd) if not error: for l in result.split('\n'): items = [item for item in l.strip().split(' ') if item.strip()] if len(items) == 4: log_lst[items[0]] = { 'console': items[1], 'syslog': items[2], 'file': items[3] } return log_lst
def list(self, table, record=None): cmd = '{0} list {1} {2}'.format(self.cmd, table, record if record else '') result, error = execute.exec_cmd(cmd) objs = [] if not error: obj = {} for l in result.split('\n'): if not l.strip(): objs.append(obj) obj = {} else: if ':' in l: key, value = l.split(':', 1) obj[key.strip()] = value.strip() return objs
def bond(self, br_name, bond_name, ports, lacp = False, mode = None): if br_name and bond_name and ports != None: ports = ' '.join(ports) cmd = 'ovs-vsctl add-bond {0} {1} {2}'.format(br_name, bond_name, ports) _, error = execute.exec_cmd(cmd) if not error: err = False if lacp: err = self.d.set('Port', bond_name, {'lacp' : 'active'}) if mode == 'slb': err = self.d.set('Port', bond_name, {'bond_mode' : 'balance-slb'}) elif mode == 'tcp': err = self.d.set('Port', bond_name, {'bond_mode' : 'balance-tcp'}) return err else: return False else: raise ValueError('Bridge name or Bond name is None')
def mirror(self, name, br_name, input_port, output_port, direction = None): if name and br_name and input_port and output_port: br_cmd = '-- set bridge {0} mirror=@m'.format(br_name) ports = chain(input_port, output_port) ports_cmds = [] for port in ports: ports_cmds.append('-- --id=@{0} get Port {0}'.format(port)) mirror_cmd = '-- --id=@m create Mirror name={0}'.format(name) if not direction or direction == 'in' or direction == 'all': mirror_cmd += ' select-src-port=@' + ',@'.join(input_port) if not direction or direction == 'out' or direction == 'all': mirror_cmd += ' select-dst-port=@' + ',@'.join(input_port) mirror_cmd += ' output-port=@' + ',@'.join(output_port) cmd = 'ovs-vsctl {0} {1} {2}'.format(br_cmd, ' '.join(ports_cmds), mirror_cmd) _, error = execute.exec_cmd(cmd) return False if error else True else: raise ValueError('Mirror name or Bridge name or Ports is None')
def destroy(self, table, record): cmd = '{0} destroy {1} {2}'.format(self.cmd, table, record) _, error = execute.exec_cmd(cmd) return False if error else True
def create(self, table, data): cmd = '{0} create {1} {2}'.format(self.cmd, table, self.__build_params(data)) _, error = execute.exec_cmd(cmd) return False if error else True
def remove(self, table, record, column, data): cmd = '{0} remove {1} {2} {3} {4}'.format(self.cmd, table, record, column, self.__build_params(data)) _, error = execute.exec_cmd(cmd) return False if error else True
def flush(self, if_name): if if_name: _, error = execute.exec_cmd('{0} ip addr flush dev {1}'.format(self.netns, if_name)) return False if error else True else: raise ValueError('Interface name is None')
def __delete_container(self, container_name): execute.exec_cmd('docker stop ' + container_name) execute.exec_cmd('docker rm ' + container_name)
def set(self, table, record, data): cmd = '{0} set {1} {2} {3}'.format(self.cmd, table, record, self.__build_params(data)) _, error = execute.exec_cmd(cmd) return False if error else True
def find(self, table, condition): cmd = '{0} find {1} {2}'.format(self.cmd, table, condition) result, error = execute.exec_cmd(cmd) return result.strip() if not error else None
def del_tap(self, tap_name): if tap_name: _, error = execute.exec_cmd('tunctl -d {0}'.format(tap_name)) return False if error else True else: raise ValueError('Tap interface name is None')
def del_flow(self, br_name, flow=None): if not br_name: raise ValueError('Bridge name is None') cmd = 'ovs-ofctl del-flows {0} \"{1}\"'.format(br_name, flow) _, error = execute.exec_cmd(cmd) return False if error else True
def list_br(self): cmd = 'ovs-vsctl list-br' result, error = execute.exec_cmd(cmd) return [l.strip() for l in result.split('\n') if l.strip()] if not error else []
def set_log_pattern(self, destination, pattern): cmd = 'ovs-appctl vlog/set PATTERN:{0}:{1}'.format(destination, pattern) _, error = execute.exec_cmd(cmd) return False if error else True
def del_flow(self, br_name, flow = None): if not br_name: raise ValueError('Bridge name is None') cmd = 'ovs-ofctl del-flows {0} \"{1}\"'.format(br_name, flow) _, error = execute.exec_cmd(cmd) return False if error else True
def set_log(self, module, destination, level): cmd = 'ovs-appctl vlog/set {0}:{1}:{2}'.format(module, destination, level) _, error = execute.exec_cmd(cmd) return False if error else True
def list_port(self, br_name): cmd = 'ovs-vsctl list-ports {0}'.format(br_name) result, error = execute.exec_cmd(cmd) return [l.strip() for l in result.split('\n') if l.strip()] if not error else []
def set_log_facility(self, facility): cmd = 'ovs-appctl vlog/set FACILITY:{0}'.format(facility) _, error = execute.exec_cmd(cmd) return False if error else True
def list_port_to_br(self, port_name): cmd = 'ovs-vsctl port-to-br {0}'.format(port_name) result, error = execute.exec_cmd(cmd) return [l.strip() for l in result.split('\n') if l.strip()] if not error else []
def __get_container_pid(self, container_name): c_pid, error = execute.exec_cmd('docker inspect --format={{.State.Pid}} ' + container_name) if not c_pid or error: raise IOError('Get container {0} PID fail : {1}'.format(container_name, error)) return c_pid.strip()
def shutdown(self, if_name): if if_name: _, error = execute.exec_cmd('{0} ip link set {1} down'.format(self.netns, if_name)) return False if error else True else: raise ValueError('Interface name is None')