blob: c26fb205b6ff09022dbf15a40b5af8683db1a1cb [file] [log] [blame]
Scott Baker8e6647a2016-06-20 17:16:20 -07001from rest_framework.decorators import api_view
2from rest_framework.response import Response
3from rest_framework.reverse import reverse
4from rest_framework import serializers
5from rest_framework import generics
6from rest_framework import viewsets
7from rest_framework import status
8from rest_framework.decorators import detail_route, list_route
9from rest_framework.views import APIView
10from core.models import *
11from django.forms import widgets
12from django.conf.urls import patterns, url
Scott Bakerc15556d2017-05-06 09:55:01 -070013from services.volt.models import VOLTTenant
14from services.rcord.models import CordSubscriberRoot
Scott Baker8e6647a2016-06-20 17:16:20 -070015from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
16from django.shortcuts import get_object_or_404
17from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
18from xos.exceptions import *
19import json
20import subprocess
21from django.views.decorators.csrf import ensure_csrf_cookie
22
23class CordSubscriberNew(CordSubscriberRoot):
24 class Meta:
25 proxy = True
26 app_label = "cord"
27
28 def __init__(self, *args, **kwargs):
29 super(CordSubscriberNew, self).__init__(*args, **kwargs)
30
31 def __unicode__(self):
32 return u"cordSubscriber-%s" % str(self.id)
33
34 @property
35 def features(self):
36 return {"cdn": self.cdn_enable,
37 "uplink_speed": self.uplink_speed,
38 "downlink_speed": self.downlink_speed,
39 "uverse": self.enable_uverse,
40 "status": self.status}
41
42 @features.setter
43 def features(self, value):
44 self.cdn_enable = value.get("cdn", self.get_default_attribute("cdn_enable"))
45 self.uplink_speed = value.get("uplink_speed", self.get_default_attribute("uplink_speed"))
46 self.downlink_speed = value.get("downlink_speed", self.get_default_attribute("downlink_speed"))
47 self.enable_uverse = value.get("uverse", self.get_default_attribute("enable_uverse"))
48 self.status = value.get("status", self.get_default_attribute("status"))
49
50
51 def update_features(self, value):
52 d=self.features
53 d.update(value)
54 self.features = d
55
56 @property
57 def identity(self):
58 return {"account_num": self.service_specific_id,
59 "name": self.name}
60
61 @identity.setter
62 def identity(self, value):
63 self.service_specific_id = value.get("account_num", self.service_specific_id)
64 self.name = value.get("name", self.name)
65
66 def update_identity(self, value):
67 d=self.identity
68 d.update(value)
69 self.identity = d
70
71 @property
72 def related(self):
73 related = {}
74 if self.volt:
75 related["volt_id"] = self.volt.id
76 related["s_tag"] = self.volt.s_tag
77 related["c_tag"] = self.volt.c_tag
78 if self.volt.vcpe:
79 related["vsg_id"] = self.volt.vcpe.id
80 if self.volt.vcpe.instance:
81 related["instance_id"] = self.volt.vcpe.instance.id
82 related["instance_name"] = self.volt.vcpe.instance.name
83 related["wan_container_ip"] = self.volt.vcpe.wan_container_ip
84 if self.volt.vcpe.instance.node:
85 related["compute_node_name"] = self.volt.vcpe.instance.node.name
86 return related
87
88 def save(self, *args, **kwargs):
89 super(CordSubscriberNew, self).save(*args, **kwargs)
90
91class CordDevice(object):
92 def __init__(self, d={}, subscriber=None):
93 self.d = d
94 self.subscriber = subscriber
95
96 @property
97 def mac(self):
98 return self.d.get("mac", None)
99
100 @mac.setter
101 def mac(self, value):
102 self.d["mac"] = value
103
104 @property
105 def identity(self):
106 return {"name": self.d.get("name", None)}
107
108 @identity.setter
109 def identity(self, value):
110 self.d["name"] = value.get("name", None)
111
112 @property
113 def features(self):
114 return {"uplink_speed": self.d.get("uplink_speed", None),
115 "downlink_speed": self.d.get("downlink_speed", None)}
116
117 @features.setter
118 def features(self, value):
119 self.d["uplink_speed"] = value.get("uplink_speed", None)
120 self.d["downlink_speed"] = value.get("downlink_speed", None)
121
122 def update_features(self, value):
123 d=self.features
124 d.update(value)
125 self.features = d
126
127 def update_identity(self, value):
128 d=self.identity
129 d.update(value)
130 self.identity = d
131
132 def save(self):
133 if self.subscriber:
134 dev=self.subscriber.find_device(self.mac)
135 if dev:
136 self.subscriber.update_device(**self.d)
137 else:
138 self.subscriber.create_device(**self.d)
139
140# Add some structure to the REST API by subdividing the object into
141# features, identity, and related.
142
143class FeatureSerializer(serializers.Serializer):
144 cdn = serializers.BooleanField(required=False)
145 uplink_speed = serializers.IntegerField(required=False)
146 downlink_speed = serializers.IntegerField(required=False)
147 uverse = serializers.BooleanField(required=False)
148 status = serializers.CharField(required=False)
149
150class IdentitySerializer(serializers.Serializer):
151 account_num = serializers.CharField(required=False)
152 name = serializers.CharField(required=False)
153
154class DeviceFeatureSerializer(serializers.Serializer):
155 uplink_speed = serializers.IntegerField(required=False)
156 downlink_speed = serializers.IntegerField(required=False)
157
158class DeviceIdentitySerializer(serializers.Serializer):
159 name = serializers.CharField(required=False)
160
161class DeviceSerializer(serializers.Serializer):
162 mac = serializers.CharField(required=True)
163 identity = DeviceIdentitySerializer(required=False)
164 features = DeviceFeatureSerializer(required=False)
165
166 class Meta:
167 fields = ('mac', 'identity', 'features')
168
169class CordSubscriberSerializer(PlusModelSerializer):
170 id = ReadOnlyField()
171 humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
172 features = FeatureSerializer(required=False)
173 identity = IdentitySerializer(required=False)
174 related = serializers.DictField(required=False)
175
176 nested_fields = ["features", "identity"]
177
178 class Meta:
179 model = CordSubscriberNew
180 fields = ('humanReadableName',
181 'id',
182 'features',
183 'identity',
184 'related')
185
186 def getHumanReadableName(self, obj):
187 return obj.__unicode__()
188
189# @ensure_csrf_cookie
190class CordSubscriberViewSet(XOSViewSet):
191 base_name = "subscriber"
192 method_name = "subscriber"
193 method_kind = "viewset"
Scott Baker11e1e462017-03-20 16:32:17 -0700194 queryset = CordSubscriberNew.objects.select_related().all()
Scott Baker8e6647a2016-06-20 17:16:20 -0700195 serializer_class = CordSubscriberSerializer
196
197 custom_serializers = {"set_features": FeatureSerializer,
198 "set_feature": FeatureSerializer,
199 "set_identities": IdentitySerializer,
200 "set_identity": IdentitySerializer,
201 "get_devices": DeviceSerializer,
202 "add_device": DeviceSerializer,
203 "get_device_feature": DeviceFeatureSerializer,
204 "set_device_feature": DeviceFeatureSerializer}
205
206 @classmethod
207 def get_urlpatterns(self, api_path="^"):
208 patterns = super(CordSubscriberViewSet, self).get_urlpatterns(api_path=api_path)
209 patterns.append( self.detail_url("features/$", {"get": "get_features", "put": "set_features"}, "features") )
210 patterns.append( self.detail_url("features/(?P<feature>[a-zA-Z0-9\-_]+)/$", {"get": "get_feature", "put": "set_feature"}, "get_feature") )
211 patterns.append( self.detail_url("identity/$", {"get": "get_identities", "put": "set_identities"}, "identities") )
212 patterns.append( self.detail_url("identity/(?P<identity>[a-zA-Z0-9\-_]+)/$", {"get": "get_identity", "put": "set_identity"}, "get_identity") )
213
214 patterns.append( self.detail_url("devices/$", {"get": "get_devices", "post": "add_device"}, "devicees") )
215 patterns.append( self.detail_url("devices/(?P<mac>[a-zA-Z0-9\-_:]+)/$", {"get": "get_device", "delete": "delete_device"}, "getset_device") )
216 patterns.append( self.detail_url("devices/(?P<mac>[a-zA-Z0-9\-_:]+)/features/(?P<feature>[a-zA-Z0-9\-_]+)/$", {"get": "get_device_feature", "put": "set_device_feature"}, "getset_device_feature") )
217 patterns.append( self.detail_url("devices/(?P<mac>[a-zA-Z0-9\-_:]+)/identity/(?P<identity>[a-zA-Z0-9\-_]+)/$", {"get": "get_device_identity", "put": "set_device_identity"}, "getset_device_identity") )
218
219 patterns.append( url(self.api_path + "account_num_lookup/(?P<account_num>[0-9\-]+)/$", self.as_view({"get": "account_num_detail"}), name="account_num_detail") )
220
221 patterns.append( url(self.api_path + "ssidmap/(?P<ssid>[0-9\-]+)/$", self.as_view({"get": "ssiddetail"}), name="ssiddetail") )
222 patterns.append( url(self.api_path + "ssidmap/$", self.as_view({"get": "ssidlist"}), name="ssidlist") )
223
224 return patterns
225
226 def list(self, request):
227 object_list = self.filter_queryset(self.get_queryset())
228
229 serializer = self.get_serializer(object_list, many=True)
230
231 return Response(serializer.data)
232
233 def get_features(self, request, pk=None):
234 subscriber = self.get_object()
235 return Response(FeatureSerializer(subscriber.features).data)
236
237 def set_features(self, request, pk=None):
238 subscriber = self.get_object()
239 ser = FeatureSerializer(subscriber.features, data=request.data)
240 ser.is_valid(raise_exception = True)
241 subscriber.update_features(ser.validated_data)
242 subscriber.save()
243 return Response(FeatureSerializer(subscriber.features).data)
244
245 def get_feature(self, request, pk=None, feature=None):
246 subscriber = self.get_object()
247 return Response({feature: FeatureSerializer(subscriber.features).data[feature]})
248
249 def set_feature(self, request, pk=None, feature=None):
250 subscriber = self.get_object()
251 if [feature] != request.data.keys():
252 raise serializers.ValidationError("feature %s does not match keys in request body (%s)" % (feature, ",".join(request.data.keys())))
253 ser = FeatureSerializer(subscriber.features, data=request.data)
254 ser.is_valid(raise_exception = True)
255 subscriber.update_features(ser.validated_data)
256 subscriber.save()
257 return Response({feature: FeatureSerializer(subscriber.features).data[feature]})
258
259 def get_identities(self, request, pk=None):
260 subscriber = self.get_object()
261 return Response(IdentitySerializer(subscriber.identity).data)
262
263 def set_identities(self, request, pk=None):
264 subscriber = self.get_object()
265 ser = IdentitySerializer(subscriber.identity, data=request.data)
266 ser.is_valid(raise_exception = True)
267 subscriber.update_identity(ser.validated_data)
268 subscriber.save()
269 return Response(IdentitySerializer(subscriber.identity).data)
270
271 def get_identity(self, request, pk=None, identity=None):
272 subscriber = self.get_object()
273 return Response({identity: IdentitySerializer(subscriber.identity).data[identity]})
274
275 def set_identity(self, request, pk=None, identity=None):
276 subscriber = self.get_object()
277 if [identity] != request.data.keys():
278 raise serializers.ValidationError("identity %s does not match keys in request body (%s)" % (identity, ",".join(request.data.keys())))
279 ser = IdentitySerializer(subscriber.identity, data=request.data)
280 ser.is_valid(raise_exception = True)
281 subscriber.update_identity(ser.validated_data)
282 subscriber.save()
283 return Response({identity: IdentitySerializer(subscriber.identity).data[identity]})
284
285 def get_devices(self, request, pk=None):
286 subscriber = self.get_object()
287 result = []
288 for device in subscriber.devices:
289 device = CordDevice(device, subscriber)
290 result.append(DeviceSerializer(device).data)
291 return Response(result)
292
293 def add_device(self, request, pk=None):
294 subscriber = self.get_object()
295 ser = DeviceSerializer(subscriber.devices, data=request.data)
296 ser.is_valid(raise_exception = True)
297 newdevice = CordDevice(subscriber.create_device(**ser.validated_data), subscriber)
298 subscriber.save()
299 return Response(DeviceSerializer(newdevice).data)
300
301 def get_device(self, request, pk=None, mac=None):
302 subscriber = self.get_object()
303 device = subscriber.find_device(mac)
304 if not device:
305 return Response("Failed to find device %s" % mac, status=status.HTTP_404_NOT_FOUND)
306 return Response(DeviceSerializer(CordDevice(device, subscriber)).data)
307
308 def delete_device(self, request, pk=None, mac=None):
309 subscriber = self.get_object()
310 device = subscriber.find_device(mac)
311 if not device:
312 return Response("Failed to find device %s" % mac, status=status.HTTP_404_NOT_FOUND)
313 subscriber.delete_device(mac)
314 subscriber.save()
315 return Response("Okay")
316
317 def get_device_feature(self, request, pk=None, mac=None, feature=None):
318 subscriber = self.get_object()
319 device = subscriber.find_device(mac)
320 if not device:
321 return Response("Failed to find device %s" % mac, status=status.HTTP_404_NOT_FOUND)
322 return Response({feature: DeviceFeatureSerializer(CordDevice(device, subscriber).features).data[feature]})
323
324 def set_device_feature(self, request, pk=None, mac=None, feature=None):
325 subscriber = self.get_object()
326 device = subscriber.find_device(mac)
327 if not device:
328 return Response("Failed to find device %s" % mac, status=status.HTTP_404_NOT_FOUND)
329 if [feature] != request.data.keys():
330 raise serializers.ValidationError("feature %s does not match keys in request body (%s)" % (feature, ",".join(request.data.keys())))
331 device = CordDevice(device, subscriber)
332 ser = DeviceFeatureSerializer(device.features, data=request.data)
333 ser.is_valid(raise_exception = True)
334 device.update_features(ser.validated_data)
335 device.save()
336 subscriber.save()
337 return Response({feature: DeviceFeatureSerializer(device.features).data[feature]})
338
339 def get_device_identity(self, request, pk=None, mac=None, identity=None):
340 subscriber = self.get_object()
341 device = subscriber.find_device(mac)
342 if not device:
343 return Response("Failed to find device %s" % mac, status=status.HTTP_404_NOT_FOUND)
344 return Response({identity: DeviceIdentitySerializer(CordDevice(device, subscriber).identity).data[identity]})
345
346 def set_device_identity(self, request, pk=None, mac=None, identity=None):
347 subscriber = self.get_object()
348 device = subscriber.find_device(mac)
349 if not device:
350 return Response("Failed to find device %s" % mac, status=status.HTTP_404_NOT_FOUND)
351 if [identity] != request.data.keys():
352 raise serializers.ValidationError("identity %s does not match keys in request body (%s)" % (feature, ",".join(request.data.keys())))
353 device = CordDevice(device, subscriber)
354 ser = DeviceIdentitySerializer(device.identity, data=request.data)
355 ser.is_valid(raise_exception = True)
356 device.update_identity(ser.validated_data)
357 device.save()
358 subscriber.save()
359 return Response({identity: DeviceIdentitySerializer(device.identity).data[identity]})
360
361 def account_num_detail(self, pk=None, account_num=None):
362 object_list = CordSubscriberNew.get_tenant_objects().all()
363 object_list = [x for x in object_list if x.service_specific_id == account_num]
364 if not object_list:
365 return Response("Failed to find account_num %s" % account_num, status=status.HTTP_404_NOT_FOUND)
366
367 return Response( object_list[0].id )
368
369 def ssidlist(self, request):
370 object_list = CordSubscriberNew.get_tenant_objects().all()
371
372 ssidmap = [ {"service_specific_id": x.service_specific_id, "subscriber_id": x.id} for x in object_list ]
373
374 return Response({"ssidmap": ssidmap})
375
376 def ssiddetail(self, pk=None, ssid=None):
377 object_list = CordSubscriberNew.get_tenant_objects().all()
378
379 ssidmap = [ {"service_specific_id": x.service_specific_id, "subscriber_id": x.id} for x in object_list if str(x.service_specific_id)==str(ssid) ]
380
381 if len(ssidmap)==0:
382 raise XOSNotFound("didn't find ssid %s" % str(ssid))
383
384 return Response( ssidmap[0] )
385