blob: 12fc4e99abb45b26574e05377bce3ea43b250214 [file] [log] [blame]
Scott Bakerfb9544a2016-03-25 10:55:03 -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.decorators import detail_route, list_route
8from rest_framework.views import APIView
9from core.models import *
10from django.forms import widgets
11from django.conf.urls import patterns, url
12from services.cord.models import VOLTTenant, VBNGTenant, CordSubscriberRoot
13from core.xoslib.objects.cordsubscriber import CordSubscriber
Scott Bakerd9d55f22016-03-25 13:33:11 -070014from api.xosapi_helpers import PlusSerializerMixin, XOSViewSet
Scott Bakerfb9544a2016-03-25 10:55:03 -070015from django.shortcuts import get_object_or_404
16from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
17from xos.exceptions import *
18import json
19import subprocess
20
21if hasattr(serializers, "ReadOnlyField"):
22 # rest_framework 3.x
23 ReadOnlyField = serializers.ReadOnlyField
24else:
25 # rest_framework 2.x
26 ReadOnlyField = serializers.Field
27
28class CordSubscriberIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
29 id = ReadOnlyField()
30 service_specific_id = ReadOnlyField()
31 vlan_id = ReadOnlyField() # XXX remove this
32 c_tag = ReadOnlyField()
33 s_tag = ReadOnlyField()
34 vcpe_id = ReadOnlyField()
35 instance = ReadOnlyField()
36 image = ReadOnlyField()
37 vbng_id = ReadOnlyField()
38 firewall_enable = serializers.BooleanField()
39 firewall_rules = serializers.CharField()
40 url_filter_enable = serializers.BooleanField()
41 url_filter_rules = serializers.CharField()
42 url_filter_level = serializers.CharField(required=False)
43 cdn_enable = serializers.BooleanField()
44 instance_name = ReadOnlyField()
45 image_name = ReadOnlyField()
46 routeable_subnet = serializers.CharField(required=False)
47 ssh_command = ReadOnlyField()
48 bbs_account = ReadOnlyField()
49
50 wan_container_ip = ReadOnlyField()
51 uplink_speed = serializers.CharField(required=False)
52 downlink_speed = serializers.CharField(required=False)
53 status = serializers.CharField()
54 enable_uverse = serializers.BooleanField()
55
56 lan_ip = ReadOnlyField()
57 wan_ip = ReadOnlyField()
58 nat_ip = ReadOnlyField()
59 private_ip = ReadOnlyField()
60
61 wan_mac = ReadOnlyField()
62
63 vcpe_synced = serializers.BooleanField()
64
65 humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
66
67 class Meta:
68 model = CordSubscriber
69 fields = ('humanReadableName', 'id',
70 'service_specific_id', 'vlan_id', 's_tag', 'c_tag',
71 'vcpe_id', 'instance', 'instance_name', 'image', 'image_name',
72 'firewall_enable', 'firewall_rules',
73 'url_filter_enable', 'url_filter_rules', 'url_filter_level',
74 'bbs_account',
75 'ssh_command',
76 'vcpe_synced',
77 'cdn_enable', 'vbng_id', 'routeable_subnet', 'nat_ip', 'lan_ip', 'wan_ip', 'private_ip', 'wan_mac',
78 'wan_container_ip',
79 'uplink_speed', 'downlink_speed', 'status', 'enable_uverse')
80
81
82 def getHumanReadableName(self, obj):
83 return obj.__unicode__()
84
85#------------------------------------------------------------------------------
86# The "old" API
87# This is used by the xoslib-based GUI
88#------------------------------------------------------------------------------
89
90class CordSubscriberList(XOSListCreateAPIView):
91 queryset = CordSubscriber.get_tenant_objects().select_related().all()
92 serializer_class = CordSubscriberIdSerializer
93
94 method_kind = "list"
95 method_name = "cordsubscriber"
96
97class CordSubscriberDetail(XOSRetrieveUpdateDestroyAPIView):
98 queryset = CordSubscriber.get_tenant_objects().select_related().all()
99 serializer_class = CordSubscriberIdSerializer
100
101 method_kind = "detail"
102 method_name = "cordsubscriber"
103
Scott Bakerfb9544a2016-03-25 10:55:03 -0700104
105#------------------------------------------------------------------------------
106# The "new" API with many more REST endpoints.
107# This is for integration with with the subscriber GUI
108#------------------------------------------------------------------------------
109
110class CordSubscriberViewSet(XOSViewSet):
111 base_name = "subscriber"
Scott Bakerd9d55f22016-03-25 13:33:11 -0700112 method_name = "subscriber"
Scott Bakerfb9544a2016-03-25 10:55:03 -0700113 method_kind = "viewset"
114 queryset = CordSubscriber.get_tenant_objects().select_related().all()
115 serializer_class = CordSubscriberIdSerializer
116
117 def get_vcpe(self):
118 subscriber = self.get_object()
119 if not subscriber.vcpe:
120 raise XOSMissingField("vCPE object is not present for subscriber")
121 return subscriber.vcpe
122
123 @classmethod
Scott Bakerbca3a1b2016-03-28 13:22:10 -0700124 def get_urlpatterns(self, api_path="^"):
Scott Bakerd9d55f22016-03-25 13:33:11 -0700125 patterns = super(CordSubscriberViewSet, self).get_urlpatterns(api_path=api_path)
Scott Bakerfb9544a2016-03-25 10:55:03 -0700126 patterns.append( self.detail_url("vcpe_synced/$", {"get": "get_vcpe_synced"}, "vcpe_synced") )
127 patterns.append( self.detail_url("url_filter/$", {"get": "get_url_filter"}, "url_filter") )
128 patterns.append( self.detail_url("url_filter/(?P<level>[a-zA-Z0-9\-_]+)/$", {"put": "set_url_filter"}, "url_filter") )
129 patterns.append( self.detail_url("services/$", {"get": "get_services"}, "services") )
130 patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "get_service") )
131 patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/true/$", {"put": "enable_service"}, "enable_service") )
132 patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/false/$", {"put": "disable_service"}, "disable_service") )
133
134 patterns.append( self.detail_url("users/$", {"get": "get_users", "post": "create_user"}, "users") )
135 patterns.append( self.detail_url("users/clearusers/$", {"get": "clear_users", "put": "clear_users", "post": "clear_users"}, "clearusers") )
136 patterns.append( self.detail_url("users/newuser/$", {"put": "create_user", "post": "create_user"}, "newuser") )
137 patterns.append( self.detail_url("users/(?P<uid>[0-9\-]+)/$", {"delete": "delete_user"}, "user") )
138 patterns.append( self.detail_url("users/(?P<uid>[0-9\-]+)/url_filter/$", {"get": "get_user_level"}, "user_level") )
139 patterns.append( self.detail_url("users/(?P<uid>[0-9\-]+)/url_filter/(?P<level>[a-zA-Z0-9\-_]+)/$", {"put": "set_user_level"}, "set_user_level") )
140
141 patterns.append( self.detail_url("bbsdump/$", {"get": "get_bbsdump"}, "bbsdump") )
142
Scott Bakerd9d55f22016-03-25 13:33:11 -0700143 patterns.append( url(self.api_path + "subidlookup/(?P<ssid>[0-9\-]+)/$", self.as_view({"get": "ssiddetail"}), name="ssiddetail") )
144 patterns.append( url(self.api_path + "subidlookup/$", self.as_view({"get": "ssidlist"}), name="ssidlist") )
Scott Bakerfb9544a2016-03-25 10:55:03 -0700145
146 return patterns
147
148 def list(self, request):
149 object_list = self.filter_queryset(self.get_queryset())
150
151 serializer = self.get_serializer(object_list, many=True)
152
153 return Response({"subscribers": serializer.data})
154
155 def get_vcpe_synced(self, request, pk=None):
156 subscriber = self.get_object()
157 return Response({"vcpe_synced": subscriber.vcpe_synced})
158
159 def get_url_filter(self, request, pk=None):
160 subscriber = self.get_object()
161 return Response({"level": subscriber.url_filter_level})
162
163 def set_url_filter(self, request, pk=None, level=None):
164 subscriber = self.get_object()
165 subscriber.url_filter_level = level
166 subscriber.save()
167 return Response({"level": subscriber.url_filter_level})
168
169 def get_users(self, request, pk=None):
170 subscriber = self.get_object()
171 return Response(subscriber.users)
172
173 def get_user_level(self, request, pk=None, uid=None):
174 subscriber = self.get_object()
175 user = subscriber.find_user(uid)
176 if user and user.get("level", None):
177 level = user["level"]
178 else:
179 level = self.get_object().url_filter_level
180
181 return Response( {"id": uid, "level": level} )
182
183 def set_user_level(self, request, pk=None, uid=None, level=None):
184 subscriber = self.get_object()
185 subscriber.update_user(uid, level=level)
186 subscriber.save()
187 return self.get_user_level(request, pk, uid)
188
189 def create_user(self, request, pk=None):
190 data = request.DATA
191 name = data.get("name",None)
192 mac = data.get("mac",None)
193 if (not name):
194 raise XOSMissingField("name must be specified when creating user")
195 if (not mac):
196 raise XOSMissingField("mac must be specified when creating user")
197
198 subscriber = self.get_object()
199 newuser = subscriber.create_user(name=name, mac=mac)
200 subscriber.save()
201
202 return Response(newuser)
203
204 def delete_user(self, request, pk=None, uid=None):
205 subscriber = self.get_object()
206 subscriber.delete_user(uid)
207 subscriber.save()
208
209 return Response( {"id": uid, "deleted": True} )
210
211 def clear_users(self, request, pk=None):
212 subscriber = self.get_object()
213 subscriber.users = []
214 subscriber.save()
215
216 return Response( "Okay" )
217
218 def get_services(self, request, pk=None):
219 subscriber = self.get_object()
220 return Response(subscriber.services)
221
222 def get_service(self, request, pk=None, service=None):
223 service_attr = service+"_enable"
224 subscriber = self.get_object()
225 return Response({service: getattr(subscriber, service_attr)})
226
227 def enable_service(self, request, pk=None, service=None):
228 service_attr = service+"_enable"
229 subscriber = self.get_object()
230 setattr(subscriber, service_attr, True)
231 subscriber.save()
232 return Response({service: getattr(subscriber, service_attr)})
233
234 def disable_service(self, request, pk=None, service=None):
235 service_attr = service+"_enable"
236 subscriber = self.get_object()
237 setattr(subscriber, service_attr, False)
238 subscriber.save()
239 return Response({service: getattr(subscriber, service_attr)})
240
241 def get_bbsdump(self, request, pk=None):
242 subscriber = self.get_object()
243 if not subsciber.volt or not subscriber.volt.vcpe:
244 raise XOSMissingField("subscriber has no vCPE")
245 if not subscriber.volt.vcpe.bbs_account:
246 raise XOSMissingField("subscriber has no bbs_account")
247
248 result=subprocess.check_output(["python", "/opt/xos/observers/vcpe/broadbandshield.py", "dump", subscriber.volt.vcpe.bbs_account, "123"])
249 if request.GET.get("theformat",None)=="text":
250 from django.http import HttpResponse
251 return HttpResponse(result, content_type="text/plain")
252 else:
253 return Response( {"bbs_dump": result } )
254
255 def setup_demo_subscriber(self, subscriber):
256 # nuke the users and start over
257 subscriber.users = []
258 subscriber.create_user(name="Mom's PC", mac="010203040506", level="PG_13")
259 subscriber.create_user(name="Dad's PC", mac="90E2Ba82F975", level="PG_13")
260 subscriber.create_user(name="Jack's Laptop", mac="685B359D91D5", level="PG_13")
261 subscriber.create_user(name="Jill's Laptop", mac="34363BC9B6A6", level="PG_13")
262 subscriber.save()
263
264 def initdemo(self, request):
265 object_list = CordSubscriber.get_tenant_objects().all()
266
267 # reset the parental controls in any existing demo vCPEs
268 for o in object_list:
269 if str(o.service_specific_id) in ["0", "1"]:
270 self.setup_demo_subscriber(o)
271
272 demo_subscribers = [o for o in object_list if o.is_demo_user]
273
274 if demo_subscribers:
275 return Response({"id": demo_subscribers[0].id})
276
277 subscriber = CordSubscriberRoot(service_specific_id=1234,
278 name="demo-subscriber",)
279 subscriber.is_demo_user = True
280 subscriber.save()
281
282 self.setup_demo_subscriber(subscriber)
283
284 return Response({"id": subscriber.id})
285
286 def ssidlist(self, request):
287 object_list = CordSubscriber.get_tenant_objects().all()
288
289 ssidmap = [ {"service_specific_id": x.service_specific_id, "subscriber_id": x.id} for x in object_list ]
290
291 return Response({"ssidmap": ssidmap})
292
293 def ssiddetail(self, pk=None, ssid=None):
294 object_list = CordSubscriber.get_tenant_objects().all()
295
296 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) ]
297
298 if len(ssidmap)==0:
299 raise XOSNotFound("didn't find ssid %s" % str(ssid))
300
301 return Response( ssidmap[0] )
302