blob: 68c3b61e2397c7a1b1d1537ebd18b9b636325930 [file] [log] [blame]
Matteo Scandolo517962f2018-05-01 09:42:04 -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 functools
16import unittest
17from mock import patch, call, Mock, PropertyMock
18import requests_mock
19
20import os, sys
21
Matteo Scandolo517962f2018-05-01 09:42:04 -070022test_path=os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
Matteo Scandolo517962f2018-05-01 09:42:04 -070023
24def match_json(desired, req):
25 if desired!=req.json():
26 print >> sys.stderr, "mismatch: '%s' != '%s'" % (desired, req.json())
27 return False
28 return True
29
Matteo Scandolo517962f2018-05-01 09:42:04 -070030class TestSyncAddressManagerServiceInstance(unittest.TestCase):
31
32 def setUp(self):
33 global MockObjectList, model_accessor, SyncStep
34
35 self.sys_path_save = sys.path
Matteo Scandolo517962f2018-05-01 09:42:04 -070036
37 # Setting up the config module
38 from xosconfig import Config
39 config = os.path.join(test_path, "test_config.yaml")
40 Config.clear()
41 Config.init(config, "synchronizer-config-schema.yaml")
42 # END Setting up the config module
43
Scott Bakerec4d9e42019-02-04 16:40:38 -080044 from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
45 mock_modelaccessor_config(test_path, [("fabric", "fabric.xproto"),
46 ("addressmanager", "addressmanager.xproto"),
47 ("onos-service", "onos.xproto")])
Matteo Scandolo517962f2018-05-01 09:42:04 -070048
Scott Bakerec4d9e42019-02-04 16:40:38 -080049 import xossynchronizer.modelaccessor
50 import mock_modelaccessor
51 reload(mock_modelaccessor) # in case nose2 loaded it in a previous test
52 reload(xossynchronizer.modelaccessor) # in case nose2 loaded it in a previous test
53
54 from sync_addressmanagerserviceinstance import SyncAddressManagerServiceInstance, model_accessor, SyncStep
Matteo Scandolo517962f2018-05-01 09:42:04 -070055 from mock_modelaccessor import MockObjectList
56
Scott Bakerec4d9e42019-02-04 16:40:38 -080057 self.sync_step = SyncAddressManagerServiceInstance(model_accessor = model_accessor)
Matteo Scandolo517962f2018-05-01 09:42:04 -070058
59 # import all class names to globals
60 for (k, v) in model_accessor.all_model_classes.items():
61 globals()[k] = v
62
63 # Some of the functions we call have side-effects. For example, creating a VSGServiceInstance may lead to creation of
64 # tags. Ideally, this wouldn't happen, but it does. So make sure we reset the world.
65 model_accessor.reset_all_object_stores()
66
67 # TODO: this should be addressed in the mock model accessor
68 model_accessor.get_content_type_id = lambda x: x.self_content_type_id
69
70 AddressManagerServiceInstance.get_attribute = None
71
72 self.service = FabricService()
73 self.onos_service = ONOSService(rest_hostname = "fabric_host", rest_port=1234)
74 self.onos_app = ONOSApp(owner = self.onos_service)
75
76 self.onos_dependency = ServiceDependency(subscriber_service = self.service,
77 provider_service_instance = self.onos_app)
78 self.onos_service.provideded_links = MockObjectList(initial = [self.onos_dependency])
79 self.service.subscribed_links = MockObjectList(initial = [self.onos_dependency])
80
81 self.amsi_service_instance = AddressManagerServiceInstance(public_ip = "1.2.3.4",
82 public_mac="11:22:33:44:55:66",
83 provided_links = MockObjectList())
84 self.amsi_inst = AddressManagerServiceInstance(public_ip = "5.6.7.8",
85 public_mac="55:66:77:88:99:00",
86 provided_links = MockObjectList())
87
88 def tearDown(self):
89 sys.path = self.sys_path_save
90
91 def test_get_fabric_onos_service_internal(self):
92 with patch.object(FabricService.objects, "get_items") as fabricservice_objects:
93 fabricservice_objects.return_value =[self.service]
94
95 osi = self.sync_step.get_fabric_onos_service_internal()
96 self.assertEqual(osi, self.onos_service)
97
98 def test_get_fabric_onos_service_internal_nolinks(self):
99 with patch.object(FabricService.objects, "get_items") as fabricservice_objects:
100 fabricservice_objects.return_value =[self.service]
101
102 self.service.subscribed_links = MockObjectList(initial=[])
103
104 osi = self.sync_step.get_fabric_onos_service_internal()
105 self.assertEqual(osi, None)
106
107 def test_get_fabric_onos_service(self):
108 with patch.object(FabricService.objects, "get_items") as fabricservice_objects:
109 fabricservice_objects.return_value =[self.service]
110
111 osi = self.sync_step.get_fabric_onos_service()
112 self.assertEqual(osi, self.onos_service)
113
114 def test_get_fabric_onos_service_nolinks(self):
115 with patch.object(FabricService.objects, "get_items") as fabricservice_objects:
116 fabricservice_objects.return_value =[self.service]
117
118 self.service.subscribed_links = MockObjectList(initial=[])
119
120 with self.assertRaises(Exception) as e:
121 osi = self.sync_step.get_fabric_onos_service()
122
123 self.assertEqual(e.exception.message, "Fabric ONOS service not found")
124
125 def test_get_node_tag(self):
126 with patch.object(Tag.objects, "get_items") as tag_objects:
127 node = Node(id=6745)
128 tag = Tag(content_type = model_accessor.get_content_type_id(node),
129 object_id = node.id,
130 name="foo",
131 value="bar")
132 tag_objects.return_value = [tag]
133
134 self.assertEqual(self.sync_step.get_node_tag(node, "foo"), "bar")
135
136 def test_fetch_pending(self):
137 with patch.object(FabricService.objects, "get_items") as fabricservice_objects, \
138 patch.object(AddressManagerServiceInstance, "get_attribute") as get_attribute, \
139 patch.object(Instance.objects, "get_items") as instance_objects, \
140 patch.object(SyncStep, "fetch_pending") as syncstep_fetch_pending:
141 fabricservice_objects.return_value =[self.service]
142
143 node = Node(dataPlaneIp = "11.22.33.44")
144 instance1 = Instance(id=3445, node=node, instance_name="instance1")
145 instance2 = Instance(id=3446, node=node, instance_name="instance2")
146 instance_objects.return_value = [instance1, instance2]
147
148 # for self.amsi_inst...
149 get_attribute.return_value = instance1.id
150
151 # for self.amsi_service_instance...
152 some_service_instance = ServiceInstance(instance=instance2)
153 some_link = ServiceInstanceLink(subscriber_service_instance=some_service_instance, provider_service_instance=self.amsi_service_instance)
154 some_service_instance.subscribed_links = MockObjectList(initial=[some_link])
155 self.amsi_service_instance.provided_links = MockObjectList(initial=[some_link])
156
157 syncstep_fetch_pending.return_value = [self.amsi_inst, self.amsi_service_instance]
158
159 objs = self.sync_step.fetch_pending(deleted = False)
160 self.assertEqual(len(objs), 2)
161
162 def test_fetch_pending_no_attribute(self):
163 with patch.object(FabricService.objects, "get_items") as fabricservice_objects, \
164 patch.object(AddressManagerServiceInstance, "get_attribute") as get_attribute, \
165 patch.object(Instance.objects, "get_items") as instance_objects, \
166 patch.object(SyncStep, "fetch_pending") as syncstep_fetch_pending:
167 fabricservice_objects.return_value = [self.service]
168 syncstep_fetch_pending.return_value = [self.amsi_inst, self.amsi_service_instance]
169
170 node = Node(dataPlaneIp="11.22.33.44")
171 instance2 = Instance(id=3446, node=node, instance_name="instance1")
172 instance_objects.return_value = [instance2]
173
174 # for self.amsi_inst, see that it has no instance
175 get_attribute.return_value = None
176
177 # for self.amsi_service_instance...
178 some_service_instance = ServiceInstance(instance=instance2)
179 some_link = ServiceInstanceLink(subscriber_service_instance=some_service_instance,
180 provider_service_instance=self.amsi_service_instance)
181 some_service_instance.subscribed_links = MockObjectList(initial=[some_link])
182 self.amsi_service_instance.provided_links = MockObjectList(initial=[some_link])
183
184 objs = self.sync_step.fetch_pending(deleted=False)
185
186 self.assertEqual(len(objs), 1)
187
188 def test_fetch_pending_no_subscriber_instance(self):
189 with patch.object(FabricService.objects, "get_items") as fabricservice_objects, \
190 patch.object(AddressManagerServiceInstance, "get_attribute") as get_attribute, \
191 patch.object(Instance.objects, "get_items") as instance_objects, \
192 patch.object(SyncStep, "fetch_pending") as syncstep_fetch_pending:
193 fabricservice_objects.return_value =[self.service]
194
195 node = Node(dataPlaneIp = "11.22.33.44")
196 instance1 = Instance(id=3445, node=node, instance_name="instance1")
197 instance_objects.return_value = [instance1]
198
199 # for self.amsi_inst...
200 get_attribute.return_value = instance1.id
201
202 # for self.amsi_service_instance...
203 some_service_instance = ServiceInstance(instance=None)
204 some_link = ServiceInstanceLink(subscriber_service_instance=some_service_instance, provider_service_instance=self.amsi_service_instance)
205 some_service_instance.subscribed_links = MockObjectList(initial=[some_link])
206 self.amsi_service_instance.provided_links = MockObjectList(initial=[some_link])
207
208 syncstep_fetch_pending.return_value = [self.amsi_inst, self.amsi_service_instance]
209
210 objs = self.sync_step.fetch_pending(deleted = False)
211 self.assertEqual(len(objs), 1)
212
213 @requests_mock.Mocker()
214 def test_sync_record_instance(self, m):
215 with patch.object(FabricService.objects, "get_items") as fabricservice_objects, \
216 patch.object(AddressManagerServiceInstance, "get_attribute") as get_attribute, \
217 patch.object(Instance.objects, "get_items") as instance_objects:
218 fabricservice_objects.return_value = [self.service]
219
220 node = Node(dataPlaneIp = "11.22.33.44")
221 instance = Instance(id=3445, node=node)
222 instance_objects.return_value = [instance]
223
224 get_attribute.return_value = instance.id
225
226 m.post("http://fabric_host:1234/onos/routeservice/routes",
227 status_code=200,
228 additional_matcher=functools.partial(match_json,{u'prefix': u'5.6.7.8/32', u'nextHop': u'11.22.33.44'}))
229
230 self.sync_step.sync_record(self.amsi_inst)
231
232 @requests_mock.Mocker()
233 def test_sync_record_service_instance(self, m):
234 with patch.object(FabricService.objects, "get_items") as fabricservice_objects, \
235 patch.object(Instance.objects, "get_items") as instance_objects:
236 fabricservice_objects.return_value = [self.service]
237
238 node = Node(dataPlaneIp = "55.66.77.88")
239 instance = Instance(id=5443, node=node)
240 instance_objects.return_value = [instance]
241
242 some_service_instance = ServiceInstance(instance=instance)
243 some_link = ServiceInstanceLink(subscriber_service_instance=some_service_instance, provider_service_instance=self.amsi_service_instance)
244 some_service_instance.subscribed_links = MockObjectList(initial=[some_link])
245 self.amsi_service_instance.provided_links = MockObjectList(initial=[some_link])
246
247 m.post("http://fabric_host:1234/onos/routeservice/routes",
248 status_code=200,
249 additional_matcher=functools.partial(match_json,{u'prefix': u'1.2.3.4/32', u'nextHop': u'55.66.77.88'}))
250
251 self.sync_step.sync_record(self.amsi_service_instance)
252
253 def test_get_subscriber(self):
254 some_service_instance = ServiceInstance()
255 some_link = ServiceInstanceLink(subscriber_service_instance=some_service_instance,
256 provider_service_instance=self.amsi_service_instance)
257 some_service_instance.subscribed_links = MockObjectList(initial=[some_link])
258 self.amsi_service_instance.provided_links = MockObjectList(initial=[some_link])
259
260 self.assertEqual(self.sync_step.get_subscriber(self.amsi_service_instance), some_service_instance)
261
262 def test_get_routes_url(self):
263 url = self.sync_step.get_routes_url(self.onos_service)
264 self.assertEqual(url, "http://fabric_host:1234/onos/routeservice/routes")
265
266 @requests_mock.Mocker()
267 def test_delete_route(self, m):
268 m.delete("http://fabric_host:1234/onos/routeservice/routes",
269 status_code=200,
270 additional_matcher=functools.partial(match_json,{u'prefix': u'5.6.7.8/32', u'nextHop': u'55.66.77.88'}))
271
272 route = {u'prefix': u'5.6.7.8/32', u'nextHop': u'55.66.77.88'}
273
274 self.sync_step.delete_route(self.onos_service, route)
275
276 @requests_mock.Mocker()
277 def test_post_route(self, m):
278 m.post("http://fabric_host:1234/onos/routeservice/routes",
279 status_code=200,
280 additional_matcher=functools.partial(match_json,{u'prefix': u'5.6.7.8/32', u'nextHop': u'55.66.77.88'}))
281
282 route = {u'prefix': u'5.6.7.8/32', u'nextHop': u'55.66.77.88'}
283
284 self.sync_step.post_route(self.onos_service, route)
285
286if __name__ == "__main__":
287 unittest.main()