Skip to content

Commit cc44415

Browse files
kyudscg505
authored andcommitted
[Deprecate] Deprecate sky local up ip-list (#8065)
* deprecate local up ip list * bump api server version
1 parent 994e6f0 commit cc44415

File tree

8 files changed

+12
-340
lines changed

8 files changed

+12
-340
lines changed

sky/client/cli/command.py

Lines changed: 5 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6239,33 +6239,6 @@ def local():
62396239
is_flag=True,
62406240
help='Launch cluster without GPU support even '
62416241
'if GPUs are detected on the host.')
6242-
@click.option(
6243-
'--ips',
6244-
type=str,
6245-
required=False,
6246-
help='Path to the file containing IP addresses of remote machines.')
6247-
@click.option('--ssh-user',
6248-
type=str,
6249-
required=False,
6250-
help='SSH username for accessing remote machines.')
6251-
@click.option('--ssh-key-path',
6252-
type=str,
6253-
required=False,
6254-
help='Path to the SSH private key.')
6255-
@click.option('--cleanup',
6256-
is_flag=True,
6257-
help='Clean up the remote cluster instead of deploying it.')
6258-
@click.option(
6259-
'--context-name',
6260-
type=str,
6261-
required=False,
6262-
help='Name to use for the kubeconfig context. Defaults to "default". '
6263-
'Used with the ip list.')
6264-
@click.option('--password',
6265-
type=str,
6266-
required=False,
6267-
help='Password for the ssh-user to execute sudo commands. '
6268-
'Required only if passwordless sudo is not setup.')
62696242
@click.option(
62706243
'--name',
62716244
type=str,
@@ -6282,56 +6255,10 @@ def local():
62826255
@flags.config_option(expose_value=False)
62836256
@_add_click_options(flags.COMMON_OPTIONS)
62846257
@usage_lib.entrypoint
6285-
def local_up(gpus: bool, ips: str, ssh_user: str, ssh_key_path: str,
6286-
cleanup: bool, context_name: Optional[str],
6287-
password: Optional[str], name: Optional[str],
6288-
port_start: Optional[int], async_call: bool):
6289-
"""Creates a local or remote cluster."""
6290-
6291-
def _validate_args(ips, ssh_user, ssh_key_path, cleanup):
6292-
# If any of --ips, --ssh-user, or --ssh-key-path is specified,
6293-
# all must be specified
6294-
if bool(ips) or bool(ssh_user) or bool(ssh_key_path):
6295-
if not (ips and ssh_user and ssh_key_path):
6296-
raise click.BadParameter(
6297-
'All --ips, --ssh-user, and --ssh-key-path '
6298-
'must be specified together.')
6299-
6300-
# --cleanup can only be used if --ips, --ssh-user and --ssh-key-path
6301-
# are all provided
6302-
if cleanup and not (ips and ssh_user and ssh_key_path):
6303-
raise click.BadParameter('--cleanup can only be used with '
6304-
'--ips, --ssh-user and --ssh-key-path.')
6305-
6306-
_validate_args(ips, ssh_user, ssh_key_path, cleanup)
6307-
6308-
# If remote deployment arguments are specified, run remote up script
6309-
ip_list = None
6310-
ssh_key = None
6311-
if ips and ssh_user and ssh_key_path:
6312-
# Read and validate IP file
6313-
try:
6314-
with open(os.path.expanduser(ips), 'r', encoding='utf-8') as f:
6315-
ip_list = f.read().strip().splitlines()
6316-
if not ip_list:
6317-
raise click.BadParameter(f'IP file is empty: {ips}')
6318-
except (IOError, OSError) as e:
6319-
raise click.BadParameter(f'Failed to read IP file {ips}: {str(e)}')
6320-
6321-
# Read and validate SSH key file
6322-
try:
6323-
with open(os.path.expanduser(ssh_key_path), 'r',
6324-
encoding='utf-8') as f:
6325-
ssh_key = f.read()
6326-
if not ssh_key:
6327-
raise click.BadParameter(
6328-
f'SSH key file is empty: {ssh_key_path}')
6329-
except (IOError, OSError) as e:
6330-
raise click.BadParameter(
6331-
f'Failed to read SSH key file {ssh_key_path}: {str(e)}')
6332-
6333-
request_id = sdk.local_up(gpus, ip_list, ssh_user, ssh_key, cleanup,
6334-
context_name, password, name, port_start)
6258+
def local_up(gpus: bool, name: Optional[str], port_start: Optional[int],
6259+
async_call: bool):
6260+
"""Creates a local cluster."""
6261+
request_id = sdk.local_up(gpus, name, port_start)
63356262
_async_call_or_wait(request_id, async_call, request_name='local up')
63366263

63376264

@@ -6344,12 +6271,7 @@ def _validate_args(ips, ssh_user, ssh_key_path, cleanup):
63446271
@_add_click_options(flags.COMMON_OPTIONS)
63456272
@usage_lib.entrypoint
63466273
def local_down(name: Optional[str], async_call: bool):
6347-
"""Deletes a local cluster.
6348-
6349-
This will only delete a local cluster started without the ip list.
6350-
To clean up the local cluster started with a ip list, use `sky local up`
6351-
with the cleanup flag.
6352-
"""
6274+
"""Deletes a local cluster."""
63536275
request_id = sdk.local_down(name)
63546276
_async_call_or_wait(request_id, async_call, request_name='sky.local.down')
63556277

sky/client/sdk.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,12 +1712,6 @@ def storage_delete(name: str) -> server_common.RequestId[None]:
17121712
@server_common.check_server_healthy_or_start
17131713
@annotations.client_api
17141714
def local_up(gpus: bool,
1715-
ips: Optional[List[str]],
1716-
ssh_user: Optional[str],
1717-
ssh_key: Optional[str],
1718-
cleanup: bool,
1719-
context_name: Optional[str] = None,
1720-
password: Optional[str] = None,
17211715
name: Optional[str] = None,
17221716
port_start: Optional[int] = None) -> server_common.RequestId[None]:
17231717
"""Launches a Kubernetes cluster on local machines.
@@ -1733,15 +1727,7 @@ def local_up(gpus: bool,
17331727
raise ValueError('`sky local up` is only supported when '
17341728
'running SkyPilot locally.')
17351729

1736-
body = payloads.LocalUpBody(gpus=gpus,
1737-
ips=ips,
1738-
ssh_user=ssh_user,
1739-
ssh_key=ssh_key,
1740-
cleanup=cleanup,
1741-
context_name=context_name,
1742-
password=password,
1743-
name=name,
1744-
port_start=port_start)
1730+
body = payloads.LocalUpBody(gpus=gpus, name=name, port_start=port_start)
17451731
response = server_common.make_authenticated_request(
17461732
'POST', '/local_up', json=json.loads(body.model_dump_json()))
17471733
return server_common.get_request_id(response)

sky/client/sdk_async.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -656,19 +656,13 @@ async def storage_delete(
656656
@annotations.client_api
657657
async def local_up(
658658
gpus: bool,
659-
ips: Optional[List[str]],
660-
ssh_user: Optional[str],
661-
ssh_key: Optional[str],
662-
cleanup: bool,
663-
context_name: Optional[str] = None,
664659
name: Optional[str] = None,
665-
password: Optional[str] = None,
660+
port_start: Optional[int] = None,
666661
stream_logs: Optional[StreamConfig] = DEFAULT_STREAM_CONFIG) -> None:
667662
"""Async version of local_up() that launches a Kubernetes cluster on
668663
local machines."""
669-
request_id = await context_utils.to_thread(sdk.local_up, gpus, ips,
670-
ssh_user, ssh_key, cleanup,
671-
context_name, name, password)
664+
request_id = await context_utils.to_thread(sdk.local_up, gpus, name,
665+
port_start)
672666
if stream_logs is not None:
673667
return await _stream_and_get(request_id, stream_logs)
674668
else:

sky/core.py

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,44 +1293,10 @@ def _realtime_kubernetes_gpu_availability_single(
12931293
# =================
12941294
@usage_lib.entrypoint
12951295
def local_up(gpus: bool,
1296-
ips: Optional[List[str]],
1297-
ssh_user: Optional[str],
1298-
ssh_key: Optional[str],
1299-
cleanup: bool,
1300-
context_name: Optional[str] = None,
1301-
password: Optional[str] = None,
13021296
name: Optional[str] = None,
13031297
port_start: Optional[int] = None) -> None:
1304-
"""Creates a local or remote cluster."""
1305-
1306-
def _validate_args(ips, ssh_user, ssh_key, cleanup):
1307-
# If any of --ips, --ssh-user, or --ssh-key-path is specified,
1308-
# all must be specified
1309-
if bool(ips) or bool(ssh_user) or bool(ssh_key):
1310-
if not (ips and ssh_user and ssh_key):
1311-
with ux_utils.print_exception_no_traceback():
1312-
raise ValueError(
1313-
'All ips, ssh_user, and ssh_key must be specified '
1314-
'together.')
1315-
1316-
# --cleanup can only be used if --ips, --ssh-user and --ssh-key-path
1317-
# are all provided
1318-
if cleanup and not (ips and ssh_user and ssh_key):
1319-
with ux_utils.print_exception_no_traceback():
1320-
raise ValueError(
1321-
'cleanup can only be used with ips, ssh_user and ssh_key.')
1322-
1323-
_validate_args(ips, ssh_user, ssh_key, cleanup)
1324-
1325-
# If remote deployment arguments are specified, run remote up script
1326-
if ips:
1327-
assert ssh_user is not None and ssh_key is not None
1328-
kubernetes_deploy_utils.deploy_remote_cluster(ips, ssh_user, ssh_key,
1329-
cleanup, context_name,
1330-
password)
1331-
else:
1332-
# Run local deployment (kind) if no remote args are specified
1333-
kubernetes_deploy_utils.deploy_local_cluster(name, port_start, gpus)
1298+
"""Creates a local cluster."""
1299+
kubernetes_deploy_utils.deploy_local_cluster(name, port_start, gpus)
13341300

13351301

13361302
def local_down(name: Optional[str] = None) -> None:

sky/server/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# based on version info is needed.
1111
# For more details and code guidelines, refer to:
1212
# https://docs.skypilot.co/en/latest/developers/CONTRIBUTING.html#backward-compatibility-guidelines
13-
API_VERSION = 23
13+
API_VERSION = 24
1414

1515
# The minimum peer API version that the code should still work with.
1616
# Notes (dev):

sky/server/requests/payloads.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -695,12 +695,6 @@ class ListAcceleratorCountsBody(RequestBody):
695695
class LocalUpBody(RequestBody):
696696
"""The request body for the local up endpoint."""
697697
gpus: bool = True
698-
ips: Optional[List[str]] = None
699-
ssh_user: Optional[str] = None
700-
ssh_key: Optional[str] = None
701-
cleanup: bool = False
702-
context_name: Optional[str] = None
703-
password: Optional[str] = None
704698
name: Optional[str] = None
705699
port_start: Optional[int] = None
706700

sky/utils/kubernetes/kubernetes_deploy_utils.py

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -170,94 +170,6 @@ def deploy_ssh_cluster(cleanup: bool = False,
170170
is_local=True))
171171

172172

173-
def deploy_remote_cluster(ip_list: List[str],
174-
ssh_user: str,
175-
ssh_key: str,
176-
cleanup: bool,
177-
context_name: Optional[str] = None,
178-
password: Optional[str] = None):
179-
success = False
180-
path_to_package = os.path.dirname(__file__)
181-
up_script_path = os.path.join(path_to_package, 'deploy_remote_cluster.py')
182-
# Get directory of script and run it from there
183-
cwd = os.path.dirname(os.path.abspath(up_script_path))
184-
185-
# Create temporary files for the IPs and SSH key
186-
with tempfile.NamedTemporaryFile(mode='w') as ip_file, \
187-
tempfile.NamedTemporaryFile(mode='w') as key_file:
188-
189-
# Write IPs and SSH key to temporary files
190-
ip_file.write('\n'.join(ip_list))
191-
ip_file.flush()
192-
193-
key_file.write(ssh_key)
194-
key_file.flush()
195-
os.chmod(key_file.name, 0o600)
196-
197-
# Use the legacy mode command line arguments for backward compatibility
198-
deploy_command = [
199-
sys.executable, up_script_path, '--ips-file', ip_file.name,
200-
'--user', ssh_user, '--ssh-key', key_file.name
201-
]
202-
203-
if context_name is not None:
204-
deploy_command.extend(['--context-name', context_name])
205-
if password is not None:
206-
deploy_command.extend(['--password', password])
207-
if cleanup:
208-
deploy_command.append('--cleanup')
209-
210-
# Setup logging paths
211-
run_timestamp = sky_logging.get_run_timestamp()
212-
log_path = os.path.join(constants.SKY_LOGS_DIRECTORY, run_timestamp,
213-
'local_up.log')
214-
215-
if cleanup:
216-
msg_str = 'Cleaning up remote cluster...'
217-
else:
218-
msg_str = 'Deploying remote cluster...'
219-
220-
# Create environment with PYTHONUNBUFFERED=1 to ensure unbuffered output
221-
env = os.environ.copy()
222-
env['PYTHONUNBUFFERED'] = '1'
223-
224-
with rich_utils.safe_status(
225-
ux_utils.spinner_message(msg_str,
226-
log_path=log_path,
227-
is_local=True)):
228-
returncode, _, stderr = log_lib.run_with_log(
229-
cmd=deploy_command,
230-
log_path=log_path,
231-
require_outputs=True,
232-
stream_logs=False,
233-
line_processor=log_utils.SkyRemoteUpLineProcessor(
234-
log_path=log_path, is_local=True),
235-
cwd=cwd,
236-
env=env)
237-
if returncode == 0:
238-
success = True
239-
else:
240-
with ux_utils.print_exception_no_traceback():
241-
log_hint = ux_utils.log_path_hint(log_path, is_local=True)
242-
raise RuntimeError('Failed to deploy remote cluster. '
243-
f'Full log: {log_hint}'
244-
f'\nError: {stderr}')
245-
246-
if success:
247-
if cleanup:
248-
logger.info(
249-
ux_utils.finishing_message(
250-
'🎉 Remote cluster cleaned up successfully.',
251-
log_path=log_path,
252-
is_local=True))
253-
else:
254-
logger.info(
255-
ux_utils.finishing_message(
256-
'🎉 Remote cluster deployed successfully.',
257-
log_path=log_path,
258-
is_local=True))
259-
260-
261173
def generate_kind_config(port_start: int,
262174
num_nodes: int = 1,
263175
gpus: bool = False) -> str:

0 commit comments

Comments
 (0)