blob: 29a89626dfbd04f5849bdee0b34c0409037ec641 [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070017""" fake_stub.py
18
19 Implements a simple fake grpc stub to use for unit testing.
20"""
21
22import functools
23
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070024ContentTypeMap = {}
25
26class FakeObj(object):
Scott Bakerff104cc2017-08-14 15:24:41 -070027 BASES=[]
28
Scott Baker03a163f2017-05-17 09:21:47 -070029 def __init__(self, fields=[], **kwargs):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070030 super(FakeObj, self).__setattr__("is_set", {})
31 super(FakeObj, self).__setattr__("fields", [])
32
Scott Baker03a163f2017-05-17 09:21:47 -070033 for f in fields:
34 name = f["name"]
35 self.fields.append(name)
36 setattr(self, name, f["default"])
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070037
38 super(FakeObj, self).__setattr__("is_set", {})
39 for (k,v) in kwargs.items():
40 setattr(self, k, v)
41
42 def __repr__(self):
43 lines = []
44 for k in self.fields:
45 if self.is_set.get(k, False):
46 lines.append('%s: "%s"' % (k, getattr(self, k)))
47 if lines:
48 return "\n".join(lines) + "\n"
49 else:
50 return ""
51
52 def __setattr__(self, name, value):
53 self.is_set[name] = True
54 super(FakeObj, self).__setattr__(name, value)
55
Scott Baker500f8c72017-05-19 09:41:50 -070056 @property
57 def self_content_type_id(self):
58 return "xos.%s" % self.__class__.__name__.lower()
59
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070060class FakeExtensionManager(object):
61 def __init__(self, obj, extensions):
62 self.obj = obj
63 self.extensions = extensions
64
65 def _FindExtensionByName(self, name):
66 return name
67
68 def __getitem__(self, name, default=None):
69 if name in self.extensions:
70 return self.extensions[name]
71 return default
72
Scott Baker03a163f2017-05-17 09:21:47 -070073class FakeFieldOption(object):
Scott Bakerc4156c32017-12-08 10:58:21 -080074 def __init__(self, modelName=None, reverseFieldName=None):
Scott Baker03a163f2017-05-17 09:21:47 -070075 self.modelName = modelName
Scott Bakerc4156c32017-12-08 10:58:21 -080076 self.reverseFieldName = reverseFieldName
Scott Baker03a163f2017-05-17 09:21:47 -070077
78class FakeField(object):
79 def __init__(self, field):
80 extensions = {}
81
82 fk_model = field.get("fk_model", None)
83 if fk_model:
Scott Bakerc4156c32017-12-08 10:58:21 -080084 reverseFieldName = field.get("fk_reverseFieldName", None)
85 extensions["xos.foreignKey"] = FakeFieldOption(modelName=fk_model, reverseFieldName=reverseFieldName)
Scott Baker03a163f2017-05-17 09:21:47 -070086
87 fk_reverse = field.get("fk_reverse", None)
88 if fk_reverse:
89 extensions["xos.reverseForeignKey"] = FakeFieldOption(modelName=fk_reverse)
90
91 self.Extensions = FakeExtensionManager(self, extensions)
92
93 def GetOptions(self):
94 return self
95
Scott Bakerf0ee0dc2017-05-15 10:10:05 -070096class FakeDescriptor(object):
97 def __init__(self, objName):
98 global ContentTypeIdCounter
99 global ContentTypeMap
Scott Baker03a163f2017-05-17 09:21:47 -0700100 self.objName = objName
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700101 if objName in ContentTypeMap:
102 ct = ContentTypeMap[objName]
103 else:
Scott Baker500f8c72017-05-19 09:41:50 -0700104 ct = "xos.%s" % objName.lower()
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700105 ContentTypeMap[objName] = ct
106 self.Extensions = FakeExtensionManager(self, {"xos.contentTypeId": ct})
107
108 def GetOptions(self):
109 return self
110
111 @property
112 def fields_by_name(self):
Scott Baker03a163f2017-05-17 09:21:47 -0700113 cls = globals()[self.objName]
114 fbn = {}
115 for field in cls.FIELDS:
116 fake_field = FakeField(field)
117 fbn[ field["name"] ] = fake_field
118
119 return fbn
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700120
Scott Baker5f38c7b2017-08-18 10:12:49 -0700121class Controller(FakeObj):
122 FIELDS = ( {"name": "id", "default": 0},
123 {"name": "name", "default": ""},
124 {"name": "deployment_id", "default": 0, "fk_model": "Deployment"}
125 )
126
127 def __init__(self, **kwargs):
128 return super(Controller, self).__init__(self.FIELDS, **kwargs)
129
130 DESCRIPTOR = FakeDescriptor("Controller")
131
132class Deployment(FakeObj):
133 FIELDS = ( {"name": "id", "default": 0},
134 {"name": "name", "default": ""},
135 )
136
137 def __init__(self, **kwargs):
138 return super(Deployment, self).__init__(self.FIELDS, **kwargs)
139
140 DESCRIPTOR = FakeDescriptor("Controller")
141
Scott Bakerff104cc2017-08-14 15:24:41 -0700142class User(FakeObj):
143 FIELDS = ( {"name": "id", "default": 0},
144 {"name": "email", "default": ""},
145 {"name": "site_id", "default": 0, "fk_model": "Site"}, )
146
147 def __init__(self, **kwargs):
148 return super(User, self).__init__(self.FIELDS, **kwargs)
149
150 DESCRIPTOR = FakeDescriptor("User")
151
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700152class Slice(FakeObj):
Scott Baker03a163f2017-05-17 09:21:47 -0700153 FIELDS = ( {"name": "id", "default": 0},
154 {"name": "name", "default": ""},
Scott Bakerc4156c32017-12-08 10:58:21 -0800155 {"name": "site_id", "default": 0, "fk_model": "Site", "fk_reverseFieldName": "slices"},
Scott Baker5f38c7b2017-08-18 10:12:49 -0700156 {"name": "service_id", "default": 0, "fk_model": "Service"},
Scott Bakerff104cc2017-08-14 15:24:41 -0700157 {"name": "creator_id", "default": 0, "fk_model": "User"},
Scott Baker5f38c7b2017-08-18 10:12:49 -0700158 {"name": "networks_ids", "default": [], "fk_reverse": "Network"},
159 {"name": "network", "default": ""},
Scott Bakerff104cc2017-08-14 15:24:41 -0700160 {"name": "leaf_model_name", "default": "Slice"} )
Scott Baker03a163f2017-05-17 09:21:47 -0700161
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700162 def __init__(self, **kwargs):
Scott Baker03a163f2017-05-17 09:21:47 -0700163 return super(Slice, self).__init__(self.FIELDS, **kwargs)
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700164
165 DESCRIPTOR = FakeDescriptor("Slice")
166
Scott Baker03a163f2017-05-17 09:21:47 -0700167class Site(FakeObj):
168 FIELDS = ( {"name": "id", "default": 0},
169 {"name": "name", "default": ""},
Scott Bakerc4156c32017-12-08 10:58:21 -0800170 {"name": "slices_ids", "default": [], "fk_reverse": "Slice"},
Scott Bakerff104cc2017-08-14 15:24:41 -0700171 {"name": "leaf_model_name", "default": "Site"})
Scott Baker03a163f2017-05-17 09:21:47 -0700172
173 def __init__(self, **kwargs):
174 return super(Site, self).__init__(self.FIELDS, **kwargs)
175
176 DESCRIPTOR = FakeDescriptor("Site")
177
Scott Baker500f8c72017-05-19 09:41:50 -0700178class Service(FakeObj):
179 FIELDS = ( {"name": "id", "default": 0},
Scott Bakerff104cc2017-08-14 15:24:41 -0700180 {"name": "name", "default": ""},
Scott Baker5f38c7b2017-08-18 10:12:49 -0700181 {"name": "slices_ids", "default": [], "fk_reverse": "Slice"},
Scott Bakerff104cc2017-08-14 15:24:41 -0700182 {"name": "leaf_model_name", "default": "Service"})
Scott Baker500f8c72017-05-19 09:41:50 -0700183
184 def __init__(self, **kwargs):
185 return super(Service, self).__init__(self.FIELDS, **kwargs)
186
187 DESCRIPTOR = FakeDescriptor("Service")
188
Scott Baker8f36c3f2017-09-26 16:44:36 -0700189class ServiceInstance(FakeObj):
190 FIELDS = ( {"name": "id", "default": 0},
191 {"name": "owher", "default": 0, "fk_model": "Service"},
192 {"name": "leaf_model_name", "default": "ServiceInstance"})
193
194 def __init__(self, **kwargs):
195 return super(ServiceInstance, self).__init__(self.FIELDS, **kwargs)
196
197 DESCRIPTOR = FakeDescriptor("ServiceInstance")
198
Scott Bakerff104cc2017-08-14 15:24:41 -0700199class ONOSService(FakeObj):
200 FIELDS = ( {"name": "id", "default": 0},
201 {"name": "name", "default": ""},
202 {"name": "leaf_model_name", "default": "ONOSService"})
203
204 BASES = ["Service"]
205
206 def __init__(self, **kwargs):
207 return super(ONOSService, self).__init__(self.FIELDS, **kwargs)
208
209 DESCRIPTOR = FakeDescriptor("ONOSService")
210
Scott Baker5f38c7b2017-08-18 10:12:49 -0700211class Network(FakeObj):
212 FIELDS = ( {"name": "id", "default": 0},
213 {"name": "name", "default": ""},
214 {"name": "owner_id", "default": 0, "fk_model": "Slice"},
215 {"name": "template_id", "default": 0, "fk_model": "NetworkTemplate"},
216 {"name": "controllernetworks_ids", "default": [], "fk_reverse": "ControllerNetwork"},
217 {"name": "leaf_model_name", "default": "Network"})
218
219 def __init__(self, **kwargs):
220 return super(Network, self).__init__(self.FIELDS, **kwargs)
221
222 DESCRIPTOR = FakeDescriptor("Network")
223
224class NetworkTemplate(FakeObj):
225 FIELDS = ( {"name": "id", "default": 0},
226 {"name": "name", "default": ""},
227 {"name": "vtn_kind", "default": ""},
228 {"name": "leaf_model_name", "default": "NetworkTemplate"})
229
230 def __init__(self, **kwargs):
231 return super(NetworkTemplate, self).__init__(self.FIELDS, **kwargs)
232
233 DESCRIPTOR = FakeDescriptor("NetworkTemplate")
234
235class ControllerNetwork(FakeObj):
236 FIELDS = ( {"name": "id", "default": 0},
237 {"name": "network_id", "default": 0, "fk_model": "Network"},
238 {"name": "controller_id", "default": 0, "fk_model": "Controller"},
239 {"name": "leaf_model_name", "default": "ControllerNetwork"})
240
241 def __init__(self, **kwargs):
242 return super(ControllerNetwork, self).__init__(self.FIELDS, **kwargs)
243
244 DESCRIPTOR = FakeDescriptor("ControllerNetwork")
245
246class NetworkSlice(FakeObj):
247 FIELDS = ( {"name": "id", "default": 0},
248 {"name": "network_id", "default": 0, "fk_model": "Network"},
249 {"name": "slice_id", "default": 0, "fk_model": "Slice"},
250 {"name": "leaf_model_name", "default": "ControllerNetwork"})
251
252 def __init__(self, **kwargs):
253 return super(NetworkSlice, self).__init__(self.FIELDS, **kwargs)
254
255 DESCRIPTOR = FakeDescriptor("NetworkSlice")
256
Scott Baker500f8c72017-05-19 09:41:50 -0700257class Tag(FakeObj):
258 FIELDS = ( {"name": "id", "default": 0},
259 {"name": "service_id", "default": None},
260 {"name": "name", "default": ""},
261 {"name": "value", "default": ""},
262 {"name": "content_type", "default": None},
263 {"name": "object_id", "default": None},
Scott Bakerff104cc2017-08-14 15:24:41 -0700264 {"name": "leaf_model_name", "default": "Tag"})
Scott Baker500f8c72017-05-19 09:41:50 -0700265
266 def __init__(self, **kwargs):
267 return super(Tag, self).__init__(self.FIELDS, **kwargs)
268
269 DESCRIPTOR = FakeDescriptor("Tag")
270
271class ID(FakeObj):
272 pass
273
274class FakeItemList(object):
275 def __init__(self, items):
276 self.items = items
277
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700278class FakeStub(object):
279 def __init__(self):
Scott Baker500f8c72017-05-19 09:41:50 -0700280 self.id_counter = 1
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700281 self.objs = {}
Scott Baker8f36c3f2017-09-26 16:44:36 -0700282 for name in ["Controller", "Deployment", "Slice", "Site", "Tag", "Service", "ServiceInstance", "ONOSService", "User", "Network", "NetworkTemplate", "ControllerNetwork", "NetworkSlice"]:
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700283 setattr(self, "Get%s" % name, functools.partial(self.get, name))
284 setattr(self, "List%s" % name, functools.partial(self.list, name))
285 setattr(self, "Create%s" % name, functools.partial(self.create, name))
286 setattr(self, "Delete%s" % name, functools.partial(self.delete, name))
287 setattr(self, "Update%s" % name, functools.partial(self.update, name))
288
289
290 def make_key(self, name, id):
291 return "%s:%d" % (name, id.id)
292
Scott Baker500f8c72017-05-19 09:41:50 -0700293 def get(self, classname, id, metadata=None):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700294 obj = self.objs.get(self.make_key(classname, id), None)
295 return obj
296
Scott Baker500f8c72017-05-19 09:41:50 -0700297 def list(self, classname, empty, metadata=None):
298 items = []
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700299 for (k,v) in self.objs.items():
300 (this_classname, id) = k.split(":")
301 if this_classname == classname:
302 items.append(v)
Scott Baker500f8c72017-05-19 09:41:50 -0700303 return FakeItemList(items)
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700304
Scott Baker500f8c72017-05-19 09:41:50 -0700305 def create(self, classname, obj, metadata=None):
306 obj.id = self.id_counter
307 self.id_counter = self.id_counter + 1
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700308 k = self.make_key(classname, FakeObj(id=obj.id))
309 self.objs[k] = obj
Scott Bakerff104cc2017-08-14 15:24:41 -0700310
311 for base_classname in obj.BASES:
312 base_class = globals()[base_classname]
313 base_obj = base_class(id=obj.id, leaf_model_name = classname)
314 k = self.make_key(base_classname, base_obj)
315 self.objs[k] = base_obj
316
Scott Baker500f8c72017-05-19 09:41:50 -0700317 return obj
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700318
Scott Baker500f8c72017-05-19 09:41:50 -0700319 def update(self, classname, obj, metadata=None):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700320 # TODO: partial update support?
321 k = self.make_key(classname, FakeObj(id=obj.id))
322 self.objs[k] = obj
Scott Baker500f8c72017-05-19 09:41:50 -0700323 return obj
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700324
Scott Baker500f8c72017-05-19 09:41:50 -0700325 def delete(self, classname, id, metadata=None):
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700326 k = self.make_key(classname, id)
327 del self.objs[k]
328
329class FakeSymDb(object):
330 def __init__(self):
331 self._classes = {}
Scott Baker8f36c3f2017-09-26 16:44:36 -0700332 for name in ["Controller", "Deployment", "Slice", "Site", "ID", "Tag", "Service", "ServiceInstance", "ONOSService", "User", "Network", "NetworkTemplate", "ControllerNetwork", "NetworkSlice"]:
Scott Bakerf0ee0dc2017-05-15 10:10:05 -0700333 self._classes["xos.%s" % name] = globals()[name]
334
335
336