diff --git a/uncloud/urls.py b/uncloud/urls.py index bc24d81..7e8167d 100644 --- a/uncloud/urls.py +++ b/uncloud/urls.py @@ -41,10 +41,6 @@ router.register(r'v1/service/matrix', serviceviews.MatrixServiceProductViewSet, router.register(r'v1/service/generic', serviceviews.GenericServiceProductViewSet, basename='genericserviceproduct') -# Net -#router.register(r'v1/net/vpn', netviews.VPNNetworkViewSet, basename='vpnnetwork') -#router.register(r'v1/admin/vpnreservation', netviews.VPNNetworkReservationViewSet, basename='vpnnetreservation') - # Pay router.register(r'v1/my/address', payviews.BillingAddressViewSet, basename='billingaddress') @@ -67,9 +63,18 @@ router.register(r'v1/my/user', authviews.UserViewSet, basename='user') router.register(r'v1/admin/user', authviews.AdminUserViewSet, basename='useradmin') router.register(r'v1/user/register', authviews.AccountManagementViewSet, basename='user/register') + +################################################################################ +# v2 + +# Net +router.register(r'v2/net/wireguardvpn', netviews.WireGuardVPNViewSet, basename='wireguardvpnnetwork') +#router.register(r'v1/admin/vpnreservation', netviews.VPNNetworkReservationViewSet, basename='vpnnetreservation') + + + urlpatterns = [ path(r'api/', include(router.urls)), - # web/ = stuff to view in the browser path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), # for login to REST API path('openapi', get_schema_view( @@ -77,7 +82,9 @@ urlpatterns = [ description="uncloud API", version="1.0.0" ), name='openapi-schema'), - path('vpn/create/', netviews.WireGuardVPNCreateView.as_view(), name="vpncreate"), + + # web/ = stuff to view in the browser +# path('web/vpn/create/', netviews.WireGuardVPNCreateView.as_view(), name="vpncreate"), path('login/', authviews.LoginView.as_view(), name="login"), path('logout/', authviews.LogoutView.as_view(), name="logout"), diff --git a/uncloud_net/forms.py b/uncloud_net/forms.py index 4bdcd79..ad4e013 100644 --- a/uncloud_net/forms.py +++ b/uncloud_net/forms.py @@ -8,5 +8,4 @@ class WireGuardVPNForm(forms.ModelForm): class Meta: model = WireGuardVPN - fields = [ "wireguard_public_key" ] diff --git a/uncloud_net/models.py b/uncloud_net/models.py index 819d3b8..2f573bd 100644 --- a/uncloud_net/models.py +++ b/uncloud_net/models.py @@ -29,6 +29,8 @@ class WireGuardVPN(models.Model): """ Created VPNNetworks """ + owner = models.ForeignKey(get_user_model(), + on_delete=models.CASCADE) vpnpool = models.ForeignKey(WireGuardVPNPool, on_delete=models.CASCADE) diff --git a/uncloud_net/selectors.py b/uncloud_net/selectors.py index b2f697c..70fafd2 100644 --- a/uncloud_net/selectors.py +++ b/uncloud_net/selectors.py @@ -39,4 +39,6 @@ def allowed_vpn_network_reservation_size(): max_reservations=2**(F('subnetwork_mask')-F('network_mask'))).filter( num_reservations__lt=F('max_reservations')) - return set([ pool.subnetwork_mask for pool in pools ]) + # Need to return set of tuples, see + # https://docs.djangoproject.com/en/3.1/ref/models/fields/#field-choices + return set([ (pool.subnetwork_mask, pool.subnetwork_mask) for pool in pools ]) diff --git a/uncloud_net/serializers.py b/uncloud_net/serializers.py index e2555d5..8c6c567 100644 --- a/uncloud_net/serializers.py +++ b/uncloud_net/serializers.py @@ -5,6 +5,16 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from .models import * +from .services import * + +class WireGuardVPNSerializer(serializers.ModelSerializer): + class Meta: + model = WireGuardVPN + fields = [ 'wireguard_public_key' ] + read_only_fields = [ 'address ' ] + + def create(self, validated_data): + pass # class WireGuardVPNPoolSerializer(serializers.ModelSerializer): # class Meta: diff --git a/uncloud_net/services.py b/uncloud_net/services.py index 68c1e79..45e14c9 100644 --- a/uncloud_net/services.py +++ b/uncloud_net/services.py @@ -1,59 +1,35 @@ from django.db import transaction + from .models import * +from .selectors import * @transaction.atomic -def create_vpn(*, +def create_wireguard_vpn(*, public_key: str, - network_size: int - ) -> VPNNetwork: + network_mask: int + ) -> WireGuardVPN: - # Select suitable pool - pools = VPNPool.objects.filter(subnetwork_size=network_size) + pool = get_suitable_pool(network_mask)[0] # FIXME: exception - which? if not pools: return None + # last_net = ipaddress.ip_network(self.used_networks.last().address) + # last_net_ip = last_net[0] - # Find all pools with the correct size + # if last_net_ip.version == 6: + # offset_to_next = 2**(128 - self.subnetwork_size) + # elif last_net_ip.version == 4: + # offset_to_next = 2**(32 - self.subnetwork_size) - # For each pool see if it has still space: - # num network reversations < 2**(subnetwork_size-network_size) + # next_net_ip = last_net_ip + offset_to_next - - def next_free_network(self): - if self.num_free_networks == 0: - # FIXME: use right exception - raise Exception("No free networks") - - if len(self.free_networks) > 0: - return self.free_networks[0].address - - if len(self.used_networks) > 0: - """ - sample: - - pool = 2a0a:e5c1:200::/40 - last_used = 2a0a:e5c1:204::/48 - - next: - """ - - last_net = ipaddress.ip_network(self.used_networks.last().address) - last_net_ip = last_net[0] - - if last_net_ip.version == 6: - offset_to_next = 2**(128 - self.subnetwork_size) - elif last_net_ip.version == 4: - offset_to_next = 2**(32 - self.subnetwork_size) - - next_net_ip = last_net_ip + offset_to_next - - return str(next_net_ip) - else: - # first network to be created - return self.network + # return str(next_net_ip) + # else: + # # first network to be created + # return self.network @property def wireguard_config_filename(self): diff --git a/uncloud_net/views.py b/uncloud_net/views.py index d52b076..dee3fac 100644 --- a/uncloud_net/views.py +++ b/uncloud_net/views.py @@ -23,17 +23,17 @@ from .forms import * # queryset = VPNNetworkReservation.objects.all() -# class VPNNetworkViewSet(viewsets.ModelViewSet): -# serializer_class = VPNNetworkSerializer -# permission_classes = [permissions.IsAuthenticated] +class WireGuardVPNViewSet(viewsets.ModelViewSet): + serializer_class = WireGuardVPNSerializer + permission_classes = [permissions.IsAuthenticated] -# def get_queryset(self): -# if self.request.user.is_superuser: -# obj = VPNNetwork.objects.all() -# else: -# obj = VPNNetwork.objects.filter(owner=self.request.user) + def get_queryset(self): + if self.request.user.is_superuser: + obj = WireGuardVPN.objects.all() + else: + obj = WireGuardVPN.objects.filter(owner=self.request.user) -# return obj + return obj class WireGuardVPNCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): @@ -49,7 +49,14 @@ class WireGuardVPNCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView return self.success_message % dict(cleaned_data, the_prefix = self.object.prefix) - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['available_sizes'] = 2 - return context + # def get_context_data(self, **kwargs): + # context = super().get_context_data(**kwargs) + # context['available_sizes'] = 2 + # return context + + # def post(request, *args, **kwargs): + # print(request) + # print(*args) + # print(*kwargs) + + # def post(self, request, *args, **kwargs):