def test_parsing_new_style_config(self): s = """ system { ntp { server 0.vyatta.pool.ntp.org server 1.vyatta.pool.ntp.org server us.pool.ntp.org { prefer { } } server 2.vyatta.pool.ntp.org } time-zone Europe/Moscow name-server 10.10.2.2 }""" correct = { 'system': { 'ntp': { 'server': { '0.vyatta.pool.ntp.org': {}, '1.vyatta.pool.ntp.org': {}, 'us.pool.ntp.org': { 'prefer': {} }, '2.vyatta.pool.ntp.org': {}, } }, 'time-zone': 'Europe/Moscow', 'name-server': '10.10.2.2' } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def show_firewall(self): response = {'command': 'show_firewall'} # stdin, stdout, stderr = self.client.exec_command( # '/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper show firewall') stdin, stdout, stderr = self.client.exec_command( 'cat /config/config.boot') err = stderr.read().decode() if err is '': try: result = str(stdout.read().decode()) result = (vyattaconfparser.parse_conf(result)) # Uncomment to print pretty json # print(json.dumps(result, indent=2)) response['status'] = 'Success' response['message'] = {} if 'disable' in result['firewall']['name']['WAN_IN']['rule'][ '10'].keys(): response['message']['kids'] = 'enabled' else: response['message']['kids'] = 'disabled' if 'disable' in result['firewall']['name']['WAN_IN']['rule'][ '20'].keys(): response['message']['tv'] = 'enabled' else: response['message']['tv'] = 'disabled' except Exception as e: response['status'] = 'Failure' response['message'] = str(e) else: response['status'] = 'Failure' response['message'] = err self.q.put(response) Logger.info(f'Router: {response}')
def get_snmp_information(self): # 'acl' is not implemented yet output = self.device.send_command("show configuration") # convert the configuration to dictionary config = vyattaconfparser.parse_conf(output) snmp = dict() snmp["community"] = dict() try: for i in config["service"]["snmp"]["community"]: snmp["community"].update({ i: { "acl": py23_compat.text_type(""), "mode": py23_compat.text_type( config["service"]["snmp"]["community"][i] ["authorization"]) } }) snmp.update({ "chassis_id": py23_compat.text_type(""), "contact": py23_compat.text_type(config["service"]["snmp"]["contact"]), "location": py23_compat.text_type(config["service"]["snmp"]["location"]) }) return snmp except KeyError: return {}
def get_interfaces(self): """ "show interfaces" output example: Interface IP Address S/L Description --------- ---------- --- ----------- br0 - u/D eth0 192.168.1.1/24 u/u Management eth1 192.168.1.2/24 u/u eth2 192.168.3.1/24 u/u foobar 192.168.2.2/24 lo 127.0.0.1/8 u/u ::1/128 """ output_iface = self.device.send_command("show interfaces") # Collect all interfaces' name and status match = re.findall(r"(\S+)\s+[:\-\d/\.]+\s+([uAD])/([uAD])", output_iface) # 'match' example: # [("br0", "u", "D"), ("eth0", "u", "u"), ("eth1", "u", "u")...] iface_state = {iface_name: {"State": state, "Link": link} for iface_name, state, link in match} output_conf = self.device.send_command("show configuration") # Convert the configuration to dictionary config = vyattaconfparser.parse_conf(output_conf) iface_dict = dict() for iface_type in config["interfaces"]: ifaces_detail = config["interfaces"][iface_type] for iface_name in ifaces_detail: details = ifaces_detail[iface_name] description = details.get("description", "") speed = details.get("speed", "0") if speed == "auto": speed = 0 hw_id = details.get("hw-id", "00:00:00:00:00:00") is_up = (iface_state[iface_name]["Link"] == "u") is_enabled = (iface_state[iface_name]["State"] == "u") iface_dict.update({ iface_name: { "is_up": bool(is_up), "is_enabled": bool(is_enabled), "description": description, "last_flapped": float(-1), "mtu": -1, "speed": int(speed), "mac_address": hw_id, } }) return iface_dict
def pre_plan_tasks(device): # Get the full configuration, then parse it and store it in the device key/value store so providers can # retrieve it raw_commands = device.send_command('show configuration | cat') first_line_index = None last_line_index = 0 for line in raw_commands: if line.endswith('{') and not first_line_index: first_line_index = raw_commands.index(line) if line.strip() == '}': last_line_index = raw_commands.index(line, last_line_index + 1) conf_dict = vyattaconfparser.parse_conf('\n'.join( raw_commands[first_line_index:last_line_index])) device.store('configuration', conf_dict)
def test_multiple_values_with_same_key(self): s = """ service { ssh { address 0.0.0.0 { port 22 } cipher aes128-cbc cipher aes192-cbc cipher aes256-cbc hmac hmac-md5 hmac hmac-md5-96 hmac hmac-sha1 hmac hmac-sha1-96 key-exchange-algo diffie-hellman-group-exchange-sha1 key-exchange-algo diffie-hellman-group-exchange-sha256 } } """ correct = { 'service': { 'ssh': { 'address': { '0.0.0.0': { 'port': '22', } }, 'cipher': { 'aes128-cbc': {}, 'aes192-cbc': {}, 'aes256-cbc': {}, }, 'hmac': { 'hmac-md5': {}, 'hmac-md5-96': {}, 'hmac-sha1': {}, 'hmac-sha1-96': {}, }, 'key-exchange-algo': { 'diffie-hellman-group-exchange-sha1': {}, 'diffie-hellman-group-exchange-sha256': {}, } } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def test_named_section_without_curly_braces(self): s = """ vti vti10 vti vti11 { address 1.1.1.1/28 description Tunnel number 1 test_named_no_curly 1 test_named_no_curly 2 { some_key value even deeper1 even deeper2 { another_key value } } } vti vti12 { address 2.2.2.2/28 description Tunnel number 2 } """ correct = { 'vti': { 'vti10': {}, 'vti11': { 'address': '1.1.1.1/28', 'description': 'Tunnel number 1', 'test_named_no_curly': { '1': {}, '2': { 'some_key': 'value', 'even': { 'deeper1': {}, 'deeper2': { 'another_key': 'value', } } } } }, 'vti12': { 'address': '2.2.2.2/28', 'description': 'Tunnel number 2', } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def get_facts(self): output_uptime = self.device.send_command( "cat /proc/uptime | awk '{print $1}'") uptime = int(float(output_uptime)) output = self.device.send_command("show version").split("\n") ver_str = [line for line in output if "Version" in line][0] version = self.parse_version(ver_str) sn_str = [line for line in output if "S/N" in line][0] snumber = self.parse_snumber(sn_str) hwmodel_str = [line for line in output if "HW model" in line][0] hwmodel = self.parse_hwmodel(hwmodel_str) output = self.device.send_command("show configuration") config = vyattaconfparser.parse_conf(output) if "host-name" in config["system"]: hostname = config["system"]["host-name"] else: hostname = None if "domain-name" in config["system"]: fqdn = config["system"]["domain-name"] else: fqdn = "" iface_list = list() for iface_type in config["interfaces"]: for iface_name in config["interfaces"][iface_type]: iface_list.append(iface_name) facts = { "uptime": int(uptime), "vendor": py23_compat.text_type("VyOS"), "os_version": py23_compat.text_type(version), "serial_number": py23_compat.text_type(snumber), "model": py23_compat.text_type(hwmodel), "hostname": py23_compat.text_type(hostname), "fqdn": py23_compat.text_type(fqdn), "interface_list": iface_list } return facts
def test_parsing_bgp_ipv6_works(self): s = """ protocols { bgp 1 { address-family { ipv6-unicast { network 2001:2000:6000::/40 { } network 2001:2060::/32 { } } } neighbor 10.10.1.2 { remote-as 2 } network 192.168.1.0/24 { } } }""" correct = { 'protocols': { 'bgp': { '1': { 'address-family': { 'ipv6-unicast': { 'network': { '2001:2000:6000::/40': {}, '2001:2060::/32': {} } } }, 'neighbor': { '10.10.1.2': { 'remote-as': '2' } }, 'network': { '192.168.1.0/24': {} } } } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def test_basic_parse_works_a1(self, dos_line_endings=False): s = """ interfaces { ethernet eth0 { address 192.168.0.2/24 address 192.168.1.2/24 description eth0-upstream duplex auto speed auto disable } ethernet eth1 { address 192.168.2.2/24 description eth1-other duplex auto speed auto } }""" if dos_line_endings: s = s.replace('\n', '\r\n') correct = { 'interfaces': { 'ethernet': { 'eth0': { 'address': { '192.168.0.2/24': {}, '192.168.1.2/24': {} }, 'description': 'eth0-upstream', 'duplex': 'auto', 'speed': 'auto', 'disable': 'disable' }, 'eth1': { 'address': '192.168.2.2/24', 'description': 'eth1-other', 'duplex': 'auto', 'speed': 'auto' } } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def pre_plan_tasks(device): # This puts the device terminal into a configure mode device.send_command('configure') # Disable the pager so we can get the full output from long commands device.send_command('unset VYATTA_PAGER') # Get the full configuration, then parse it and store it in the device key/value store so providers can # retrieve it raw_commands = device.send_command('show') first_line_index = None last_line_index = 0 for line in raw_commands: if line.endswith('{') and not first_line_index: first_line_index = raw_commands.index(line) if line == ' }': last_line_index = raw_commands.index(line, last_line_index + 1) conf_dict = vyattaconfparser.parse_conf('\n'.join( raw_commands[first_line_index:last_line_index])) device.store('configuration', conf_dict)
def test_wireguard_syntax(self): s = """ wireguard wg0 { address 10.200.200.1/24 listen-port 60000 mtu 1420 peer XXXX= { allowed-ips 10.200.200.3/32 } peer YYYY= { allowed-ips 10.200.200.2/32 } peer ZZ+Z= { allowed-ips 10.200.200.1/32 } private-key **************** route-allowed-ips true } """ correct = { 'wireguard': { 'wg0': { 'address': '10.200.200.1/24', 'listen-port': '60000', 'mtu': '1420', 'peer': { 'XXXX=': { 'allowed-ips': '10.200.200.3/32', }, 'YYYY=': { 'allowed-ips': '10.200.200.2/32', }, 'ZZ+Z=': { 'allowed-ips': '10.200.200.1/32', } }, 'private-key': '****************', 'route-allowed-ips': 'true' } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def test_basic_parse_works_a1(self, dos_line_endings=False): s = """ interfaces { ethernet eth0 { address 192.168.0.2/24 address 192.168.1.2/24 description eth0-upstream duplex auto speed auto disable } ethernet eth1 { address 192.168.2.2/24 description eth1-other duplex auto speed auto } }""" if dos_line_endings: s = s.replace('\n', '\r\n') correct = { 'interfaces': { 'ethernet': { 'eth0': { 'address': {'192.168.0.2/24': {}, '192.168.1.2/24': {}}, 'description': 'eth0-upstream', 'duplex': 'auto', 'speed': 'auto', 'disable': 'disable' }, 'eth1': { 'address': '192.168.2.2/24', 'description': 'eth1-other', 'duplex': 'auto', 'speed': 'auto' } } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def test_nested_keys_with_same_names(self): s = """ service { dns { dynamic { interface pppoe0 { service dyndns { host-name example.com login exampleuser password **** server dyn.dns.he.net } } } } } """ correct = { 'service': { 'dns': { 'dynamic': { 'interface': { 'pppoe0': { 'service': { 'dyndns': { 'host-name': 'example.com', 'login': '******', 'password': '******', 'server': 'dyn.dns.he.net', } } }, } }, } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(correct, rv)
def test_parsing_quoted_config_vals_special_chars(self): s = """interfaces { ethernet eth0 { description "eth0-upstream #302.5-19a (temp path)" duplex auto speed auto } }""" correct = { 'interfaces': { 'ethernet': { 'eth0': { 'description': 'eth0-upstream #302.5-19a (temp path)', 'duplex': 'auto', 'speed': 'auto' } } } } rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(rv, correct)
def get_config_dict(self, ctx, resource, vyos): cache = self.get_versioned_cache(resource.id.version) if resource.device in cache: ctx.debug("Get raw config from cache") return cache[resource.device] out = vyos.configure() out = vyos.run_conf_mode_command("save /tmp/inmanta_tmp") if not ("Saving configuration to '/tmp/inmanta_tmp'" in out or "saving configuration to non-default location '/tmp/inmanta_tmp'" in out): raise SkipResource(f"Could not save config: {out}") ctx.debug("Saved config: %(out)s", out=out) out = vyos.exit() # vyos.configure() breaks unique prompt, causing config transfer to fail command = "cat /tmp/inmanta_tmp; echo 'END PRINT'" config = self._execute_command(ctx, vyos, command, "END PRINT\r\n") config = config.replace("\r", "") config = config.replace(command, "") ctx.debug("Got raw config", config=config) conf_dict = vyattaconfparser.parse_conf(config) cache[resource.device] = conf_dict return conf_dict
def test_detailed_config_parse_correctly_a1(self): s, correct = get_detailed_parse_str_dict() rv = vparser.parse_conf(s) assert isinstance(rv, dict) assert_equal(rv, correct)