Skip to content

Commit 33d7054

Browse files
Project: Unified Migration (#364)
--------- Co-authored-by: Ania Misiorek <amisiore@akamai.com> Co-authored-by: Ania Misiorek <139170033+amisiorek-akamai@users.noreply.github.com>
1 parent 8f2231c commit 33d7054

3 files changed

Lines changed: 64 additions & 13 deletions

File tree

linode_api4/objects/linode.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,11 @@ def _interface_create(self, body: Dict[str, Any]) -> NetworkInterface:
612612
return i
613613

614614

615+
class MigrationType:
616+
COLD = "cold"
617+
WARM = "warm"
618+
619+
615620
class Instance(Base):
616621
"""
617622
A Linode Instance.
@@ -948,7 +953,13 @@ def reboot(self):
948953
return False
949954
return True
950955

951-
def resize(self, new_type, allow_auto_disk_resize=True, **kwargs):
956+
def resize(
957+
self,
958+
new_type,
959+
allow_auto_disk_resize=True,
960+
migration_type: MigrationType = MigrationType.COLD,
961+
**kwargs,
962+
):
952963
"""
953964
Resizes a Linode you have the read_write permission to a different Type. If any
954965
actions are currently running or queued, those actions must be completed first
@@ -970,6 +981,10 @@ def resize(self, new_type, allow_auto_disk_resize=True, **kwargs):
970981
data must fit within the smaller disk size. Defaults to true.
971982
:type: allow_auto_disk_resize: bool
972983
984+
:param migration_type: Type of migration to be used when resizing a Linode.
985+
Customers can choose between warm and cold, the default type is cold.
986+
:type: migration_type: str
987+
973988
:returns: True if the operation was successful.
974989
:rtype: bool
975990
"""
@@ -979,6 +994,7 @@ def resize(self, new_type, allow_auto_disk_resize=True, **kwargs):
979994
params = {
980995
"type": new_type,
981996
"allow_auto_disk_resize": allow_auto_disk_resize,
997+
"migration_type": migration_type,
982998
}
983999
params.update(kwargs)
9841000

@@ -1438,7 +1454,12 @@ def mutate(self, allow_auto_disk_resize=True):
14381454

14391455
return True
14401456

1441-
def initiate_migration(self, region=None, upgrade=None):
1457+
def initiate_migration(
1458+
self,
1459+
region=None,
1460+
upgrade=None,
1461+
migration_type: MigrationType = MigrationType.COLD,
1462+
):
14421463
"""
14431464
Initiates a pending migration that is already scheduled for this Linode
14441465
Instance
@@ -1459,10 +1480,16 @@ def initiate_migration(self, region=None, upgrade=None):
14591480
region field does not allow upgrades, then the endpoint will return a 400 error
14601481
code and the migration will not be performed.
14611482
:type: upgrade: bool
1483+
1484+
:param migration_type: The type of migration that will be used for this Linode migration.
1485+
Customers can only use this param when activating a support-created migration.
1486+
Customers can choose between a cold and warm migration, cold is the default type.
1487+
:type: mirgation_type: str
14621488
"""
14631489
params = {
14641490
"region": region.id if issubclass(type(region), Base) else region,
14651491
"upgrade": upgrade,
1492+
"type": migration_type,
14661493
}
14671494

14681495
util.drop_null_keys(params)

test/integration/helpers.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import random
21
import time
32
from typing import Callable
43

@@ -8,7 +7,7 @@
87

98

109
def get_test_label():
11-
unique_timestamp = str(int(time.time()) + random.randint(0, 1000))
10+
unique_timestamp = str(time.time_ns())
1211
label = "IntTestSDK_" + unique_timestamp
1312
return label
1413

@@ -94,13 +93,13 @@ def retry_sending_request(retries: int, condition: Callable, *args) -> object:
9493

9594

9695
def send_request_when_resource_available(
97-
timeout: int, func: Callable, *args
96+
timeout: int, func: Callable, *args, **kwargs
9897
) -> object:
9998
start_time = time.time()
10099

101100
while True:
102101
try:
103-
res = func(*args)
102+
res = func(*args, **kwargs)
104103
return res
105104
except ApiError as e:
106105
if (
@@ -110,9 +109,9 @@ def send_request_when_resource_available(
110109
):
111110
if time.time() - start_time > timeout:
112111
raise TimeoutError(
113-
"Timeout Error: resource is not available in"
112+
"Timeout Error: resource is not available in "
114113
+ str(timeout)
115-
+ "seconds"
114+
+ " seconds"
116115
)
117116
time.sleep(10)
118117
else:

test/integration/models/test_linode.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Instance,
1919
Type,
2020
)
21+
from linode_api4.objects.linode import MigrationType
2122

2223

2324
@pytest.fixture(scope="session")
@@ -302,6 +303,29 @@ def test_linode_resize_with_class(
302303
assert linode.status == "running"
303304

304305

306+
def test_linode_resize_with_migration_type(
307+
create_linode_for_long_running_tests,
308+
):
309+
linode = create_linode_for_long_running_tests
310+
m_type = MigrationType.WARM
311+
312+
wait_for_condition(10, 100, get_status, linode, "running")
313+
314+
time.sleep(5)
315+
res = linode.resize(new_type="g6-standard-1", migration_type=m_type)
316+
317+
assert res
318+
319+
wait_for_condition(10, 300, get_status, linode, "resizing")
320+
321+
assert linode.status == "resizing"
322+
323+
# Takes about 3-5 minute to resize, sometimes longer...
324+
wait_for_condition(30, 600, get_status, linode, "running")
325+
326+
assert linode.status == "running"
327+
328+
305329
def test_linode_boot_with_config(create_linode):
306330
linode = create_linode
307331

@@ -416,15 +440,16 @@ def test_linode_initate_migration(test_linode_client):
416440
chosen_region = available_regions[4]
417441
label = get_test_label() + "_migration"
418442

419-
linode, password = client.linode.instance_create(
420-
"g6-nanode-1", chosen_region, image="linode/debian10", label=label
443+
linode, _ = client.linode.instance_create(
444+
"g6-nanode-1", chosen_region, image="linode/debian12", label=label
421445
)
422446

423-
wait_for_condition(10, 100, get_status, linode, "running")
424447
# Says it could take up to ~6 hrs for migration to fully complete
425-
426448
send_request_when_resource_available(
427-
300, linode.initiate_migration, "us-mia"
449+
300,
450+
linode.initiate_migration,
451+
region="us-mia",
452+
migration_type=MigrationType.COLD,
428453
)
429454

430455
res = linode.delete()

0 commit comments

Comments
 (0)