@@ -335,6 +335,18 @@ def subnet(self) -> VPCSubnet:
335
335
return VPCSubnet (self ._client , self .subnet_id , self .vpc_id )
336
336
337
337
338
+ @dataclass
339
+ class InstancePlacementGroupAssignment (JSONObject ):
340
+ """
341
+ Represents an assignment between an instance and a Placement Group.
342
+ This is intended to be used when creating, cloning, and migrating
343
+ instances.
344
+ """
345
+
346
+ id : int
347
+ compliant_only : bool = False
348
+
349
+
338
350
@dataclass
339
351
class ConfigInterface (JSONObject ):
340
352
"""
@@ -870,6 +882,37 @@ def transfer(self):
870
882
871
883
return self ._transfer
872
884
885
+ @property
886
+ def placement_group (self ) -> Optional ["PlacementGroup" ]:
887
+ """
888
+ Returns the PlacementGroup object for the Instance.
889
+
890
+ :returns: The Placement Group this instance is under.
891
+ :rtype: Optional[PlacementGroup]
892
+ """
893
+ # Workaround to avoid circular import
894
+ from linode_api4 .objects .placement import ( # pylint: disable=import-outside-toplevel
895
+ PlacementGroup ,
896
+ )
897
+
898
+ if not hasattr (self , "_placement_group" ):
899
+ # Refresh the instance if necessary
900
+ if not self ._populated :
901
+ self ._api_get ()
902
+
903
+ pg_data = self ._raw_json .get ("placement_group" , None )
904
+
905
+ if pg_data is None :
906
+ return None
907
+
908
+ setattr (
909
+ self ,
910
+ "_placement_group" ,
911
+ PlacementGroup (self ._client , pg_data .get ("id" ), json = pg_data ),
912
+ )
913
+
914
+ return self ._placement_group
915
+
873
916
def _populate (self , json ):
874
917
if json is not None :
875
918
# fixes ipv4 and ipv6 attribute of json to make base._populate work
@@ -885,11 +928,16 @@ def invalidate(self):
885
928
"""Clear out cached properties"""
886
929
if hasattr (self , "_avail_backups" ):
887
930
del self ._avail_backups
931
+
888
932
if hasattr (self , "_ips" ):
889
933
del self ._ips
934
+
890
935
if hasattr (self , "_transfer" ):
891
936
del self ._transfer
892
937
938
+ if hasattr (self , "_placement_group" ):
939
+ del self ._placement_group
940
+
893
941
Base .invalidate (self )
894
942
895
943
def boot (self , config = None ):
@@ -1471,6 +1519,9 @@ def initiate_migration(
1471
1519
region = None ,
1472
1520
upgrade = None ,
1473
1521
migration_type : MigrationType = MigrationType .COLD ,
1522
+ placement_group : Union [
1523
+ InstancePlacementGroupAssignment , Dict [str , Any ], int
1524
+ ] = None ,
1474
1525
):
1475
1526
"""
1476
1527
Initiates a pending migration that is already scheduled for this Linode
@@ -1496,12 +1547,19 @@ def initiate_migration(
1496
1547
:param migration_type: The type of migration that will be used for this Linode migration.
1497
1548
Customers can only use this param when activating a support-created migration.
1498
1549
Customers can choose between a cold and warm migration, cold is the default type.
1499
- :type: mirgation_type: str
1550
+ :type: migration_type: str
1551
+
1552
+ :param placement_group: Information about the placement group to create this instance under.
1553
+ :type placement_group: Union[InstancePlacementGroupAssignment, Dict[str, Any], int]
1500
1554
"""
1555
+
1501
1556
params = {
1502
1557
"region" : region .id if issubclass (type (region ), Base ) else region ,
1503
1558
"upgrade" : upgrade ,
1504
1559
"type" : migration_type ,
1560
+ "placement_group" : _expand_placement_group_assignment (
1561
+ placement_group
1562
+ ),
1505
1563
}
1506
1564
1507
1565
util .drop_null_keys (params )
@@ -1583,6 +1641,12 @@ def clone(
1583
1641
label = None ,
1584
1642
group = None ,
1585
1643
with_backups = None ,
1644
+ placement_group : Union [
1645
+ InstancePlacementGroupAssignment ,
1646
+ "PlacementGroup" ,
1647
+ Dict [str , Any ],
1648
+ int ,
1649
+ ] = None ,
1586
1650
):
1587
1651
"""
1588
1652
Clones this linode into a new linode or into a new linode in the given region
@@ -1618,6 +1682,9 @@ def clone(
1618
1682
enrolled in the Linode Backup service. This will incur an additional charge.
1619
1683
:type: with_backups: bool
1620
1684
1685
+ :param placement_group: Information about the placement group to create this instance under.
1686
+ :type placement_group: Union[InstancePlacementGroupAssignment, PlacementGroup, Dict[str, Any], int]
1687
+
1621
1688
:returns: The cloned Instance.
1622
1689
:rtype: Instance
1623
1690
"""
@@ -1654,8 +1721,13 @@ def clone(
1654
1721
"label" : label ,
1655
1722
"group" : group ,
1656
1723
"with_backups" : with_backups ,
1724
+ "placement_group" : _expand_placement_group_assignment (
1725
+ placement_group
1726
+ ),
1657
1727
}
1658
1728
1729
+ util .drop_null_keys (params )
1730
+
1659
1731
result = self ._client .post (
1660
1732
"{}/clone" .format (Instance .api_endpoint ), model = self , data = params
1661
1733
)
@@ -1790,3 +1862,40 @@ def _serialize(self):
1790
1862
dct = Base ._serialize (self )
1791
1863
dct ["images" ] = [d .id for d in self .images ]
1792
1864
return dct
1865
+
1866
+
1867
+ def _expand_placement_group_assignment (
1868
+ pg : Union [
1869
+ InstancePlacementGroupAssignment , "PlacementGroup" , Dict [str , Any ], int
1870
+ ]
1871
+ ) -> Optional [Dict [str , Any ]]:
1872
+ """
1873
+ Expands the placement group argument into a dict for use in an API request body.
1874
+
1875
+ :param pg: The placement group argument to be expanded.
1876
+ :type pg: Union[InstancePlacementGroupAssignment, PlacementGroup, Dict[str, Any], int]
1877
+
1878
+ :returns: The expanded placement group.
1879
+ :rtype: Optional[Dict[str, Any]]
1880
+ """
1881
+ # Workaround to avoid circular import
1882
+ from linode_api4 .objects .placement import ( # pylint: disable=import-outside-toplevel
1883
+ PlacementGroup ,
1884
+ )
1885
+
1886
+ if pg is None :
1887
+ return None
1888
+
1889
+ if isinstance (pg , dict ):
1890
+ return pg
1891
+
1892
+ if isinstance (pg , InstancePlacementGroupAssignment ):
1893
+ return pg .dict
1894
+
1895
+ if isinstance (pg , PlacementGroup ):
1896
+ return {"id" : pg .id }
1897
+
1898
+ if isinstance (pg , int ):
1899
+ return {"id" : pg }
1900
+
1901
+ raise TypeError (f"Invalid type for Placement Group: { type (pg )} " )
0 commit comments