def voss_parse(lines, indent=None, comment_tokens=None): toplevel = re.compile(r'(^interface.*$)|(^router \w+$)|(^router vrf \w+$)') exitline = re.compile(r'^exit$') entry_reg = re.compile(r'([{};])') ancestors = list() config = list() dup_parent_index = None for line in to_native(lines, errors='surrogate_or_strict').split('\n'): text = entry_reg.sub('', line).strip() cfg = ConfigLine(text) if not text or ignore_line(text, comment_tokens): continue # Handle top level commands if toplevel.match(text): # Looking to see if we have existing parent for index, item in enumerate(config): if item.text == text: # This means we have an existing parent with same label dup_parent_index = index break ancestors = [cfg] config.append(cfg) # Handle 'exit' line elif exitline.match(text): ancestors = list() if dup_parent_index is not None: # We're working with a duplicate parent # Don't need to store exit, just go to next line in config dup_parent_index = None else: cfg._parents = ancestors[:1] config.append(cfg) # Handle sub-level commands. Only have single sub-level elif ancestors: cfg._parents = ancestors[:1] if dup_parent_index is not None: # Update existing entry, since this already exists in config config[int(dup_parent_index)].add_child(cfg) new_index = dup_parent_index + 1 config.insert(new_index, cfg) else: ancestors[0].add_child(cfg) config.append(cfg) else: # Global command, no further special handling needed config.append(cfg) return config
def add(self, lines, parents=None): ancestors = list() offset = 0 obj = None # global config command if not parents: for line in lines: # handle ignore lines if ignore_line(line): continue item = ConfigLine(line) item.raw = line self.items.append(item) else: for index, p in enumerate(parents): try: i = index + 1 obj = self.get_block(parents[:i])[0] ancestors.append(obj) except ValueError: # add parent to config offset = index * self._indent obj = ConfigLine(p) obj.raw = p.rjust(len(p) + offset) if ancestors: obj._parents = list(ancestors) ancestors[-1]._children.append(obj) self.items.append(obj) ancestors.append(obj) # add child objects for line in lines: # handle ignore lines if ignore_line(line): continue # check if child already exists for child in ancestors[-1]._children: if child.text == line: break else: offset = len(parents) * self._indent item = ConfigLine(line) item.raw = line.rjust(len(line) + offset) item._parents = ancestors ancestors[-1]._children.append(item) self.items.append(item)
def os6_parse(lines, indent=None, comment_tokens=None): sublevel_cmds = [ re.compile(r'^vlan !(priority).*$'), re.compile(r'^stack.*$'), re.compile(r'^interface.*$'), re.compile(r'datacenter-bridging.*$'), re.compile(r'line (console|telnet|ssh).*$'), re.compile(r'ip ssh !(server).*$'), re.compile(r'ip dhcp pool.*$'), re.compile(r'ip vrf !(forwarding).*$'), re.compile(r'(ip|mac|management|arp) access-list.*$'), re.compile(r'ipv6 (dhcp pool|router).*$'), re.compile(r'mail-server.*$'), re.compile(r'vpc domain.*$'), re.compile(r'router.*$'), re.compile(r'route-map.*$'), re.compile(r'policy-map.*$'), re.compile(r'class-map match-all.*$'), re.compile(r'captive-portal.*$'), re.compile(r'admin-profile.*$'), re.compile(r'link-dependency group.*$'), re.compile(r'banner motd.*$'), re.compile(r'openflow.*$'), re.compile(r'support-assist.*$'), re.compile(r'template.*$'), re.compile(r'address-family.*$'), re.compile(r'spanning-tree mst configuration.*$'), re.compile( r'logging (?!.*(cli-command|buffered|console|email|facility|file|monitor|protocol|snmp|source-interface|traps|web-session)).*$' ), re.compile(r'(radius-server|tacacs-server) host.*$') ] childline = re.compile(r'^exit$') config = list() parent = list() children = [] parent_match = False for line in str(lines).split('\n'): text = str(re.sub(r'([{};])', '', line)).strip() cfg = ConfigLine(text) cfg.raw = line if not text or ignore_line(text, comment_tokens): parent = list() children = [] continue parent_match = False # handle sublevel parent for pr in sublevel_cmds: if pr.match(line): if len(parent) != 0: cfg._parents.extend(parent) parent.append(cfg) config.append(cfg) if children: children.insert(len(parent) - 1, []) children[len(parent) - 2].append(cfg) parent_match = True continue # handle exit if childline.match(line): if children: parent[len(children) - 1]._children.extend( children[len(children) - 1]) if len(children) > 1: parent[len(children) - 2]._children.extend( parent[len(children) - 1]._children) cfg._parents.extend(parent) children.pop() parent.pop() if not children: children = list() if parent: cfg._parents.extend(parent) parent = list() config.append(cfg) # handle sublevel children elif parent_match is False and len(parent) > 0: if not children: cfglist = [cfg] children.append(cfglist) else: children[len(parent) - 1].append(cfg) cfg._parents.extend(parent) config.append(cfg) # handle global commands elif not parent: config.append(cfg) return config