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