blob: 97c93c533dae9d837c9c262e53b15579dba6a2b3 [file] [log] [blame]
Matteo Scandolo6739b512018-05-30 18:55:29 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import unittest
Matteo Scandolodb7adc32018-06-15 16:05:19 -070016import urllib
Matteo Scandolo6739b512018-05-30 18:55:29 -070017import functools
18from mock import patch, call, Mock, PropertyMock
19import requests_mock
20import multistructlog
21from multistructlog import create_logger
22
23import os, sys
24
Matteo Scandolo6739b512018-05-30 18:55:29 -070025test_path=os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
Matteo Scandolo6739b512018-05-30 18:55:29 -070026
27def match_json(desired, req):
28 if desired!=req.json():
29 raise Exception("Got request %s, but body is not matching" % req.url)
30 return False
31 return True
32
33class TestSyncFabricPort(unittest.TestCase):
34
35 def setUp(self):
36 global DeferredException
37
38 self.sys_path_save = sys.path
Matteo Scandolo6739b512018-05-30 18:55:29 -070039
40 # Setting up the config module
41 from xosconfig import Config
42 config = os.path.join(test_path, "../test_config.yaml")
43 Config.clear()
44 Config.init(config, "synchronizer-config-schema.yaml")
45 # END Setting up the config module
46
Scott Baker382366d2019-02-04 10:58:43 -080047 from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
48 mock_modelaccessor_config(test_path, [("fabric", "fabric.xproto")])
Matteo Scandolo6739b512018-05-30 18:55:29 -070049
Scott Baker382366d2019-02-04 10:58:43 -080050 import xossynchronizer.modelaccessor
51 import mock_modelaccessor
52 reload(mock_modelaccessor) # in case nose2 loaded it in a previous test
53 reload(xossynchronizer.modelaccessor) # in case nose2 loaded it in a previous test
54
55 from xossynchronizer.modelaccessor import model_accessor
56 self.model_accessor = model_accessor
57
58 from sync_fabric_port import SyncFabricPort
Matteo Scandolo6739b512018-05-30 18:55:29 -070059
60 # import all class names to globals
61 for (k, v) in model_accessor.all_model_classes.items():
62 globals()[k] = v
63
Matteo Scandolo6739b512018-05-30 18:55:29 -070064 self.sync_step = SyncFabricPort
65 self.sync_step.log = Mock()
66
Matteo Scandolo6739b512018-05-30 18:55:29 -070067 # mock onos-fabric
68 onos_fabric = Mock()
69 onos_fabric.name = "onos-fabric"
70 onos_fabric.rest_hostname = "onos-fabric"
71 onos_fabric.rest_port = "8181"
72 onos_fabric.rest_username = "onos"
73 onos_fabric.rest_password = "rocks"
74
75 onos_fabric_base = Mock()
76 onos_fabric_base.leaf_model = onos_fabric
77
78 self.fabric = Mock()
79 self.fabric.name = "fabric"
Scott Bakerafdf11d2018-08-16 15:47:55 -070080 self.fabric.provider_services = [onos_fabric_base]
Matteo Scandolo6739b512018-05-30 18:55:29 -070081
Matteo Scandolo6739b512018-05-30 18:55:29 -070082 def tearDown(self):
Matteo Scandolo6739b512018-05-30 18:55:29 -070083 sys.path = self.sys_path_save
84
85 @requests_mock.Mocker()
86 def test_sync_port(self, m):
Luca Prete15377872018-09-11 17:32:55 -070087 # IPs
88 ip1 = Mock()
89 ip1.ip = "1.1.1.1/16"
90 ip1.description = "My IPv4 ip"
91 ip2 = Mock()
92 ip2.ip = "2001:0db8:85a3:0000:0000:8a2e:0370:7334/64"
93 ip2.description = "My IPv6 ip"
94 ip3 = Mock()
95 ip3.ip = "2.2.2.2/8"
96 ip3.description = "My other IPv4 ip"
97
Matteo Scandolo6739b512018-05-30 18:55:29 -070098 intf1 = Mock()
99 intf1.name = "intf1"
Matteo Scandolo6739b512018-05-30 18:55:29 -0700100 intf1.vlanUntagged = None
Luca Prete15377872018-09-11 17:32:55 -0700101 intf1.ips.all.return_value = [ip1, ip2]
102 intf2 = Mock()
103 intf2.name = "intf2"
104 intf2.vlanUntagged = 42
105 intf2.ips.all.return_value = [ip3]
Matteo Scandolo6739b512018-05-30 18:55:29 -0700106
Luca Prete15377872018-09-11 17:32:55 -0700107 port = Mock()
108 port.id = 1
109 port.tologdict.return_value = {}
110 port.host_learning = True
111 port.interfaces.all.return_value = [intf1, intf2]
112 port.switch.ofId = "of:1234"
113 port.portId = "1"
Matteo Scandolo6739b512018-05-30 18:55:29 -0700114
115 expected_conf = {
116 "ports": {
Luca Prete15377872018-09-11 17:32:55 -0700117 "%s/%s" % (port.switch.ofId, port.portId): {
Matteo Scandolo6739b512018-05-30 18:55:29 -0700118 "interfaces": [
119 {
120 "name": intf1.name,
Luca Prete15377872018-09-11 17:32:55 -0700121 "ips": [ ip1.ip, ip2.ip ]
122 },
123 {
124 "name": intf2.name,
125 "ips": [ip3.ip],
126 "vlan-untagged": intf2.vlanUntagged
Matteo Scandolo6739b512018-05-30 18:55:29 -0700127 }
Matteo Scandolodfe75ff2018-06-15 10:52:09 -0700128 ],
129 "hostLearning": {
Luca Prete15377872018-09-11 17:32:55 -0700130 "enabled": port.host_learning
Matteo Scandolodfe75ff2018-06-15 10:52:09 -0700131 }
Matteo Scandolo6739b512018-05-30 18:55:29 -0700132 }
133 }
134 }
135
136 m.post("http://onos-fabric:8181/onos/v1/network/configuration/",
137 status_code=200,
138 additional_matcher=functools.partial(match_json, expected_conf))
139
140 with patch.object(Service.objects, "get") as onos_fabric_get:
141 onos_fabric_get.return_value = self.fabric
Scott Baker382366d2019-02-04 10:58:43 -0800142 self.sync_step(model_accessor=self.model_accessor).sync_record(port)
Matteo Scandolo6739b512018-05-30 18:55:29 -0700143 self.assertTrue(m.called)
144
145 @requests_mock.Mocker()
146 def test_delete_port(self, m):
Luca Prete15377872018-09-11 17:32:55 -0700147 # create a mock SwitchPort instance
148 port = Mock()
149 port.id = 1
150 port.tologdict.return_value = {}
151 port.host_learning = True
152 port.switch.ofId = "of:1234"
153 port.portId = "1"
Matteo Scandolo6739b512018-05-30 18:55:29 -0700154
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700155 key = urllib.quote("of:1234/1", safe='')
Matteo Scandolodb7adc32018-06-15 16:05:19 -0700156 m.delete("http://onos-fabric:8181/onos/v1/network/configuration/ports/%s" % key,
157 status_code=204)
158
Matteo Scandolo6739b512018-05-30 18:55:29 -0700159 with patch.object(Service.objects, "get") as onos_fabric_get:
160 onos_fabric_get.return_value = self.fabric
Scott Baker382366d2019-02-04 10:58:43 -0800161 self.sync_step(model_accessor=self.model_accessor).delete_record(port)
Luca Prete15377872018-09-11 17:32:55 -0700162 self.assertTrue(m.called)
Matteo Scandolo6739b512018-05-30 18:55:29 -0700163
Luca Prete15377872018-09-11 17:32:55 -0700164 @requests_mock.Mocker()
165 def test_delete_interface(self, m):
166 ip1 = Mock()
167 ip1.ip = "1.1.1.1/16"
168 ip1.description = "My IPv4 ip"
169 ip2 = Mock()
170 ip2.ip = "2001:0db8:85a3:0000:0000:8a2e:0370:7334/64"
171 ip2.description = "My IPv6 ip"
Matteo Scandolo6739b512018-05-30 18:55:29 -0700172
Luca Prete15377872018-09-11 17:32:55 -0700173 # interfaces
174 intf1 = Mock()
175 intf1.name = "intf1"
176 intf1.vlanUntagged = None
177 intf1.ips.all.return_value = [ip1, ip2]
178
179 # bindings
180 # create a mock SwitchPort instance
181 interface_to_remove = Mock()
182 interface_to_remove.id = 1
183 interface_to_remove.tologdict.return_value = {}
184 interface_to_remove.leaf_model_name = "PortInterface"
185 interface_to_remove.port.interfaces.all.return_value = [intf1]
186 interface_to_remove.port.switch.ofId = "of:1234"
187 interface_to_remove.port.portId = "1"
188 interface_to_remove.port.host_learning = True
189
190 m.post("http://onos-fabric:8181/onos/v1/network/configuration/", status_code=200)
191
192 with patch.object(Service.objects, "get") as onos_fabric_get:
193 onos_fabric_get.return_value = self.fabric
Scott Baker382366d2019-02-04 10:58:43 -0800194 self.sync_step(model_accessor=self.model_accessor).delete_record(interface_to_remove)
Luca Prete15377872018-09-11 17:32:55 -0700195 self.assertTrue(m.called)
196
197 @requests_mock.Mocker()
198 def test_delete_ip(self, m):
199 ip1 = Mock()
200 ip1.ip = "1.1.1.1/16"
201 ip1.description = "My IPv4 ip"
202
203 intf1 = Mock()
204 intf1.name = "intf1"
205 intf1.vlanUntagged = None
206 intf1.ips.all.return_value = [ip1]
207
208 ip_to_remove = Mock()
209 ip_to_remove.id = 1
210 ip_to_remove.leaf_model_name = "FabricIpAddress"
211 ip_to_remove.interface.port.interfaces.all.return_value = [intf1]
212 ip_to_remove.interface.port.switch.ofId = "of:1234"
213 ip_to_remove.interface.port.portId = "1"
214 ip_to_remove.interface.port.host_learning = True
215
216 m.post("http://onos-fabric:8181/onos/v1/network/configuration/", status_code=200)
217
218 with patch.object(Service.objects, "get") as onos_fabric_get:
219 onos_fabric_get.return_value = self.fabric
Scott Baker382366d2019-02-04 10:58:43 -0800220 self.sync_step(model_accessor=self.model_accessor).delete_record(ip_to_remove)
Scott Bakerafdf11d2018-08-16 15:47:55 -0700221 self.assertTrue(m.called)
Scott Baker382366d2019-02-04 10:58:43 -0800222
223if __name__ == '__main__':
224 unittest.main()