def _load(self, test_content=None): if not test_content: # test_content is null run_cmd = '%s exec %s ip a' % (self.ns_cmd, self.id) content, err = Popen(run_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Failed to run %s, err=%s\n" % (run_cmd, err)) return else: content = test_content lines = content.split('\n') intfs = {} # {'1':{'intf': eth0, 'ip': [ip1, ip2]}, 'mac': xxx } for l in lines: if not l: continue if not l.startswith(' '): # one interface: 1: lo: xxxxx intf_line = l.split(':') if len(intf_line) < 2: warn('Seems the interface line too short\n') continue else: id = intf_line[0].strip() intf = intf_line[1].strip() intfs[id] = {'intf': intf, 'ip': [], 'mac': '*'} else: # some content line cons = l.split() if len(cons) < 2: continue if cons[0] == 'inet': intfs[id]['ip'].append(cons[1]) elif cons[0] == 'link/ether': intfs[id]['mac'] = cons[1] self.intfs = intfs
def _load(self, test_content=None): if not test_content: # test_content is null run_cmd = '%s exec %s ip a' % (self.ns_cmd, self.id) content, err = Popen(run_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Failed to run %s, err=%s\n" % (run_cmd, err)) return else: content = test_content lines = content.split('\n') intfs = {} # {'1':{'intf': eth0, 'ip': [ip1, ip2]}, 'mac': xxx } for l in lines: if not l: continue if not l.startswith(' '): # one interface: 1: lo: xxxxx intf_line = l.split(':') if len(intf_line) < 2: warn('Seems the interface line too short\n') continue else: id = intf_line[0].strip() intf = intf_line[1].strip() intfs[id] = {'intf': intf, 'ip': [], 'mac': '*' } else: # some content line cons = l.split() if len(cons) < 2: continue if cons[0] == 'inet': intfs[id]['ip'].append(cons[1]) elif cons[0] == 'link/ether': intfs[id]['mac'] = cons[1] self.intfs = intfs
def do_dvr(self, arg): """ Check the dvr rules dvr [check] dvr check compute dvr check net """ args = arg.split() if len(args) > 2: # only 1 is valid warn("Not correct parameters, use as:\n") warn("dvr [check]\n") warn("dvr check compute\n") warn("dvr check net\n") return self.dvr = DVR() if len(args) == 0: # default cmd for ns args.insert(0, 'check') cmd = args[0] if not hasattr(self.dvr, '%s' % cmd): error('Unsupported cmd=%s\n' % cmd) return if cmd == 'check': if len(args) == 1: # only check cmd is given debug('run self.dvr.%s()\n' % cmd) getattr(self.dvr, '%s' % cmd)() else: # node parameter is given debug('run self.dvr.%s(%s)\n' % (cmd, args[1])) getattr(self.dvr, '%s' % cmd)(args[1])
def load(self, chain=None, ns=None): ''' Load chains of this table from the system :param chain: which chain to load, None for all :param ns: which ns to load, None for root :return: ''' if chain: run_cmd = self.run_cmd + ' ' + chain else: run_cmd = self.run_cmd if ns: run_cmd = 'ip netns exec %s %s' % (ns, run_cmd) rules, err = Popen(run_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Failed to run %s, err=%s\n" % (run_cmd, err)) return self.chains, self.ns = {}, ns # cleaning exiting rules chains = rules.split('\n\n') for chain in chains: # some chain r = chain.splitlines() # lines of rule #if not r: # continue title = r[0].split() # r[0] is the title row if title[0] == 'Chain' and title[1] not in self.chains: # title if 'DROP' in title: self.chains[title[1]] = IPchain(title[1], 'DROP') else: self.chains[title[1]] = IPchain(title[1]) keys = r[1].split() keys.append('flags') self.chains[title[1]].set_keys(keys) self.chains[title[1]].add_rules(r[2:]) # those are real rules
def do_dvr(self, arg): """ Check the dvr rules dvr [check] dvr check compute dvr check net """ args = arg.split() if len(args) > 2: # only 1 is valid warn("Not correct parameters, use as:\n") warn("dvr [check]\n") warn("dvr check compute\n") warn("dvr check net\n") return if len(args) == 0: # default cmd for ns args.insert(0, 'check') cmd = args[0] if not hasattr(self.dvr, '%s' % cmd): error('Unsupported cmd=%s\n' % cmd) return if cmd == 'check': if len(args) == 1: # only check cmd is given debug('run self.dvr.%s()\n' % cmd) getattr(self.dvr, '%s' % cmd)() else: # node parameter is given debug('run self.dvr.%s(%s)\n' % (cmd, args[1])) getattr(self.dvr, '%s' % cmd)(args[1])
def show_routes(self): """ """ run_cmd = '%s exec %s route -en' % (self.ns_cmd, self.id) result, err = Popen(run_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Failed to run %s, err=%s\n" % (run_cmd, err)) else: output(result)
def check(self, _node=None): node = _node or self.node if node in 'compute': output(b('# Checking DVR on compute node\n')) self._check_compute_node() elif node in 'network': output(b('# Checking DVR on network node\n')) self._check_network_node() else: error('Unknown node type=%s, compute or network?\n' % node)
def br_delbr(name): """ Delete a bridge. """ cmd = "ovs-vsctl --if-exists del-br %s" % name result, err = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Error when deleting bridge %s\n" % name) else: output("bridge %s was deleted\n" % name)
def br_addbr(bridge_name): """ Create a new bridge. """ br = ovs_lib.BaseOVS() br.add_bridge(bridge_name) if br_exists(bridge_name): output("bridge %s was created\n" % bridge_name) else: error("Error when adding new bridge %s\n" % bridge_name)
def br_delbr(bridge_name): """ Delete a bridge. """ br = ovs_lib.BaseOVS() br.delete_bridge(bridge_name) if not br_exists(bridge_name): output("bridge %s was deleted\n" % bridge_name) else: error("Error when deleting bridge %s\n" % bridge_name)
def br_addbr(name): """ Create a new bridge. """ cmd = "ovs-vsctl --may-exist add-br %s" % name result, err = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Error when adding new bridge %s\n" % name) else: output("bridge %s was created\n" % name)
def br_delbr(name): """ Delete a bridge. """ cmd = "ovs-vsctl --if-exists del-br %s" % name result, err = \ Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Error when deleting bridge %s\n" % name) else: output("bridge %s was deleted\n" % name)
def br_addbr(name): """ Create a new bridge. """ cmd = "ovs-vsctl --may-exist add-br %s" % name result, err = \ Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Error when adding new bridge %s\n" % name) else: output("bridge %s was created\n" % name)
def do_ipt(self, arg): """ Show the iptables rules, e.g., ipt vm vm1,vm2 ipt show nat,raw,filter [INPUT] ipt check nat,raw,filter """ args = arg.split() if len(args) < 1 or len(args) > 3: # only 1-3 is valid warn("Not correct parameters, use as:\n") warn("ipt vm vm_ip\n") warn("ipt show|check [filter] [INPUT]\n") return cmd = args[0] if not hasattr(self.ipt, '%s' % cmd): error('Unsupported cmd=%s\n' % cmd) return if cmd == 'vm': if len(args) == 1: error('No vm ip is given\n') return else: for vm_ip in args[1:]: debug('run self.ipt.%s(%s)\n' % (cmd, vm_ip)) getattr(self.ipt, '%s' % cmd)(vm_ip) elif cmd in ['check', 'show']: ns = None if args[-1] in NameSpaces().get_ids(): ns = args.pop() if len(args) == 1: # show debug('run self.ipt.%s(ns=%s)\n' % (cmd, ns)) getattr(self.ipt, '%s' % cmd)(ns=ns) return elif len(args) == 2: # filter|INPUT if args[1] in self.ipt.get_valid_tables(): # filter debug('run self.ipt.%s(table=%s,ns=%s)\n' % (cmd, args[1], ns)) getattr(self.ipt, '%s' % cmd)(table=args[1], ns=ns) else: # INPUT debug('run self.ipt.%s(chain=%s, ns=%s)\n' % (cmd, args[1], ns)) getattr(self.ipt, '%s' % cmd)(chain=args[1], ns=ns) elif len(args) == 3: if args[1] in self.ipt.get_valid_tables(): # filter INPUT debug('run self.ipt.%s(table=%s, chain=%s, ns=%s\n)' % (cmd, args[1], args[2], ns)) getattr(self.ipt, '%s' % cmd)(table=args[1], chain=args[2], ns=ns) else: warn("Unknown table, table=%s\n" % args[1])
def do_ipt(self, arg): """ Show the iptables rules, e.g., ipt vm vm1,vm2 ipt show nat,raw,filter [INPUT] ipt check nat,raw,filter """ args = arg.split() if len(args) < 1 or len(args) > 3: # only 1-3 is valid warn("Not correct parameters, use as:\n") warn("ipt vm vm_ip\n") warn("ipt show|check [filter] [INPUT]\n") return self.ipt = IPtables() cmd = args[0] if not hasattr(self.ipt, '%s' % cmd): error('Unsupported cmd=%s\n' % cmd) return if cmd == 'vm': if len(args) == 1: error('No vm ip is given\n') return else: for vm_ip in args[1:]: debug('run self.ipt.%s(%s)\n' % (cmd, vm_ip)) getattr(self.ipt, '%s' % cmd)(vm_ip) elif cmd in ['check', 'show']: ns = None if args[-1] in NameSpaces().get_ids(): ns = args.pop() if len(args) == 1: # show debug('run self.ipt.%s(ns=%s)\n' % (cmd, ns)) getattr(self.ipt, '%s' % cmd)(ns=ns) return elif len(args) == 2: # filter|INPUT if args[1] in self.ipt.get_valid_tables(): # filter debug('run self.ipt.%s(table=%s,ns=%s)\n' % (cmd, args[1], ns)) getattr(self.ipt, '%s' % cmd)(table=args[1], ns=ns) else: # INPUT debug('run self.ipt.%s(chain=%s, ns=%s)\n' % (cmd, args[1], ns)) getattr(self.ipt, '%s' % cmd)(chain=args[1], ns=ns) elif len(args) == 3: if args[1] in self.ipt.get_valid_tables(): # filter INPUT debug('run self.ipt.%s(table=%s, chain=%s, ns=%s\n)' % (cmd, args[1], args[2], ns)) getattr(self.ipt, '%s' % cmd)(table=args[1], chain=args[2], ns=ns) else: warn("Unknown table, table=%s\n" % args[1])
def add_flow(self, flow): """ Return True or False to add a flow. """ if not flow: return False addflow_cmd = 'ovs-ofctl add-flow %s "%s"' % (self.bridge, flow) err = Popen(addflow_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()[1] if err: output(err) error("Error when adding new flow <%s> to bridge %s\n" % (flow, self.bridge)) return False else: return True
def get_ids(self): """ Get all ids of the namespaces :return: The list of namespace ids, e.g., ['red', 'blue'] """ run_cmd = '%s list' % self.ns_cmd spaces, err = Popen(run_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate() if err: error("Failed to run %s, err=%s\n" % (run_cmd, err)) return None if not spaces: # spaces == '' return None ns_list = spaces.rstrip('\n').split('\n') ns_list.sort() return ns_list
def check(self, _node=None): guess = 'compute' for ns_id in NameSpaces().get_ids(): if ns_id.startswith('snat-'): # only network has snat-* guess = 'network' break if not _node: output(b('# No node type given, guessing...%s node\n' % guess)) else: # given _node, will check if match if _node not in guess: warn(r('# Given node type=%s not match the server\n' % _node)) guess = _node node = guess if node in 'compute': return self._compute_node_check() elif node in 'network': return self._network_node_check() else: error('Unknown node type=%s, compute or network?\n' % node)
def _parse_flow(self, line): """ Return a Flow or None, converted from a given line of original flow. """ line = line.strip() table, packet, priority, match, actions = 0, 0, 0, '', '' if line.startswith('cookie='): table = get_num_after(line, 'table=') packet = get_num_after(line, 'n_packets=') if table is None or packet is None: return None for field in line.split(): if field.startswith('priority='): # match starts with pri priority = get_num_after(field, 'priority=') if priority is None: error('No priority field found in flow\n') return None match = \ field.replace('priority=%u' % priority, '').lstrip(',').strip() if not match: match = r'*' port_no = get_num_after(field, 'in_port=') if isinstance(port_no, int): intf = self._get_port_intf(port_no) if intf: match = \ match.replace('in_port=%u' % port_no, 'in_port=%s' % intf) elif field.startswith('actions='): actions = self._process_actions(field) if priority is None: # There is no priority= field match = line.split()[len(line.split()) - 2] if len(match) >= 30: match.replace('vlan_tci', 'vlan') match = re.compile('0x0{1,}').sub('0x', match) return Flow(self.bridge, table, packet, priority, match, actions) else: return None
def _parse_flow(self, line): """ Return a Flow or None, converted from a given line of original flow. """ line = line.strip() table, packet, priority, match, actions = 0, 0, 0, '', '' if line.startswith('cookie='): table = get_num_after(line, 'table=') packet = get_num_after(line, 'n_packets=') if table is None or packet is None: return None for field in line.split(): if field.startswith('priority='): # match starts with pri priority = get_num_after(field, 'priority=') if priority is None: error('No priority field found in flow\n') return None match = \ field.replace('priority=%u' % priority, '').lstrip(',').strip() if not match: match = r'*' port_no = get_num_after(field, 'in_port=') if isinstance(port_no, int): intf = self._get_port_intf(port_no) if intf: match = \ match.replace('in_port=%u' % port_no, 'in_port=%s' % intf) elif field.startswith('actions='): actions = field.replace('actions=', '').rstrip('\n') if priority is None: # There is no priority= field match = line.split()[len(line.split()) - 2] if len(match) >= 30: match.replace('vlan_tci', 'vlan') match = re.compile('0x0{1,}').sub('0x', match) return Flow(self.bridge, table, packet, priority, match, actions) else: return None
def default(self, line): # bridge, cmd, line = self.parseline( line ) if len(line.split()) < 2: error("*** Unknown command: %s ***\n" % line) return bridge, cmd, args = "", "", "" if len(line.split()) == 2: bridge, cmd = line.split() else: bridge, cmd, args = line.split()[0], line.split()[1], " ".join(line.split()[2:]) if br_exists(bridge): try: if args: getattr(self, "do_%s" % cmd)(" ".join([bridge, args])) else: getattr(self, "do_%s" % cmd)(bridge) except AttributeError: error("*** Unknown command: %s, cmd=%s, bridge=%s, args=%s ***\n" % (line, cmd, bridge, args)) else: error("*** Bridge %s is not existed\n" % bridge)
def default(self, line): #bridge, cmd, line = self.parseline( line ) if len(line.split()) < 2: error('*** Unknown command: %s ***\n' % line) return bridge, cmd, args = '', '', '' if len(line.split()) == 2: bridge, cmd = line.split() else: bridge, cmd, args = line.split()[0], line.split()[1], ' '.join(line.split()[2:]) if br_exists(bridge): try: if args: getattr(self, 'do_%s' % cmd)(' '.join([bridge, args])) else: getattr(self, 'do_%s' % cmd)(bridge) except AttributeError: error('*** Unknown command: %s, cmd=%s, bridge=%s, args=%s ***\n' % (line, cmd, bridge, args)) else: error('*** Bridge %s is not existed\n' % bridge)
def default(self, line): #bridge, cmd, line = self.parseline( line ) if len(line.split()) < 2: error('*** Unknown command: %s ***\n' % line) return bridge, cmd, args = '', '', '' if len(line.split()) == 2: bridge, cmd = line.split() else: bridge, cmd, args = \ line.split()[0], line.split()[1], ' '.join(line.split()[2:]) if br_exists(bridge): try: if args: getattr(self, 'do_%s' % cmd)(' '.join([bridge, args])) else: getattr(self, 'do_%s' % cmd)(bridge) except AttributeError: error('*** Unknown command: ' '%s, cmd=%s, bridge=%s, args=%s ' '***\n' % (line, cmd, bridge, args)) else: error('*** Bridge %s is not existed\n' % bridge)
def do_ns(self, arg): """ Show the network namespace content, e.g., ns list ns show id_prefix ns find pattern """ args = arg.split() if len(args) > 2: # only 1-2 is valid warn("Not correct parameters, use as:\n") warn("ns [list]\n") warn("ns show id_prefix (lo intf is ignored)\n") warn("ns find pattern\n") return self.nss = NameSpaces() if len(args) == 0: # default cmd for ns args.insert(0, 'list') cmd = args[0] if not hasattr(self.nss, '%s' % cmd): error('Unsupported cmd=%s\n' % cmd) return if cmd in ['list', 'clean']: if len(args) != 1: error('No param should be given\n') return else: debug('run self.nss.%s()\n' % cmd) getattr(self.nss, '%s' % cmd)() elif cmd in ['show', 'find', 'route']: if len(args) == 2: # debug('run self.nss.%s(%s)\n' % (cmd, args[1])) getattr(self.nss, '%s' % cmd)(args[1]) else: warn("Invalid param number, no reach here, %s\n" % arg) return else: error("Unknown cmd, cmd= %s\n" % arg)
def do_ns(self, arg): """ Show the network namespace content, e.g., ns list ns show id_prefix ns find pattern """ args = arg.split() if len(args) > 2: # only 1-2 is valid warn("Not correct parameters, use as:\n") warn("ns [list]\n") warn("ns show id_prefix (lo intf is ignored)\n") warn("ns find pattern\n") return if len(args) == 0: # default cmd for ns args.insert(0, "list") cmd = args[0] if not hasattr(self.nss, "%s" % cmd): error("Unsupported cmd=%s\n" % cmd) return if cmd == "list": if len(args) != 1: error("No param should be given\n") return else: debug("run self.nss.%s(...)\n" % cmd) getattr(self.nss, "%s" % cmd)() elif cmd in ["show", "find", "route"]: if len(args) == 2: # debug("run self.nss.%s(%s)\n" % (cmd, args[1])) getattr(self.nss, "%s" % cmd)(args[1]) else: warn("Invalid param number, no reach here, %s\n" % arg) return else: error("Unknown cmd, cmd= %s\n" % arg)
def do_ns(self, arg): """ Show the network namespace content, e.g., ns list ns show id_prefix ns find pattern """ args = arg.split() if len(args) > 2: # only 1-2 is valid warn("Not correct parameters, use as:\n") warn("ns [list]\n") warn("ns show id_prefix (lo intf is ignored)\n") warn("ns find pattern\n") return if len(args) == 0: # default cmd for ns args.insert(0, 'list') cmd = args[0] if not hasattr(self.nss, '%s' % cmd): error('Unsupported cmd=%s\n' % cmd) return if cmd == 'list': if len(args) != 1: error('No param should be given\n') return else: debug('run self.nss.%s(...)\n' % cmd) getattr(self.nss, '%s' % cmd)() elif cmd in ['show', 'find', 'route']: if len(args) == 2: # debug('run self.nss.%s(%s)\n' % (cmd, args[1])) getattr(self.nss, '%s' % cmd)(args[1]) else: warn("Invalid param number, no reach here, %s\n" % arg) return else: error("Unknown cmd, cmd= %s\n" % arg)
def del_flow(self, flow_ids, forced=False): """ Return True or False to del a flow from given list. """ if len(flow_ids) <= 0: return False if not self.flows: self.load_flows() del_flows = [] fd = sys.stdin.fileno() old = termios.tcgetattr(fd) for flow_id in flow_ids: if isinstance(flow_id, str) and flow_id.isdigit(): flow_id = int(flow_id) else: continue if flow_id >= len(self.flows): continue else: del_flow = self.flows[flow_id] if forced: del_flows.append(del_flow) else: Flow.banner_output() del_flow.fmt_output() output('Del the flow? [Y/n]: ') new = termios.tcgetattr(fd) new[3] = new[3] & ~termios.ICANON try: termios.tcsetattr(fd, termios.TCSADRAIN, new) while True: in_ch = sys.stdin.read(1) if in_ch == 'n' or in_ch == 'N': output('\tCancel the deletion.\n') break elif in_ch == 'y' or in_ch == 'Y' or in_ch != '\n': del_flows.append(del_flow) output('\n') break else: output('\nWrong, please input [Y/n]: ') continue finally: termios.tcsetattr(fd, termios.TCSADRAIN, old) if not del_flows: return False self.load_flows(True) f = open(self.flows_db, 'r') while True: lines = f.readlines(1000) if not lines: break for line in lines: flow = self._parse_flow(line) if flow in del_flows: del_matches = line.replace(',', ' ').split() del_matches = \ filter(lambda m: not (m.startswith("cookie=") or m.startswith("actions=")), del_matches) del_cmd = "ovs-ofctl --strict del-flows %s %s" \ % (self.bridge, ','.join(del_matches)) err = Popen(del_cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()[1] if err: error("Error when delflow <%s> in bridge %s\n" % (','.join(del_matches), self.bridge)) error(err) return False f.close() self.load_flows() return True