We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
API call to add VPN tunnel fails: group field is required
### Deployment Type

Self-hosted

### NetBox Version

v3.7.2

### Python Version

3.11

### Steps to Reproduce

```
$ curl -s -i http://netbox-test.lein.io/api/vpn/tunnels/ \
-H "Authorization: Token 176d4c04ccc8f2a549ea6fd393567d9da5a796ff" \
-H "Content-type: application/json" \
-H "Accept: application/json; indent=4" \
-d '{"name":"TestTunnel", "encapsulation":"ipsec-tunnel", "status":"active"}'
```

### Expected Behavior

Tunnel "TestTunnel" is added successfully.

### Observed Behavior

```
HTTP/1.1 400 Bad Request
API-Version: 3.7
...
{
    "group": [
        "This field is required."
    ]
}
```

Adding the same tunnel in GUI is successful (using only those three mandatory fields).

### Workaround

Create a tunnel group like "TEMP", then add `"group":1` (where 1 is the group ID) in the create call, and finally edit the resulted tunnel to remove the TEMP group.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `netbox/vpn/api/serializers.py`
Content:
```
1 from django.contrib.contenttypes.models import ContentType
2 from drf_spectacular.utils import extend_schema_field
3 from rest_framework import serializers
4 
5 from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedRouteTargetSerializer
6 from ipam.models import RouteTarget
7 from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
8 from netbox.api.serializers import NetBoxModelSerializer
9 from netbox.constants import NESTED_SERIALIZER_PREFIX
10 from tenancy.api.nested_serializers import NestedTenantSerializer
11 from utilities.api import get_serializer_for_model
12 from vpn.choices import *
13 from vpn.models import *
14 from .nested_serializers import *
15 
16 __all__ = (
17     'IKEPolicySerializer',
18     'IKEProposalSerializer',
19     'IPSecPolicySerializer',
20     'IPSecProfileSerializer',
21     'IPSecProposalSerializer',
22     'L2VPNSerializer',
23     'L2VPNTerminationSerializer',
24     'TunnelGroupSerializer',
25     'TunnelSerializer',
26     'TunnelTerminationSerializer',
27 )
28 
29 
30 class TunnelGroupSerializer(NetBoxModelSerializer):
31     url = serializers.HyperlinkedIdentityField(view_name='vpn-api:tunnelgroup-detail')
32     tunnel_count = serializers.IntegerField(read_only=True)
33 
34     class Meta:
35         model = TunnelGroup
36         fields = [
37             'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
38             'tunnel_count',
39         ]
40 
41 
42 class TunnelSerializer(NetBoxModelSerializer):
43     url = serializers.HyperlinkedIdentityField(
44         view_name='vpn-api:tunnel-detail'
45     )
46     status = ChoiceField(
47         choices=TunnelStatusChoices
48     )
49     group = NestedTunnelGroupSerializer()
50     encapsulation = ChoiceField(
51         choices=TunnelEncapsulationChoices
52     )
53     ipsec_profile = NestedIPSecProfileSerializer(
54         required=False,
55         allow_null=True
56     )
57     tenant = NestedTenantSerializer(
58         required=False,
59         allow_null=True
60     )
61 
62     class Meta:
63         model = Tunnel
64         fields = (
65             'id', 'url', 'display', 'name', 'status', 'group', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id',
66             'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
67         )
68 
69 
70 class TunnelTerminationSerializer(NetBoxModelSerializer):
71     url = serializers.HyperlinkedIdentityField(
72         view_name='vpn-api:tunneltermination-detail'
73     )
74     tunnel = NestedTunnelSerializer()
75     role = ChoiceField(
76         choices=TunnelTerminationRoleChoices
77     )
78     termination_type = ContentTypeField(
79         queryset=ContentType.objects.all()
80     )
81     termination = serializers.SerializerMethodField(
82         read_only=True
83     )
84     outside_ip = NestedIPAddressSerializer(
85         required=False,
86         allow_null=True
87     )
88 
89     class Meta:
90         model = TunnelTermination
91         fields = (
92             'id', 'url', 'display', 'tunnel', 'role', 'termination_type', 'termination_id', 'termination', 'outside_ip',
93             'tags', 'custom_fields', 'created', 'last_updated',
94         )
95 
96     @extend_schema_field(serializers.JSONField(allow_null=True))
97     def get_termination(self, obj):
98         serializer = get_serializer_for_model(obj.termination, prefix=NESTED_SERIALIZER_PREFIX)
99         context = {'request': self.context['request']}
100         return serializer(obj.termination, context=context).data
101 
102 
103 class IKEProposalSerializer(NetBoxModelSerializer):
104     url = serializers.HyperlinkedIdentityField(
105         view_name='vpn-api:ikeproposal-detail'
106     )
107     authentication_method = ChoiceField(
108         choices=AuthenticationMethodChoices
109     )
110     encryption_algorithm = ChoiceField(
111         choices=EncryptionAlgorithmChoices
112     )
113     authentication_algorithm = ChoiceField(
114         choices=AuthenticationAlgorithmChoices
115     )
116     group = ChoiceField(
117         choices=DHGroupChoices
118     )
119 
120     class Meta:
121         model = IKEProposal
122         fields = (
123             'id', 'url', 'display', 'name', 'description', 'authentication_method', 'encryption_algorithm',
124             'authentication_algorithm', 'group', 'sa_lifetime', 'comments', 'tags', 'custom_fields', 'created',
125             'last_updated',
126         )
127 
128 
129 class IKEPolicySerializer(NetBoxModelSerializer):
130     url = serializers.HyperlinkedIdentityField(
131         view_name='vpn-api:ikepolicy-detail'
132     )
133     version = ChoiceField(
134         choices=IKEVersionChoices
135     )
136     mode = ChoiceField(
137         choices=IKEModeChoices
138     )
139     proposals = SerializedPKRelatedField(
140         queryset=IKEProposal.objects.all(),
141         serializer=NestedIKEProposalSerializer,
142         required=False,
143         many=True
144     )
145 
146     class Meta:
147         model = IKEPolicy
148         fields = (
149             'id', 'url', 'display', 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'comments',
150             'tags', 'custom_fields', 'created', 'last_updated',
151         )
152 
153 
154 class IPSecProposalSerializer(NetBoxModelSerializer):
155     url = serializers.HyperlinkedIdentityField(
156         view_name='vpn-api:ipsecproposal-detail'
157     )
158     encryption_algorithm = ChoiceField(
159         choices=EncryptionAlgorithmChoices
160     )
161     authentication_algorithm = ChoiceField(
162         choices=AuthenticationAlgorithmChoices
163     )
164 
165     class Meta:
166         model = IPSecProposal
167         fields = (
168             'id', 'url', 'display', 'name', 'description', 'encryption_algorithm', 'authentication_algorithm',
169             'sa_lifetime_seconds', 'sa_lifetime_data', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
170         )
171 
172 
173 class IPSecPolicySerializer(NetBoxModelSerializer):
174     url = serializers.HyperlinkedIdentityField(
175         view_name='vpn-api:ipsecpolicy-detail'
176     )
177     proposals = SerializedPKRelatedField(
178         queryset=IPSecProposal.objects.all(),
179         serializer=NestedIPSecProposalSerializer,
180         required=False,
181         many=True
182     )
183     pfs_group = ChoiceField(
184         choices=DHGroupChoices,
185         required=False
186     )
187 
188     class Meta:
189         model = IPSecPolicy
190         fields = (
191             'id', 'url', 'display', 'name', 'description', 'proposals', 'pfs_group', 'comments', 'tags',
192             'custom_fields', 'created', 'last_updated',
193         )
194 
195 
196 class IPSecProfileSerializer(NetBoxModelSerializer):
197     url = serializers.HyperlinkedIdentityField(
198         view_name='vpn-api:ipsecprofile-detail'
199     )
200     mode = ChoiceField(
201         choices=IPSecModeChoices
202     )
203     ike_policy = NestedIKEPolicySerializer()
204     ipsec_policy = NestedIPSecPolicySerializer()
205 
206     class Meta:
207         model = IPSecProfile
208         fields = (
209             'id', 'url', 'display', 'name', 'description', 'mode', 'ike_policy', 'ipsec_policy', 'comments', 'tags',
210             'custom_fields', 'created', 'last_updated',
211         )
212 
213 
214 #
215 # L2VPN
216 #
217 
218 class L2VPNSerializer(NetBoxModelSerializer):
219     url = serializers.HyperlinkedIdentityField(view_name='vpn-api:l2vpn-detail')
220     type = ChoiceField(choices=L2VPNTypeChoices, required=False)
221     import_targets = SerializedPKRelatedField(
222         queryset=RouteTarget.objects.all(),
223         serializer=NestedRouteTargetSerializer,
224         required=False,
225         many=True
226     )
227     export_targets = SerializedPKRelatedField(
228         queryset=RouteTarget.objects.all(),
229         serializer=NestedRouteTargetSerializer,
230         required=False,
231         many=True
232     )
233     tenant = NestedTenantSerializer(required=False, allow_null=True)
234 
235     class Meta:
236         model = L2VPN
237         fields = [
238             'id', 'url', 'display', 'identifier', 'name', 'slug', 'type', 'import_targets', 'export_targets',
239             'description', 'comments', 'tenant', 'tags', 'custom_fields', 'created', 'last_updated'
240         ]
241 
242 
243 class L2VPNTerminationSerializer(NetBoxModelSerializer):
244     url = serializers.HyperlinkedIdentityField(view_name='vpn-api:l2vpntermination-detail')
245     l2vpn = NestedL2VPNSerializer()
246     assigned_object_type = ContentTypeField(
247         queryset=ContentType.objects.all()
248     )
249     assigned_object = serializers.SerializerMethodField(read_only=True)
250 
251     class Meta:
252         model = L2VPNTermination
253         fields = [
254             'id', 'url', 'display', 'l2vpn', 'assigned_object_type', 'assigned_object_id',
255             'assigned_object', 'tags', 'custom_fields', 'created', 'last_updated'
256         ]
257 
258     @extend_schema_field(serializers.JSONField(allow_null=True))
259     def get_assigned_object(self, instance):
260         serializer = get_serializer_for_model(instance.assigned_object, prefix=NESTED_SERIALIZER_PREFIX)
261         context = {'request': self.context['request']}
262         return serializer(instance.assigned_object, context=context).data
263
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/netbox/vpn/api/serializers.py b/netbox/vpn/api/serializers.py
--- a/netbox/vpn/api/serializers.py
+++ b/netbox/vpn/api/serializers.py
@@ -46,7 +46,10 @@
     status = ChoiceField(
         choices=TunnelStatusChoices
     )
-    group = NestedTunnelGroupSerializer()
+    group = NestedTunnelGroupSerializer(
+        required=False,
+        allow_null=True
+    )
     encapsulation = ChoiceField(
         choices=TunnelEncapsulationChoices
     )

{"golden_diff": "diff --git a/netbox/vpn/api/serializers.py b/netbox/vpn/api/serializers.py\n--- a/netbox/vpn/api/serializers.py\n+++ b/netbox/vpn/api/serializers.py\n@@ -46,7 +46,10 @@\n     status = ChoiceField(\n         choices=TunnelStatusChoices\n     )\n-    group = NestedTunnelGroupSerializer()\n+    group = NestedTunnelGroupSerializer(\n+        required=False,\n+        allow_null=True\n+    )\n     encapsulation = ChoiceField(\n         choices=TunnelEncapsulationChoices\n     )\n", "issue": "API call to add VPN tunnel fails: group field is required\n### Deployment Type\r\n\r\nSelf-hosted\r\n\r\n### NetBox Version\r\n\r\nv3.7.2\r\n\r\n### Python Version\r\n\r\n3.11\r\n\r\n### Steps to Reproduce\r\n\r\n```\r\n$ curl -s -i http://netbox-test.lein.io/api/vpn/tunnels/ \\\r\n-H \"Authorization: Token 176d4c04ccc8f2a549ea6fd393567d9da5a796ff\" \\\r\n-H \"Content-type: application/json\" \\\r\n-H \"Accept: application/json; indent=4\" \\\r\n-d '{\"name\":\"TestTunnel\", \"encapsulation\":\"ipsec-tunnel\", \"status\":\"active\"}'\r\n```\r\n\r\n### Expected Behavior\r\n\r\nTunnel \"TestTunnel\" is added successfully.\r\n\r\n### Observed Behavior\r\n\r\n```\r\nHTTP/1.1 400 Bad Request\r\nAPI-Version: 3.7\r\n...\r\n{\r\n    \"group\": [\r\n        \"This field is required.\"\r\n    ]\r\n}\r\n```\r\n\r\nAdding the same tunnel in GUI is successful (using only those three mandatory fields).\r\n\r\n### Workaround\r\n\r\nCreate a tunnel group like \"TEMP\", then add `\"group\":1` (where 1 is the group ID) in the create call, and finally edit the resulted tunnel to remove the TEMP group.\n", "before_files": [{"content": "from django.contrib.contenttypes.models import ContentType\nfrom drf_spectacular.utils import extend_schema_field\nfrom rest_framework import serializers\n\nfrom ipam.api.nested_serializers import NestedIPAddressSerializer, NestedRouteTargetSerializer\nfrom ipam.models import RouteTarget\nfrom netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField\nfrom netbox.api.serializers import NetBoxModelSerializer\nfrom netbox.constants import NESTED_SERIALIZER_PREFIX\nfrom tenancy.api.nested_serializers import NestedTenantSerializer\nfrom utilities.api import get_serializer_for_model\nfrom vpn.choices import *\nfrom vpn.models import *\nfrom .nested_serializers import *\n\n__all__ = (\n    'IKEPolicySerializer',\n    'IKEProposalSerializer',\n    'IPSecPolicySerializer',\n    'IPSecProfileSerializer',\n    'IPSecProposalSerializer',\n    'L2VPNSerializer',\n    'L2VPNTerminationSerializer',\n    'TunnelGroupSerializer',\n    'TunnelSerializer',\n    'TunnelTerminationSerializer',\n)\n\n\nclass TunnelGroupSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(view_name='vpn-api:tunnelgroup-detail')\n    tunnel_count = serializers.IntegerField(read_only=True)\n\n    class Meta:\n        model = TunnelGroup\n        fields = [\n            'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',\n            'tunnel_count',\n        ]\n\n\nclass TunnelSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:tunnel-detail'\n    )\n    status = ChoiceField(\n        choices=TunnelStatusChoices\n    )\n    group = NestedTunnelGroupSerializer()\n    encapsulation = ChoiceField(\n        choices=TunnelEncapsulationChoices\n    )\n    ipsec_profile = NestedIPSecProfileSerializer(\n        required=False,\n        allow_null=True\n    )\n    tenant = NestedTenantSerializer(\n        required=False,\n        allow_null=True\n    )\n\n    class Meta:\n        model = Tunnel\n        fields = (\n            'id', 'url', 'display', 'name', 'status', 'group', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id',\n            'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass TunnelTerminationSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:tunneltermination-detail'\n    )\n    tunnel = NestedTunnelSerializer()\n    role = ChoiceField(\n        choices=TunnelTerminationRoleChoices\n    )\n    termination_type = ContentTypeField(\n        queryset=ContentType.objects.all()\n    )\n    termination = serializers.SerializerMethodField(\n        read_only=True\n    )\n    outside_ip = NestedIPAddressSerializer(\n        required=False,\n        allow_null=True\n    )\n\n    class Meta:\n        model = TunnelTermination\n        fields = (\n            'id', 'url', 'display', 'tunnel', 'role', 'termination_type', 'termination_id', 'termination', 'outside_ip',\n            'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n    @extend_schema_field(serializers.JSONField(allow_null=True))\n    def get_termination(self, obj):\n        serializer = get_serializer_for_model(obj.termination, prefix=NESTED_SERIALIZER_PREFIX)\n        context = {'request': self.context['request']}\n        return serializer(obj.termination, context=context).data\n\n\nclass IKEProposalSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ikeproposal-detail'\n    )\n    authentication_method = ChoiceField(\n        choices=AuthenticationMethodChoices\n    )\n    encryption_algorithm = ChoiceField(\n        choices=EncryptionAlgorithmChoices\n    )\n    authentication_algorithm = ChoiceField(\n        choices=AuthenticationAlgorithmChoices\n    )\n    group = ChoiceField(\n        choices=DHGroupChoices\n    )\n\n    class Meta:\n        model = IKEProposal\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'authentication_method', 'encryption_algorithm',\n            'authentication_algorithm', 'group', 'sa_lifetime', 'comments', 'tags', 'custom_fields', 'created',\n            'last_updated',\n        )\n\n\nclass IKEPolicySerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ikepolicy-detail'\n    )\n    version = ChoiceField(\n        choices=IKEVersionChoices\n    )\n    mode = ChoiceField(\n        choices=IKEModeChoices\n    )\n    proposals = SerializedPKRelatedField(\n        queryset=IKEProposal.objects.all(),\n        serializer=NestedIKEProposalSerializer,\n        required=False,\n        many=True\n    )\n\n    class Meta:\n        model = IKEPolicy\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'comments',\n            'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass IPSecProposalSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ipsecproposal-detail'\n    )\n    encryption_algorithm = ChoiceField(\n        choices=EncryptionAlgorithmChoices\n    )\n    authentication_algorithm = ChoiceField(\n        choices=AuthenticationAlgorithmChoices\n    )\n\n    class Meta:\n        model = IPSecProposal\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'encryption_algorithm', 'authentication_algorithm',\n            'sa_lifetime_seconds', 'sa_lifetime_data', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass IPSecPolicySerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ipsecpolicy-detail'\n    )\n    proposals = SerializedPKRelatedField(\n        queryset=IPSecProposal.objects.all(),\n        serializer=NestedIPSecProposalSerializer,\n        required=False,\n        many=True\n    )\n    pfs_group = ChoiceField(\n        choices=DHGroupChoices,\n        required=False\n    )\n\n    class Meta:\n        model = IPSecPolicy\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'proposals', 'pfs_group', 'comments', 'tags',\n            'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass IPSecProfileSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ipsecprofile-detail'\n    )\n    mode = ChoiceField(\n        choices=IPSecModeChoices\n    )\n    ike_policy = NestedIKEPolicySerializer()\n    ipsec_policy = NestedIPSecPolicySerializer()\n\n    class Meta:\n        model = IPSecProfile\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'mode', 'ike_policy', 'ipsec_policy', 'comments', 'tags',\n            'custom_fields', 'created', 'last_updated',\n        )\n\n\n#\n# L2VPN\n#\n\nclass L2VPNSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(view_name='vpn-api:l2vpn-detail')\n    type = ChoiceField(choices=L2VPNTypeChoices, required=False)\n    import_targets = SerializedPKRelatedField(\n        queryset=RouteTarget.objects.all(),\n        serializer=NestedRouteTargetSerializer,\n        required=False,\n        many=True\n    )\n    export_targets = SerializedPKRelatedField(\n        queryset=RouteTarget.objects.all(),\n        serializer=NestedRouteTargetSerializer,\n        required=False,\n        many=True\n    )\n    tenant = NestedTenantSerializer(required=False, allow_null=True)\n\n    class Meta:\n        model = L2VPN\n        fields = [\n            'id', 'url', 'display', 'identifier', 'name', 'slug', 'type', 'import_targets', 'export_targets',\n            'description', 'comments', 'tenant', 'tags', 'custom_fields', 'created', 'last_updated'\n        ]\n\n\nclass L2VPNTerminationSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(view_name='vpn-api:l2vpntermination-detail')\n    l2vpn = NestedL2VPNSerializer()\n    assigned_object_type = ContentTypeField(\n        queryset=ContentType.objects.all()\n    )\n    assigned_object = serializers.SerializerMethodField(read_only=True)\n\n    class Meta:\n        model = L2VPNTermination\n        fields = [\n            'id', 'url', 'display', 'l2vpn', 'assigned_object_type', 'assigned_object_id',\n            'assigned_object', 'tags', 'custom_fields', 'created', 'last_updated'\n        ]\n\n    @extend_schema_field(serializers.JSONField(allow_null=True))\n    def get_assigned_object(self, instance):\n        serializer = get_serializer_for_model(instance.assigned_object, prefix=NESTED_SERIALIZER_PREFIX)\n        context = {'request': self.context['request']}\n        return serializer(instance.assigned_object, context=context).data\n", "path": "netbox/vpn/api/serializers.py"}], "after_files": [{"content": "from django.contrib.contenttypes.models import ContentType\nfrom drf_spectacular.utils import extend_schema_field\nfrom rest_framework import serializers\n\nfrom ipam.api.nested_serializers import NestedIPAddressSerializer, NestedRouteTargetSerializer\nfrom ipam.models import RouteTarget\nfrom netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField\nfrom netbox.api.serializers import NetBoxModelSerializer\nfrom netbox.constants import NESTED_SERIALIZER_PREFIX\nfrom tenancy.api.nested_serializers import NestedTenantSerializer\nfrom utilities.api import get_serializer_for_model\nfrom vpn.choices import *\nfrom vpn.models import *\nfrom .nested_serializers import *\n\n__all__ = (\n    'IKEPolicySerializer',\n    'IKEProposalSerializer',\n    'IPSecPolicySerializer',\n    'IPSecProfileSerializer',\n    'IPSecProposalSerializer',\n    'L2VPNSerializer',\n    'L2VPNTerminationSerializer',\n    'TunnelGroupSerializer',\n    'TunnelSerializer',\n    'TunnelTerminationSerializer',\n)\n\n\nclass TunnelGroupSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(view_name='vpn-api:tunnelgroup-detail')\n    tunnel_count = serializers.IntegerField(read_only=True)\n\n    class Meta:\n        model = TunnelGroup\n        fields = [\n            'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',\n            'tunnel_count',\n        ]\n\n\nclass TunnelSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:tunnel-detail'\n    )\n    status = ChoiceField(\n        choices=TunnelStatusChoices\n    )\n    group = NestedTunnelGroupSerializer(\n        required=False,\n        allow_null=True\n    )\n    encapsulation = ChoiceField(\n        choices=TunnelEncapsulationChoices\n    )\n    ipsec_profile = NestedIPSecProfileSerializer(\n        required=False,\n        allow_null=True\n    )\n    tenant = NestedTenantSerializer(\n        required=False,\n        allow_null=True\n    )\n\n    class Meta:\n        model = Tunnel\n        fields = (\n            'id', 'url', 'display', 'name', 'status', 'group', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id',\n            'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass TunnelTerminationSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:tunneltermination-detail'\n    )\n    tunnel = NestedTunnelSerializer()\n    role = ChoiceField(\n        choices=TunnelTerminationRoleChoices\n    )\n    termination_type = ContentTypeField(\n        queryset=ContentType.objects.all()\n    )\n    termination = serializers.SerializerMethodField(\n        read_only=True\n    )\n    outside_ip = NestedIPAddressSerializer(\n        required=False,\n        allow_null=True\n    )\n\n    class Meta:\n        model = TunnelTermination\n        fields = (\n            'id', 'url', 'display', 'tunnel', 'role', 'termination_type', 'termination_id', 'termination', 'outside_ip',\n            'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n    @extend_schema_field(serializers.JSONField(allow_null=True))\n    def get_termination(self, obj):\n        serializer = get_serializer_for_model(obj.termination, prefix=NESTED_SERIALIZER_PREFIX)\n        context = {'request': self.context['request']}\n        return serializer(obj.termination, context=context).data\n\n\nclass IKEProposalSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ikeproposal-detail'\n    )\n    authentication_method = ChoiceField(\n        choices=AuthenticationMethodChoices\n    )\n    encryption_algorithm = ChoiceField(\n        choices=EncryptionAlgorithmChoices\n    )\n    authentication_algorithm = ChoiceField(\n        choices=AuthenticationAlgorithmChoices\n    )\n    group = ChoiceField(\n        choices=DHGroupChoices\n    )\n\n    class Meta:\n        model = IKEProposal\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'authentication_method', 'encryption_algorithm',\n            'authentication_algorithm', 'group', 'sa_lifetime', 'comments', 'tags', 'custom_fields', 'created',\n            'last_updated',\n        )\n\n\nclass IKEPolicySerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ikepolicy-detail'\n    )\n    version = ChoiceField(\n        choices=IKEVersionChoices\n    )\n    mode = ChoiceField(\n        choices=IKEModeChoices\n    )\n    proposals = SerializedPKRelatedField(\n        queryset=IKEProposal.objects.all(),\n        serializer=NestedIKEProposalSerializer,\n        required=False,\n        many=True\n    )\n\n    class Meta:\n        model = IKEPolicy\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'comments',\n            'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass IPSecProposalSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ipsecproposal-detail'\n    )\n    encryption_algorithm = ChoiceField(\n        choices=EncryptionAlgorithmChoices\n    )\n    authentication_algorithm = ChoiceField(\n        choices=AuthenticationAlgorithmChoices\n    )\n\n    class Meta:\n        model = IPSecProposal\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'encryption_algorithm', 'authentication_algorithm',\n            'sa_lifetime_seconds', 'sa_lifetime_data', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass IPSecPolicySerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ipsecpolicy-detail'\n    )\n    proposals = SerializedPKRelatedField(\n        queryset=IPSecProposal.objects.all(),\n        serializer=NestedIPSecProposalSerializer,\n        required=False,\n        many=True\n    )\n    pfs_group = ChoiceField(\n        choices=DHGroupChoices,\n        required=False\n    )\n\n    class Meta:\n        model = IPSecPolicy\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'proposals', 'pfs_group', 'comments', 'tags',\n            'custom_fields', 'created', 'last_updated',\n        )\n\n\nclass IPSecProfileSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(\n        view_name='vpn-api:ipsecprofile-detail'\n    )\n    mode = ChoiceField(\n        choices=IPSecModeChoices\n    )\n    ike_policy = NestedIKEPolicySerializer()\n    ipsec_policy = NestedIPSecPolicySerializer()\n\n    class Meta:\n        model = IPSecProfile\n        fields = (\n            'id', 'url', 'display', 'name', 'description', 'mode', 'ike_policy', 'ipsec_policy', 'comments', 'tags',\n            'custom_fields', 'created', 'last_updated',\n        )\n\n\n#\n# L2VPN\n#\n\nclass L2VPNSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(view_name='vpn-api:l2vpn-detail')\n    type = ChoiceField(choices=L2VPNTypeChoices, required=False)\n    import_targets = SerializedPKRelatedField(\n        queryset=RouteTarget.objects.all(),\n        serializer=NestedRouteTargetSerializer,\n        required=False,\n        many=True\n    )\n    export_targets = SerializedPKRelatedField(\n        queryset=RouteTarget.objects.all(),\n        serializer=NestedRouteTargetSerializer,\n        required=False,\n        many=True\n    )\n    tenant = NestedTenantSerializer(required=False, allow_null=True)\n\n    class Meta:\n        model = L2VPN\n        fields = [\n            'id', 'url', 'display', 'identifier', 'name', 'slug', 'type', 'import_targets', 'export_targets',\n            'description', 'comments', 'tenant', 'tags', 'custom_fields', 'created', 'last_updated'\n        ]\n\n\nclass L2VPNTerminationSerializer(NetBoxModelSerializer):\n    url = serializers.HyperlinkedIdentityField(view_name='vpn-api:l2vpntermination-detail')\n    l2vpn = NestedL2VPNSerializer()\n    assigned_object_type = ContentTypeField(\n        queryset=ContentType.objects.all()\n    )\n    assigned_object = serializers.SerializerMethodField(read_only=True)\n\n    class Meta:\n        model = L2VPNTermination\n        fields = [\n            'id', 'url', 'display', 'l2vpn', 'assigned_object_type', 'assigned_object_id',\n            'assigned_object', 'tags', 'custom_fields', 'created', 'last_updated'\n        ]\n\n    @extend_schema_field(serializers.JSONField(allow_null=True))\n    def get_assigned_object(self, instance):\n        serializer = get_serializer_for_model(instance.assigned_object, prefix=NESTED_SERIALIZER_PREFIX)\n        context = {'request': self.context['request']}\n        return serializer(instance.assigned_object, context=context).data\n", "path": "netbox/vpn/api/serializers.py"}]}