aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorAndrej Kozemcak <andrej.kozemcak@pantheon.tech>2019-05-28 10:19:21 +0200
committerAndrej Kozemcak <andrej.kozemcak@pantheon.tech>2019-06-03 10:01:26 +0200
commitadf44f2a5eeb056c5fece0454d3e09d08df160fe (patch)
treeaee220cedfccc15f59bccfae1ca7ec6b4a904809 /test
parent6dfe3074e92b3188c9fa72303f4135442cc0d5dd (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.py6
-rw-r--r--test/netconf_client.py29
-rw-r--r--test/netopeer_controler.py71
-rwxr-xr-xtest/run_test.py12
-rw-r--r--test/test_ietf_interfaces.py134
-rw-r--r--test/test_oc_interfaces.py94
-rw-r--r--test/topology.py16
-rw-r--r--test/util.py8
-rw-r--r--test/vpp_controler.py15
-rw-r--r--test/vppctl.py119
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