Skip to content

Commit 8151e25

Browse files
committed
init
1 parent 5e120f6 commit 8151e25

12 files changed

Lines changed: 324 additions & 1 deletion

linode_api4/groups/vpc.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from linode_api4.groups import Group
55
from linode_api4.objects import VPC, Region, VPCIPAddress, VPCIPv6RangeOptions
66
from linode_api4.objects.base import _flatten_request_body_recursive
7+
from linode_api4.objects.vpc import VPCType
78
from linode_api4.paginated_list import PaginatedList
89
from linode_api4.util import drop_null_keys
910

@@ -36,6 +37,7 @@ def create(
3637
description: Optional[str] = None,
3738
subnets: Optional[List[Dict[str, Any]]] = None,
3839
ipv6: Optional[List[Union[VPCIPv6RangeOptions, Dict[str, Any]]]] = None,
40+
vpc_type: Optional[Union[VPCType, str]] = None,
3941
**kwargs,
4042
) -> VPC:
4143
"""
@@ -53,6 +55,11 @@ def create(
5355
:type subnets: List[Dict[str, Any]]
5456
:param ipv6: The IPv6 address ranges for this VPC.
5557
:type ipv6: List[Union[VPCIPv6RangeOptions, Dict[str, Any]]]
58+
:param vpc_type: The type of VPC to create. Defaults to ``regular`` on
59+
the API side. Set to ``rdma`` to create a GPUDirect
60+
RDMA VPC (requires the ``GPUDirect RDMA`` account
61+
capability).
62+
:type vpc_type: Optional[Union[VPCType, str]]
5663
5764
:returns: The new VPC object.
5865
:rtype: VPC
@@ -63,6 +70,7 @@ def create(
6370
"description": description,
6471
"ipv6": ipv6,
6572
"subnets": subnets,
73+
"vpc_type": vpc_type,
6674
}
6775

6876
if subnets is not None and len(subnets) > 0:

linode_api4/objects/linode.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,11 @@ def interface_create(
21062106
:param vpc: The VPC-specific configuration of the new interface.
21072107
If set, the new instance will be a VPC interface.
21082108
2109+
.. note::
2110+
RDMA VPC interfaces (``rdma_vpc``) cannot be added via this
2111+
endpoint. They may only be specified at instance creation time via
2112+
:func:`linode_api4.LinodeGroup.instance_create`.
2113+
21092114
:returns: The newly created Linode Interface.
21102115
:rtype: LinodeInterface
21112116
"""

linode_api4/objects/linode_interfaces.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,47 @@ class LinodeInterfaceVLANOptions(JSONObject):
187187
ipam_address: Optional[str] = None
188188

189189

190+
@dataclass
191+
class LinodeInterfaceRDMAVPCIPv4AddressOptions(JSONObject):
192+
"""
193+
Options accepted for a single address when creating or updating the IPv4
194+
configuration of an RDMA VPC Linode Interface.
195+
196+
Only one address is supported per RDMA VPC interface, and it must be
197+
marked as primary.
198+
"""
199+
200+
address: Optional[str] = None
201+
primary: Optional[bool] = None
202+
203+
204+
@dataclass
205+
class LinodeInterfaceRDMAVPCIPv4Options(JSONObject):
206+
"""
207+
Options accepted when creating or updating the IPv4 configuration of an
208+
RDMA VPC Linode Interface.
209+
210+
The ``addresses`` list MUST contain exactly one element. If omitted, the
211+
API defaults to a single primary ``auto`` address.
212+
"""
213+
214+
addresses: Optional[List[LinodeInterfaceRDMAVPCIPv4AddressOptions]] = None
215+
216+
217+
@dataclass
218+
class LinodeInterfaceRDMAVPCOptions(JSONObject):
219+
"""
220+
RDMA-VPC-exclusive options accepted when creating or updating a Linode
221+
Interface.
222+
223+
Used for GPUDirect RDMA interfaces. Default routes and NAT 1:1 addresses
224+
are not supported on RDMA VPC interfaces.
225+
"""
226+
227+
subnet_id: int = 0
228+
ipv4: Optional[LinodeInterfaceRDMAVPCIPv4Options] = None
229+
230+
190231
@dataclass
191232
class LinodeInterfaceOptions(JSONObject):
192233
"""
@@ -204,6 +245,7 @@ class LinodeInterfaceOptions(JSONObject):
204245
vpc: Optional[LinodeInterfaceVPCOptions] = None
205246
public: Optional[LinodeInterfacePublicOptions] = None
206247
vlan: Optional[LinodeInterfaceVLANOptions] = None
248+
rdma_vpc: Optional[LinodeInterfaceRDMAVPCOptions] = None
207249

208250

209251
# Interface GET Response
@@ -409,6 +451,45 @@ class LinodeInterfaceVLAN(JSONObject):
409451
ipam_address: Optional[str] = None
410452

411453

454+
@dataclass
455+
class LinodeInterfaceRDMAVPCIPv4Address(JSONObject):
456+
"""
457+
A single address under the IPv4 configuration of an RDMA VPC Linode Interface.
458+
"""
459+
460+
put_class = LinodeInterfaceRDMAVPCIPv4AddressOptions
461+
462+
address: str = ""
463+
primary: bool = False
464+
465+
466+
@dataclass
467+
class LinodeInterfaceRDMAVPCIPv4(JSONObject):
468+
"""
469+
The IPv4 configuration of an RDMA VPC Linode Interface.
470+
"""
471+
472+
put_class = LinodeInterfaceRDMAVPCIPv4Options
473+
474+
addresses: List[LinodeInterfaceRDMAVPCIPv4Address] = field(
475+
default_factory=list
476+
)
477+
478+
479+
@dataclass
480+
class LinodeInterfaceRDMAVPC(JSONObject):
481+
"""
482+
RDMA VPC-specific configuration field for a Linode Interface.
483+
"""
484+
485+
put_class = LinodeInterfaceRDMAVPCOptions
486+
487+
vpc_id: int = 0
488+
subnet_id: int = 0
489+
490+
ipv4: Optional[LinodeInterfaceRDMAVPCIPv4] = None
491+
492+
412493
class LinodeInterface(DerivedBase):
413494
"""
414495
A Linode's network interface.
@@ -449,6 +530,7 @@ class LinodeInterface(DerivedBase):
449530
"public": Property(mutable=True, json_object=LinodeInterfacePublic),
450531
"vlan": Property(mutable=True, json_object=LinodeInterfaceVLAN),
451532
"vpc": Property(mutable=True, json_object=LinodeInterfaceVPC),
533+
"rdma_vpc": Property(mutable=True, json_object=LinodeInterfaceRDMAVPC),
452534
}
453535

