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