diff options
author | 2019-05-28 10:19:21 +0200 | |
---|---|---|
committer | 2019-06-03 10:01:26 +0200 | |
commit | adf44f2a5eeb056c5fece0454d3e09d08df160fe (patch) | |
tree | aee220cedfccc15f59bccfae1ca7ec6b4a904809 /test | |
parent | 6dfe3074e92b3188c9fa72303f4135442cc0d5dd (diff) |
[TEST] - Initialize to use of YDK in sweetcomb test
- remove netopeer client
- use YDK
- check result, assert when error
Change-Id: Icb29dd5a35e8f7dbbeff2e44ec088b890f93b5ef
Signed-off-by: Andrej Kozemcak <andrej.kozemcak@pantheon.tech>
Diffstat (limited to 'test')
-rw-r--r-- | test/framework.py | 6 | ||||
-rw-r--r-- | test/netconf_client.py | 29 | ||||
-rw-r--r-- | test/netopeer_controler.py | 71 | ||||
-rwxr-xr-x | test/run_test.py | 12 | ||||
-rw-r--r-- | test/test_ietf_interfaces.py | 134 | ||||
-rw-r--r-- | test/test_oc_interfaces.py | 94 | ||||
-rw-r--r-- | test/topology.py | 16 | ||||
-rw-r--r-- | test/util.py | 8 | ||||
-rw-r--r-- | test/vpp_controler.py | 15 | ||||
-rw-r--r-- | test/vppctl.py | 119 |
10 files changed, 368 insertions, 136 deletions
diff --git a/test/framework.py b/test/framework.py index b308a1a..5c890dc 100644 --- a/test/framework.py +++ b/test/framework.py @@ -1,5 +1,6 @@ # # Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,6 +18,8 @@ import unittest from topology import Topology +import vppctl + class SweetcombTestCase(unittest.TestCase): @@ -34,11 +37,12 @@ class SweetcombTestCase(unittest.TestCase): cls.vpp = cls.topology.get_vpp() cls.netopeer_cli = cls.topology.get_netopeer_cli() + cls.vppctl = vppctl.Vppctl() def check_response(self, resps, expected_result, checks): assert resps[1] == expected_result - for key,val in checks.items(): + for key, val in checks.items(): for resp in resps: r = str(resp).strip() if r.find("<"+key+">") == 0: diff --git a/test/netconf_client.py b/test/netconf_client.py new file mode 100644 index 0000000..8208ce9 --- /dev/null +++ b/test/netconf_client.py @@ -0,0 +1,29 @@ +# +# Copyright (c) 2019 Cisco and/or its affiliates. +# +# Licensed 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 ydk.providers import NetconfServiceProvider + + +class NetConfClient(NetconfServiceProvider): + def __init__(self, address, username, password=None, port=830, protocol="ssh", + on_demand=True, common_cache=False, timeout=None, repo=None, private_key_path=None, public_key_path=None): + super(NetConfClient, self).__init__(address, username, password, port, + protocol, on_demand, common_cache, + timeout, repo, private_key_path, + public_key_path) + + def terminate(self): + pass diff --git a/test/netopeer_controler.py b/test/netopeer_controler.py deleted file mode 100644 index e95cbb4..0000000 --- a/test/netopeer_controler.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright (c) 2019 PANTHEON.tech. -# -# Licensed 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. -# - -import pexpect - -class Netopeer_controler: - def __init__(self): - self.name = "netopeer2-cli" - self.password = "0000" - - def __del__(self): - self.kill() - - def kill(self): - if self.child is None: - return - - self.child.sendline("exit\r") - self.child.logfile.close() - #self.child.kill() - self.child = None - - def terminate(self): - self.kill() - - def set_password(self, password): - self.password = password; - - def spawn(self): - self.child = pexpect.spawn(self.name) - self.child.logfile = open('/var/log/Netopeer_controler.log', 'wb') - self.child.setwinsize(1,1024) - self.pid = self.child.pid - self.child.expect(">") - self.child.sendline("connect\r") - i = self.child.expect(["Password:", "Are you sure you want to continue connecting (yes/no)?"]) - if 0 == i: - self.child.sendline(self.password + '\r') - elif 1 == i: - self.child.sendline("yes\r") - self.child.expect("Password:") - self.child.sendline(self.password + '\r') - - self.child.expect(">") - - def get(self, msg): - self.child.sendline("get --filter-xpath {}\r".format(msg)) - self.child.expect("> ") - return self.child.before.decode('ascii') - - def edit_config(self, msg): - f = open("/tmp/tmp_example.xml", "w") - f.write(msg) - f.close() - - self.child.sendline("edit-config --target running --config=/tmp/tmp_example.xml\r") - self.child.expect("> ") - return self.child.before.decode('ascii') diff --git a/test/run_test.py b/test/run_test.py index e3190c4..a4cce6d 100755 --- a/test/run_test.py +++ b/test/run_test.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # # Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,15 +20,20 @@ import unittest import util -from framewrok import SweetcombTestCase +from framework import SweetcombTestCase from test_ietf_interfaces import TestIetfInterfaces +from test_oc_interfaces import TestOcInterfaces + def suite(): suite = unittest.TestSuite() - suite.addTest(TestIetfInterfaces('test_interface_up')) - suite.addTest(TestIetfInterfaces('test_ip_addr')) + suite.addTest(TestIetfInterfaces('test_ipv4')) + suite.addTest(TestIetfInterfaces('test_interface')) + suite.addTest(TestOcInterfaces('test_interface')) + suite.addTest(TestOcInterfaces('test_interface_ipv4')) return suite + if __name__ == '__main__': util.import_yang_modules() runner = unittest.TextTestRunner() diff --git a/test/test_ietf_interfaces.py b/test/test_ietf_interfaces.py index 2b421d3..3b08859 100644 --- a/test/test_ietf_interfaces.py +++ b/test/test_ietf_interfaces.py @@ -1,11 +1,12 @@ # # Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. # # Licensed 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 +# 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, @@ -18,6 +19,11 @@ import unittest import util from framework import SweetcombTestCase +from ydk.models.ietf import ietf_interfaces +from ydk.models.ietf import iana_if_type +from ydk.services import CRUDService +from ydk.errors import YError + class TestIetfInterfaces(SweetcombTestCase): @@ -31,50 +37,82 @@ class TestIetfInterfaces(SweetcombTestCase): self.topology.close_topology() - def test_interface_up(self): - - self.vpp.show_interface() - - self.netopeer_cli.get("/ietf-interfaces:*") - ts = '''<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"> - <interface> - <name>local0</name> - <enabled>true</enabled> - </interface> - <interface> - <name>host-vpp1</name> - <enabled>true</enabled> - </interface> -</interfaces>''' - - self.netopeer_cli.edit_config(ts) - self.netopeer_cli.get("/ietf-interfaces:*") - - self.vpp.show_interface() - - def test_ip_addr(self): - self.vpp.show_address() - self.netopeer_cli.get("/ietf-interfaces:*") - - util.ping('192.168.0.1') - - ts = '''<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\" xmlns:ip=\"urn:ietf:params:xml:ns:yang:ietf-ip\"> - <interface> - <name>host-vpp1</name> - <enabled>true</enabled> - <ip:ipv4> - <ip:enabled>true</ip:enabled> - <ip:address> - <ip:ip>192.168.0.1</ip:ip> - <ip:prefix-length>24</ip:prefix-length> - </ip:address> - </ip:ipv4> - </interface> -</interfaces>''' - - self.netopeer_cli.edit_config(ts) - self.netopeer_cli.get("/ietf-interfaces:*") - - self.vpp.show_address() - - util.ping('192.168.0.1') + def test_interface(self): + name = "host-vpp1" + crud_service = CRUDService() + + interface = ietf_interfaces.Interfaces.Interface() + interface.name = name + interface.type = iana_if_type.EthernetCsmacd() + interface.enabled = True + interface.ipv4 = interface.Ipv4() + interface.ipv4.mtu = 1500 + + try: + crud_service.create(self.netopeer_cli, interface) + except YError as err: + print("Error create services: {}".format(err)) + assert() + + p = self.vppctl.show_interface(name) + self.assertIsNotNone(p) + + self.assertEquals(interface.enabled, p.State) + #FIXME: MTU assert + #self.assertEquals(interface.ipv4.mtu, p.MTU) + + interface.enabled = False + + try: + crud_service.create(self.netopeer_cli, interface) + except YError as err: + print("Error create services: {}".format(err)) + assert() + + p = self.vppctl.show_interface(name) + self.assertIsNotNone(p) + self.assertEquals(interface.enabled, p.State) + + def test_ipv4(self): + name = "host-vpp1" + crud_service = CRUDService() + + interface = ietf_interfaces.Interfaces.Interface() + interface.name = name + interface.type = iana_if_type.EthernetCsmacd() + interface.ipv4 = interface.Ipv4() + addr = interface.Ipv4().Address() + addr.ip = "192.168.0.1" + addr.prefix_length = 24 + interface.ipv4.address.append(addr) + addr1 = interface.Ipv4().Address() + addr1.ip = "142.168.0.1" + addr1.prefix_length = 14 + interface.ipv4.address.append(addr1) + + try: + crud_service.create(self.netopeer_cli, interface) + except YError as err: + print("Error create services: {}".format(err)) + assert() + + a = self.vppctl.show_address(name) + self.assertIsNotNone(a) + + prefix = interface.ipv4.address[0].ip + "/" + \ + str(interface.ipv4.address[0].prefix_length) + self.assertIn(prefix, a.addr) + + prefix = interface.ipv4.address[1].ip + "/" + \ + str(interface.ipv4.address[1].prefix_length) + self.assertIn(prefix, a.addr) + + try: + crud_service.delete(self.netopeer_cli, interface) + except YError as err: + print("Error create services: {}".format(err)) + assert() + + a = self.vppctl.show_address(name) + + self.assertIsNone(a) diff --git a/test/test_oc_interfaces.py b/test/test_oc_interfaces.py new file mode 100644 index 0000000..3b94945 --- /dev/null +++ b/test/test_oc_interfaces.py @@ -0,0 +1,94 @@ +# +# Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. +# +# Licensed 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. +# + +import unittest + +import util +from framework import SweetcombTestCase +from ydk.models.openconfig import openconfig_interfaces +from ydk.models.ietf import iana_if_type +from ydk.services import CRUDService +from ydk.errors import YError + + +class TestOcInterfaces(SweetcombTestCase): + cleanup = False + + def setUp(self): + super(TestOcInterfaces, self).setUp() + self.create_topology() + + def tearDown(self): + super(TestOcInterfaces, self).setUp() + + self.topology.close_topology() + + def test_interface(self): + name = "host-vpp1" + crud_service = CRUDService() + + interface = openconfig_interfaces.Interfaces.Interface() + interface.name = name + interface.config.type = iana_if_type.EthernetCsmacd() + interface.config.enabled = True + + try: + crud_service.create(self.netopeer_cli, interface) + except YError: + print("Error create services") + + p = self.vppctl.show_interface(name) + self.assertIsNotNone(p) + self.assertEquals(interface.config.enabled, p.State) + + interface.config.enabled = False + + try: + crud_service.create(self.netopeer_cli, interface) + except YError as err: + print("Error create services: {}".format(err)) + + p = self.vppctl.show_interface(name) + self.assertIsNotNone(p) + self.assertEquals(interface.config.enabled, p.State) + + @unittest.skip("YDK return error when try set IP address") + def test_interface_ipv4(self): + name = "host-vpp1" + crud_service = CRUDService() + + interface = openconfig_interfaces.Interfaces.Interface() + interface.name = name + subinterface = interface.Subinterfaces.Subinterface() + + addr = subinterface.ipv4.addresses.Address() + addr.ip = "10.0.0.2" + addr.config = addr.Config() + # FIXME It return error, why ?????????????????????? + addr.config.ip = "10.0.0.2" + addr.config.prefix_length = 24 + subinterface.index = 0 + subinterface.ipv4.addresses.address.append(addr) + interface.subinterfaces.subinterface.append(subinterface) + + try: + crud_service.create(self.netopeer_cli, interface) + except YError as err: + print("Error create services: {}".format(err)) + assert() + + a = self.vppctl.show_address(name) diff --git a/test/topology.py b/test/topology.py index 617601b..a8a2f15 100644 --- a/test/topology.py +++ b/test/topology.py @@ -1,5 +1,6 @@ # # Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,12 +17,13 @@ import os import subprocess -from netopeer_controler import Netopeer_controler from vpp_controler import Vpp_controler +from netconf_client import NetConfClient from socket import AF_INET from pyroute2 import IPRoute import psutil import time +from ydk.providers import NetconfServiceProvider class Topology: debug = False @@ -109,11 +111,18 @@ class Topology: self.vpp.spawn() self.process.append(self.vpp) + def _start_netconfclient(self): + print("Start NetconfClient") + self.netconf_client = NetConfClient(address="127.0.0.1", + username="root", password="0000") + self.process.append(self.netconf_client) + def get_vpp(self): return self.vpp def get_netopeer_cli(self): - return self.netopeer_cli + #return self.netopeer_cli + return self.netconf_client def create_topology(self, debug=False): #try: @@ -127,7 +136,8 @@ class Topology: #Wait for netopeer server time.sleep(1) - self._start_netopeer_cli() + #self._start_netopeer_cli() + self._start_netconfclient() #except: #self._kill_process() diff --git a/test/util.py b/test/util.py index c31439d..576bc43 100644 --- a/test/util.py +++ b/test/util.py @@ -1,5 +1,6 @@ # # Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,13 +19,16 @@ import subprocess import os import time + def ping(ip): subprocess.run("ping -c 4 " + ip, shell=True) + def import_yang_modules(): print("Import YANG models to sysrepo.") - directory = '/root/src/sweetcomb/' + #directory = '/root/src/sweetcomb/' + directory = './' os.chdir(directory) subprocess.run(["make", "uninstall-models"]) subprocess.run(["make", "install-models"]) @@ -38,4 +42,4 @@ def import_yang_modules(): "--datastore=running", "--format=xml", "--leve=0", "ietf-interfaces"]) os.chdir(directory) - time.sleep(2)
\ No newline at end of file + time.sleep(2) diff --git a/test/vpp_controler.py b/test/vpp_controler.py index e764e9b..32d6d70 100644 --- a/test/vpp_controler.py +++ b/test/vpp_controler.py @@ -1,5 +1,6 @@ # # Copyright (c) 2019 PANTHEON.tech. +# Copyright (c) 2019 Cisco and/or its affiliates. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,6 +18,8 @@ import subprocess import time import psutil +import os + class Vpp_controler: debug = False @@ -24,7 +27,8 @@ class Vpp_controler: def __init__(self, debug=False): self.cmd = "vpp" self.ccmd = "vppctl" - self.configuration = "/root/src/sweetcomb/test/conf/vpp.conf" + self.rootPath = os.getcwd() + self.configuration = self.rootPath + "/vpp.conf" self.process = None self.debug = debug @@ -41,7 +45,8 @@ class Vpp_controler: def spawn(self): self.process = subprocess.Popen([self.cmd, "-c", self.configuration], - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) time.sleep(4) self._default_conf_vpp() @@ -64,9 +69,3 @@ class Vpp_controler: proc.kill() self.process = None - - def show_interface(self): - subprocess.run(self.ccmd + " show int", shell=True) - - def show_address(self): - subprocess.run(self.ccmd + " show int addr", shell=True) diff --git a/test/vppctl.py b/test/vppctl.py new file mode 100644 index 0000000..1f5cc99 --- /dev/null +++ b/test/vppctl.py @@ -0,0 +1,119 @@ +# +# Copyright (c) 2019 Cisco and/or its affiliates. +# +# Licensed 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. +# + +import subprocess +import re + + +class VppInterface: + def __init__(self, str): + self.str = str + self.name = None + self.Idx = None + self.State = None + self.MTU = None + self.Counter = None + self.Count = None + self._parse() + + def _parse(self): + columns = re.split('\s+', self.str) + j = 0 + for column in columns: + j += 1 + if 1 == j: + self.name = column + elif 2 == j: + self.Idx = column + elif 3 == j: + if 'up' == column: + self.State = True + elif 'down' == column: + self.State = False + elif 4 == j: + self.MTU = column.split("/")[0] + elif 5 == j: + self.Counter = column + elif 6 == j: + self.Count = column + + +class VppIpv4Address: + def __init__(self, name): + self.name = name + self.str = str + self.addr = list() + + def addAddress(self, str): + tmp = re.split('\s+', str) + self.addr.append(tmp[2]) + + +class Vppctl: + def __init__(self): + self.cmd = "vppctl" + + def show_interface(self, name=None): + interfaces = list() + p = subprocess.run(self.cmd + " show int", shell=True, + stdout=subprocess.PIPE) + str = p.stdout.decode("utf-8") + lines = str.split("\n") + i = 0 + for line in lines: + i += 1 + if 1 == i: + continue + + interfaces.append(VppInterface(line)) + + if name is None: + return interfaces + else: + for intf in interfaces: + if intf.name == name: + return intf + + return None + + def show_address(self, ifName=None): + interfaces = dict() + p = subprocess.run(self.cmd + " show int addr", shell=True, + stdout=subprocess.PIPE) + str = p.stdout.decode("utf-8") + lines = str.split("\n") + for line in lines: + if re.match('^\s+', line) is None: + tmp = line.split(" ") + name = tmp[0] + else: + if name is None: + continue + + if name in interfaces: + interface = interfaces[name] + else: + interface = VppIpv4Address(name) + interfaces[name] = interface + + interface.addAddress(line) + + if ifName is None: + return interfaces + elif ifName in interfaces: + return interfaces[ifName] + else: + return None |