454536
def firewalls(self, *filters) -> List[Firewall]:

linode_api4/objects/region.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class Capability(StrEnum):
6565
ruleset = "Cloud Firewall Rule Set"
6666
prefixlists = "Cloud Firewall Prefix Lists"
6767
current_prefixlists = "Cloud Firewall Prefix List Current References"
68+
gpudirect_rdma = "GPUDirect RDMA"
6869

6970

7071
@dataclass

linode_api4/objects/vpc.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@
55
from linode_api4.objects import Base, DerivedBase, Property, Region
66
from linode_api4.objects.base import _flatten_request_body_recursive
77
from linode_api4.objects.networking import VPCIPAddress
8-
from linode_api4.objects.serializable import JSONObject
8+
from linode_api4.objects.serializable import JSONObject, StrEnum
99
from linode_api4.paginated_list import PaginatedList
1010
from linode_api4.util import drop_null_keys
1111

1212

13+
class VPCType(StrEnum):
14+
"""
15+
VPCType represents the supported VPC types.
16+
"""
17+
18+
regular = "regular"
19+
rdma = "rdma"
20+
21+
1322
@dataclass
1423
class VPCIPv6RangeOptions(JSONObject):
1524
"""
@@ -89,6 +98,7 @@ class VPCSubnet(DerivedBase):
8998
"ipv6": Property(json_object=VPCSubnetIPv6Range, unordered=True),
9099
"linodes": Property(json_object=VPCSubnetLinode, unordered=True),
91100
"databases": Property(json_object=VPCSubnetDatabase, unordered=True),
101+
"vpc_type": Property(),
92102
"created": Property(is_datetime=True),
93103
"updated": Property(is_datetime=True),
94104
}
@@ -110,6 +120,7 @@ class VPC(Base):
110120
"region": Property(slug_relationship=Region),
111121
"ipv6": Property(json_object=VPCIPv6Range, unordered=True),
112122
"subnets": Property(derived_class=VPCSubnet),
123+
"vpc_type": Property(),
113124
"created": Property(is_datetime=True),
114125
"updated": Property(is_datetime=True),
115126
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"id": 999,
3+
"mac_address": "22:00:f2:9e:d3:48",
4+
"created": "2026-03-12T09:54:34",
5+
"updated": "2026-03-12T09:54:35",
6+
"default_route": {
7+
"ipv4": false,
8+
"ipv6": false
9+
},
10+
"version": 1,
11+
"public": null,
12+
"vpc": null,
13+
"vlan": null,
14+
"rdma_vpc": {
15+
"vpc_id": 7,
16+
"subnet_id": 8,
17+
"ipv4": {
18+
"addresses": [
19+
{
20+
"address": "10.0.0.2",
21+
"primary": true
22+
}
23+
]
24+
}
25+
}
26+
}
27+

test/fixtures/vpcs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"id": 123456,
66
"description": "A very real VPC.",
77
"region": "us-southeast",
8+
"vpc_type": "regular",
89
"ipv6": [
910
{
1011
"range": "fd71:1140:a9d0::/52"

test/fixtures/vpcs_123456.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"id": 123456,
44
"description": "A very real VPC.",
55
"region": "us-southeast",
6+
"vpc_type": "regular",
67
"ipv6": [
78
{
89
"range": "fd71:1140:a9d0::/52"

test/fixtures/vpcs_123456_subnets.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
]
3636
}
3737
],
38+
"vpc_type": "regular",
3839
"created": "2018-01-01T00:01:01",
3940
"updated": "2018-01-01T00:01:01"
4041
}

test/fixtures/vpcs_123456_subnets_789.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"range": "fd71:1140:a9d0::/52"
88
}
99
],
10+
"vpc_type": "regular",
1011
"linodes": [
1112
{
1213
"id": 12345,

0 commit comments

Comments
 (0)