in between commit

Signed-off-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
This commit is contained in:
Nico Schottelius 2020-04-08 16:24:39 +02:00
parent 3d2f8574d3
commit d3f2a3e071
4 changed files with 125 additions and 21 deletions

View File

@ -11,3 +11,6 @@ parsedatetime
pyparsing
pydot
django-extensions
# PDF creating
django-hardcopy

View File

@ -13,32 +13,52 @@ log = logging.getLogger(__name__)
wireguard_template="""
[Interface]
ListenPort = 51820
PrivateKey = {privatekey}
"""
# Nico, 2019-01-23, Switzerland
#[Peer]
#PublicKey = kL1S/Ipq6NkFf1MAsNRou4b9VoUsnnb4ZxgiBrH0zA8=
#AllowedIPs = 2a0a:e5c1:101::/48
peer_template="""
# {username}
[Peer]
PublicKey = {public_key}
AllowedIPs = {vpnnetwork}
"""
class Command(BaseCommand):
help = 'General uncloud commands'
def add_arguments(self, parser):
parser.add_argument('--hostname', action='store_true', help='Name of this VPN Host',
parser.add_argument('--hostname',
action='store_true',
help='Name of this VPN Host',
required=True)
def handle(self, *args, **options):
# for net
if options['bootstrap']:
self.bootstrap()
self.create_vpn_config(options['hostname'])
def create_vpn_config(self, hostname):
for pool in VPNPool.objects.filter(vpn_hostname
default_cluster = VPNNetwork.objects.get_or_create(name="default")
# local_host =
configs = []
for pool in VPNPool.objects.filter(vpn_hostname=hostname):
pool_config = {
'private_key': pool.wireguard_private_key,
'subnetwork_size': pool.subnetwork_size,
'config_file': '/etc/wireguard/{}.conf'.format(pool.network),
'peers': []
}
for vpnnetwork in VPNNetworkReservation.objects.filter(vpnpool=pool):
pool_config['peers'].append({
'vpnnetwork': "{}/{}".format(vpnnetwork.address,
pool_config['subnetwork_size']),
'public_key': vpnnetwork.wireguard_public_key,
}
)
configs.append(pool_config)
print(configs)

View File

@ -23,13 +23,73 @@ class VPNPool(UncloudModel):
network_size = models.IntegerField(validators=[MinValueValidator(0),
MaxValueValidator(128)])
subnetwork_size = models.IntegerField(validators=[MinValueValidator(0),
MaxValueValidator(128)])
subnetwork_size = models.IntegerField(validators=[
MinValueValidator(0),
MaxValueValidator(128)
])
vpn_hostname = models.CharField(max_length=256)
wireguard_private_key = models.CharField(max_length=48)
@property
def num_maximum_networks(self):
"""
sample:
network_size = 40
subnetwork_size = 48
maximum_networks = 2^(48-40)
2nd sample:
network_size = 8
subnetwork_size = 24
maximum_networks = 2^(24-8)
"""
return 2**(subnetwork_size - network_size)
@property
def used_networks(self):
return self.vpnnetworkreservation_set.objects.filter(vpnpool=self, status='used')
@property
def num_used_networks(self):
return len(self.used_networks)
@property
def num_free_networks(self):
return self.num_maximum_networks - self.num_used_networks
@property
def next_free_network(self):
free_net = self.vpnnetworkreservation_set.objects.filter(vpnpool=self,
status='free')
last_net = self.vpnnetworkreservation_set.objects.filter(vpnpool=self,
status='used')
if num_free_networks == 0:
raise Exception("No free networks")
if len(free_net) > 0:
return free_net[0].address
if len(used_net) > 0:
"""
sample:
pool = 2a0a:e5c1:200::/40
last_used = 2a0a:e5c1:204::/48
next:
"""
last_ip = last_net.address
# next_ip =
class VPNNetworkReservation(UncloudModel):
"""
@ -37,9 +97,15 @@ class VPNNetworkReservation(UncloudModel):
"""
vpnpool = models.ForeignKey(VPNPool,
on_delete=models.CASCADE)
address = models.GenericIPAddressField(primary_key=True)
status = models.CharField(max_length=256,
choices = (
('used', 'used'),
('free', 'free')
)
)
class VPNNetwork(Product):
"""

View File

@ -12,7 +12,6 @@ class VPNPoolSerializer(serializers.ModelSerializer):
fields = '__all__'
class VPNNetworkSerializer(serializers.ModelSerializer):
class Meta:
model = VPNNetwork
fields = '__all__'
@ -53,8 +52,24 @@ class VPNNetworkSerializer(serializers.ModelSerializer):
msg = _("No pool available for networks with size = {}. Available are: {}".format(data['network_size'], sizes))
raise serializers.ValidationError(msg)
return data
def create(self, validated_data):
from_pool =
"""
Creating a new vpnnetwork - there are a couple of race conditions,
especially when run in parallel.
"""
pools = VPNPool.objects.filter(subnetwork_size=data['network_size'])
found_pool = False
for pool in pools:
if pool.num_free_networks > 0:
found_pool = True
# address = pool.
# reservation = VPNNetworkReservation(vpnpool=pool,
pool = VPNPool.objects.first(subnetwork_size=data['network_size'])
return VPNNetwork(**validated_data)