blob: 33fb4296336c719247d603d488ae7e7578c8473b [file] [log] [blame]
Jeremy Mowery8b664f72015-12-04 11:52:16 -07001from core.models import Service, TenantWithContainer
2from django.db import transaction
Jeremy Moweryc951d5b2016-01-08 17:07:46 -07003from typing import Mapping, Tuple
Jeremy Mowery8b664f72015-12-04 11:52:16 -07004
5VPN_KIND = "vpn"
6
Jeremy Mowery82760822016-01-08 16:36:22 -07007
Jeremy Mowery8b664f72015-12-04 11:52:16 -07008class VPNService(Service):
Jeremy Mowery82760822016-01-08 16:36:22 -07009 """Defines the Service for creating VPN servers."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070010 KIND = VPN_KIND
11
12 class Meta:
13 proxy = True
14 # The name used to find this service, all directories are named this
15 app_label = "vpn"
16 verbose_name = "VPN Service"
17
Jeremy Mowery82760822016-01-08 16:36:22 -070018
Jeremy Mowery7ced7382015-12-04 23:58:38 -070019class VPNTenant(TenantWithContainer):
Jeremy Mowery82760822016-01-08 16:36:22 -070020 """Defines the Tenant for creating VPN servers."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070021
22 class Meta:
23 proxy = True
24 verbose_name = "VPN Tenant"
25
26 KIND = VPN_KIND
27
28 sync_attributes = ("nat_ip", "nat_mac",)
29
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -070030 default_attributes = {'server_key': 'Error key not found',
31 'client_conf': 'Configuration not found',
32 'server_address': '10.8.0.1',
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -070033 'client_address': '10.8.0.2',
34 'can_view_subnet': False,
35 'is_persistent': True}
Jeremy Mowery8b664f72015-12-04 11:52:16 -070036
37 def __init__(self, *args, **kwargs):
38 vpn_services = VPNService.get_service_objects().all()
39 if vpn_services:
40 self._meta.get_field(
41 "provider_service").default = vpn_services[0].id
42 super(VPNTenant, self).__init__(*args, **kwargs)
43
44 def save(self, *args, **kwargs):
45 super(VPNTenant, self).save(*args, **kwargs)
46 model_policy_vpn_tenant(self.pk)
47
48 def delete(self, *args, **kwargs):
49 self.cleanup_container()
50 super(VPNTenant, self).delete(*args, **kwargs)
51
52 @property
53 def server_key(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070054 """str: The server_key used to connect to the VPN server."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070055 return self.get_attribute(
56 "server_key",
57 self.default_attributes['server_key'])
58
Jeremy Mowery00dc8e72015-12-04 15:28:40 -070059 @server_key.setter
Jeremy Mowerya8ce9372015-12-07 13:38:15 -070060 def server_key(self, value):
Jeremy Mowery8b664f72015-12-04 11:52:16 -070061 self.set_attribute("server_key", value)
62
63 @property
64 def addresses(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070065 """Mapping[str, Tuple[str, str, str]]: The ip, mac address, and subnet of networks of this Tenant."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070066 if (not self.id) or (not self.instance):
67 return {}
68
69 addresses = {}
70 # The ports field refers to networks for the instance.
71 # This loop stores the details for the NAT network that will be
72 # necessary for ansible.
73 for ns in self.instance.ports.all():
74 if "nat" in ns.network.name.lower():
Jeremy Mowerya9b673b2016-01-07 21:25:50 -070075 addresses["nat"] = (ns.ip, ns.mac, ns.network.subnet)
Jeremy Mowery8b664f72015-12-04 11:52:16 -070076 return addresses
77
78 # This getter is necessary because nat_ip is a sync_attribute
79 @property
80 def nat_ip(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070081 """str: The IP of this Tenant on the NAT network."""
Jeremy Mowerya9b673b2016-01-07 21:25:50 -070082 return self.addresses.get("nat", (None, None, None))[0]
Jeremy Mowery8b664f72015-12-04 11:52:16 -070083
84 # This getter is necessary because nat_mac is a sync_attribute
85 @property
86 def nat_mac(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070087 """str: The MAC address of this Tenant on the NAT network."""
Jeremy Mowerya9b673b2016-01-07 21:25:50 -070088 return self.addresses.get("nat", (None, None, None))[1]
89
90 @property
91 def subnet(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070092 """str: The subnet of this Tenant on the NAT network."""
Jeremy Mowerya9b673b2016-01-07 21:25:50 -070093 return self.addresses.get("nat", (None, None, None))[2]
Jeremy Mowery8b664f72015-12-04 11:52:16 -070094
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -070095 @property
96 def server_address(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070097 """str: The IP address of the server on the VPN."""
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -070098 return self.get_attribute(
99 'server_address',
100 self.default_attributes['server_address'])
101
102 @server_address.setter
103 def server_address(self, value):
104 self.set_attribute("server_address", value)
105
106 @property
107 def client_address(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700108 """str: The IP address of the client on the VPN."""
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700109 return self.get_attribute(
110 'client_address',
111 self.default_attributes['client_address'])
112
113 @client_address.setter
114 def client_address(self, value):
115 self.set_attribute("client_address", value)
116
117 @property
118 def client_conf(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700119 """str: The client configuration for the client to connect to this server."""
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700120 return self.get_attribute(
121 "client_conf",
122 self.default_attributes['client_conf'])
123
124 @client_conf.setter
125 def client_conf(self, value):
126 self.set_attribute("client_conf", value)
127
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700128 @property
129 def is_persistent(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700130 """bool: True if the VPN connection is persistence, false otherwise."""
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700131 return self.get_attribute(
132 "is_persistent",
133 self.default_attributes['is_persistent'])
134
135 @is_persistent.setter
136 def is_persistent(self, value):
137 self.set_attribute("is_persistent", value)
138
139 @property
140 def can_view_subnet(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700141 """bool: True if the client can see the subnet of the server, false otherwise."""
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700142 return self.get_attribute(
143 "can_view_subnet",
144 self.default_attributes['can_view_subnet'])
145
146 @can_view_subnet.setter
147 def can_view_subnet(self, value):
148 self.set_attribute("can_view_subnet", value)
149
Jeremy Mowery8b664f72015-12-04 11:52:16 -0700150
151def model_policy_vpn_tenant(pk):
Jeremy Mowery82760822016-01-08 16:36:22 -0700152 """Manages the contain for the VPN Tenant."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -0700153 # This section of code is atomic to prevent race conditions
154 with transaction.atomic():
155 # We find all of the tenants that are waiting to update
156 tenant = VPNTenant.objects.select_for_update().filter(pk=pk)
157 if not tenant:
158 return
159 # Since this code is atomic it is safe to always use the first tenant
160 tenant = tenant[0]
161 tenant.manage_container()