skypilot-nightly 1.0.0.dev20250827__py3-none-any.whl → 1.0.0.dev20250829__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of skypilot-nightly might be problematic. Click here for more details.

Files changed (86) hide show
  1. sky/__init__.py +2 -2
  2. sky/admin_policy.py +11 -10
  3. sky/authentication.py +1 -1
  4. sky/backends/backend.py +3 -5
  5. sky/backends/backend_utils.py +140 -52
  6. sky/backends/cloud_vm_ray_backend.py +30 -25
  7. sky/backends/local_docker_backend.py +3 -8
  8. sky/backends/wheel_utils.py +35 -8
  9. sky/client/cli/command.py +41 -9
  10. sky/client/sdk.py +23 -8
  11. sky/client/sdk_async.py +6 -2
  12. sky/clouds/aws.py +118 -1
  13. sky/core.py +1 -4
  14. sky/dashboard/out/404.html +1 -1
  15. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  16. sky/dashboard/out/clusters/[cluster].html +1 -1
  17. sky/dashboard/out/clusters.html +1 -1
  18. sky/dashboard/out/config.html +1 -1
  19. sky/dashboard/out/index.html +1 -1
  20. sky/dashboard/out/infra/[context].html +1 -1
  21. sky/dashboard/out/infra.html +1 -1
  22. sky/dashboard/out/jobs/[job].html +1 -1
  23. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  24. sky/dashboard/out/jobs.html +1 -1
  25. sky/dashboard/out/users.html +1 -1
  26. sky/dashboard/out/volumes.html +1 -1
  27. sky/dashboard/out/workspace/new.html +1 -1
  28. sky/dashboard/out/workspaces/[name].html +1 -1
  29. sky/dashboard/out/workspaces.html +1 -1
  30. sky/global_user_state.py +82 -22
  31. sky/jobs/client/sdk.py +5 -2
  32. sky/jobs/recovery_strategy.py +9 -4
  33. sky/jobs/server/server.py +2 -1
  34. sky/logs/agent.py +2 -2
  35. sky/logs/aws.py +6 -3
  36. sky/provision/aws/config.py +78 -3
  37. sky/provision/aws/instance.py +45 -6
  38. sky/provision/do/utils.py +2 -1
  39. sky/provision/kubernetes/instance.py +55 -11
  40. sky/provision/kubernetes/utils.py +11 -2
  41. sky/provision/nebius/utils.py +36 -2
  42. sky/schemas/db/global_user_state/007_cluster_event_request_id.py +34 -0
  43. sky/serve/client/impl.py +5 -4
  44. sky/serve/replica_managers.py +4 -3
  45. sky/serve/serve_utils.py +2 -2
  46. sky/serve/server/impl.py +3 -2
  47. sky/serve/server/server.py +2 -1
  48. sky/server/auth/oauth2_proxy.py +10 -4
  49. sky/server/common.py +4 -4
  50. sky/server/daemons.py +16 -5
  51. sky/server/requests/executor.py +5 -3
  52. sky/server/requests/payloads.py +3 -1
  53. sky/server/requests/preconditions.py +3 -2
  54. sky/server/requests/requests.py +121 -19
  55. sky/server/server.py +85 -60
  56. sky/server/stream_utils.py +7 -5
  57. sky/setup_files/dependencies.py +6 -1
  58. sky/sky_logging.py +28 -0
  59. sky/skylet/constants.py +6 -0
  60. sky/skylet/events.py +2 -3
  61. sky/skypilot_config.py +10 -10
  62. sky/task.py +1 -1
  63. sky/templates/aws-ray.yml.j2 +1 -0
  64. sky/templates/nebius-ray.yml.j2 +4 -8
  65. sky/usage/usage_lib.py +3 -2
  66. sky/utils/annotations.py +8 -2
  67. sky/utils/cluster_utils.py +3 -3
  68. sky/utils/common_utils.py +0 -72
  69. sky/utils/controller_utils.py +4 -3
  70. sky/utils/dag_utils.py +4 -4
  71. sky/utils/db/db_utils.py +11 -0
  72. sky/utils/db/migration_utils.py +1 -1
  73. sky/utils/kubernetes/config_map_utils.py +3 -3
  74. sky/utils/kubernetes_enums.py +1 -0
  75. sky/utils/lock_events.py +94 -0
  76. sky/utils/schemas.py +3 -0
  77. sky/utils/timeline.py +24 -93
  78. sky/utils/yaml_utils.py +77 -10
  79. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250829.dist-info}/METADATA +8 -2
  80. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250829.dist-info}/RECORD +86 -84
  81. /sky/dashboard/out/_next/static/{-eL7Ky3bxVivzeLHNB9U6 → hYJYFIxp_ZFONR4wTIJqZ}/_buildManifest.js +0 -0
  82. /sky/dashboard/out/_next/static/{-eL7Ky3bxVivzeLHNB9U6 → hYJYFIxp_ZFONR4wTIJqZ}/_ssgManifest.js +0 -0
  83. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250829.dist-info}/WHEEL +0 -0
  84. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250829.dist-info}/entry_points.txt +0 -0
  85. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250829.dist-info}/licenses/LICENSE +0 -0
  86. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250829.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@ import pathlib
16
16
  import re
17
17
  import shutil
18
18
  import subprocess
19
+ import sys
19
20
  import tempfile
20
21
  from typing import Optional, Tuple
21
22
 
@@ -133,19 +134,45 @@ def _build_sky_wheel() -> pathlib.Path:
133
134
  # It is important to normalize the path, otherwise 'pip wheel' would
134
135
  # treat the directory as a file and generate an empty wheel.
135
136
  norm_path = str(tmp_dir) + os.sep
137
+ # TODO(#5046): Consider adding native UV support for building wheels.
138
+ # Use `python -m pip` instead of `pip3` for better compatibility across
139
+ # different environments (conda, venv, UV, system Python, etc.)
136
140
  try:
137
- # TODO(suquark): For python>=3.7, 'subprocess.run' supports capture
138
- # of the output.
139
141
  subprocess.run([
140
- 'pip3', 'wheel', '--no-deps', norm_path, '--wheel-dir',
142
+ sys.executable, '-m', 'pip', 'wheel', '--no-deps', norm_path,
143
+ '--wheel-dir',
141
144
  str(tmp_dir)
142
145
  ],
143
- stdout=subprocess.DEVNULL,
144
- stderr=subprocess.PIPE,
145
- check=True)
146
+ capture_output=True,
147
+ check=True,
148
+ text=True)
146
149
  except subprocess.CalledProcessError as e:
147
- raise RuntimeError('Failed to build pip wheel for SkyPilot. '
148
- f'Error message: {e.stderr.decode()}') from e
150
+ error_msg = e.stderr
151
+ if 'No module named pip' in error_msg:
152
+ # pip module not found - provide helpful suggestions based on
153
+ # the available package managers
154
+ if shutil.which('uv'):
155
+ msg = ('pip module not found. Since you have UV installed, '
156
+ 'you can install pip by running:\n'
157
+ ' uv pip install pip')
158
+ elif shutil.which('conda'):
159
+ msg = (
160
+ 'pip module not found. Since you have conda installed, '
161
+ 'you can install pip by running:\n'
162
+ ' conda install pip')
163
+ else:
164
+ msg = ('pip module not found. Please install pip for your '
165
+ f'Python environment ({sys.executable}).')
166
+ else:
167
+ # Other pip errors
168
+ msg = f'pip wheel command failed. Error: {error_msg}'
169
+ raise RuntimeError('Failed to build pip wheel for SkyPilot.\n' +
170
+ msg) from e
171
+ except FileNotFoundError as e:
172
+ # Python executable not found (extremely rare)
173
+ raise RuntimeError(
174
+ f'Failed to build pip wheel for SkyPilot. '
175
+ f'Python executable not found: {sys.executable}') from e
149
176
 
150
177
  try:
151
178
  wheel_path = next(tmp_dir.glob(_WHEEL_PATTERN))
sky/client/cli/command.py CHANGED
@@ -287,9 +287,10 @@ def _complete_cluster_name(ctx: click.Context, param: click.Parameter,
287
287
  del ctx, param # Unused.
288
288
  # TODO(zhwu): we send requests to API server for completion, which can cause
289
289
  # large latency. We should investigate caching mechanism if needed.
290
- response = requests_lib.get(
291
- f'{server_common.get_server_url()}'
290
+ response = server_common.make_authenticated_request(
291
+ 'GET',
292
292
  f'/api/completion/cluster_name?incomplete={incomplete}',
293
+ retry=False,
293
294
  timeout=2.0,
294
295
  )
295
296
  response.raise_for_status()
@@ -300,9 +301,10 @@ def _complete_storage_name(ctx: click.Context, param: click.Parameter,
300
301
  incomplete: str) -> List[str]:
301
302
  """Handle shell completion for storage names."""
302
303
  del ctx, param # Unused.
303
- response = requests_lib.get(
304
- f'{server_common.get_server_url()}'
304
+ response = server_common.make_authenticated_request(
305
+ 'GET',
305
306
  f'/api/completion/storage_name?incomplete={incomplete}',
307
+ retry=False,
306
308
  timeout=2.0,
307
309
  )
308
310
  response.raise_for_status()
@@ -313,15 +315,34 @@ def _complete_volume_name(ctx: click.Context, param: click.Parameter,
313
315
  incomplete: str) -> List[str]:
314
316
  """Handle shell completion for volume names."""
315
317
  del ctx, param # Unused.
316
- response = requests_lib.get(
317
- f'{server_common.get_server_url()}'
318
+ response = server_common.make_authenticated_request(
319
+ 'GET',
318
320
  f'/api/completion/volume_name?incomplete={incomplete}',
321
+ retry=False,
319
322
  timeout=2.0,
320
323
  )
321
324
  response.raise_for_status()
322
325
  return response.json()
323
326
 
324
327
 
328
+ def _complete_api_request(ctx: click.Context, param: click.Parameter,
329
+ incomplete: str) -> List[str]:
330
+ """Handle shell completion for API requests."""
331
+ del ctx, param # Unused.
332
+ response = server_common.make_authenticated_request(
333
+ 'GET',
334
+ f'/api/completion/api_request?incomplete={incomplete}',
335
+ retry=False,
336
+ timeout=2.0,
337
+ )
338
+ try:
339
+ response.raise_for_status()
340
+ except requests_lib.exceptions.HTTPError:
341
+ # Server may be outdated/missing this API. Silently skip.
342
+ return []
343
+ return response.json()
344
+
345
+
325
346
  def _complete_file_name(ctx: click.Context, param: click.Parameter,
326
347
  incomplete: str) -> List[str]:
327
348
  """Handle shell completion for file names.
@@ -6018,7 +6039,10 @@ def api_stop():
6018
6039
 
6019
6040
  @api.command('logs', cls=_DocumentedCodeCommand)
6020
6041
  @flags.config_option(expose_value=False)
6021
- @click.argument('request_id', required=False, type=str)
6042
+ @click.argument('request_id',
6043
+ required=False,
6044
+ type=str,
6045
+ **_get_shell_complete_args(_complete_api_request))
6022
6046
  @click.option('--server-logs',
6023
6047
  is_flag=True,
6024
6048
  default=False,
@@ -6062,7 +6086,11 @@ def api_logs(request_id: Optional[str], server_logs: bool,
6062
6086
 
6063
6087
  @api.command('cancel', cls=_DocumentedCodeCommand)
6064
6088
  @flags.config_option(expose_value=False)
6065
- @click.argument('request_ids', required=False, type=str, nargs=-1)
6089
+ @click.argument('request_ids',
6090
+ required=False,
6091
+ type=str,
6092
+ nargs=-1,
6093
+ **_get_shell_complete_args(_complete_api_request))
6066
6094
  @flags.all_option('Cancel all your requests.')
6067
6095
  @flags.all_users_option('Cancel all requests from all users.')
6068
6096
  @usage_lib.entrypoint
@@ -6094,7 +6122,11 @@ def api_cancel(request_ids: Optional[List[str]], all: bool, all_users: bool):
6094
6122
 
6095
6123
  @api.command('status', cls=_DocumentedCodeCommand)
6096
6124
  @flags.config_option(expose_value=False)
6097
- @click.argument('request_ids', required=False, type=str, nargs=-1)
6125
+ @click.argument('request_ids',
6126
+ required=False,
6127
+ type=str,
6128
+ nargs=-1,
6129
+ **_get_shell_complete_args(_complete_api_request))
6098
6130
  @click.option('--all-status',
6099
6131
  '-a',
6100
6132
  is_flag=True,
sky/client/sdk.py CHANGED
@@ -53,6 +53,7 @@ from sky.utils import rich_utils
53
53
  from sky.utils import status_lib
54
54
  from sky.utils import subprocess_utils
55
55
  from sky.utils import ux_utils
56
+ from sky.utils import yaml_utils
56
57
  from sky.utils.kubernetes import ssh_utils
57
58
 
58
59
  if typing.TYPE_CHECKING:
@@ -100,7 +101,8 @@ def reload_config() -> None:
100
101
  def stream_response(request_id: None,
101
102
  response: 'requests.Response',
102
103
  output_stream: Optional['io.TextIOBase'] = None,
103
- resumable: bool = False) -> None:
104
+ resumable: bool = False,
105
+ get_result: bool = True) -> None:
104
106
  ...
105
107
 
106
108
 
@@ -108,14 +110,16 @@ def stream_response(request_id: None,
108
110
  def stream_response(request_id: server_common.RequestId[T],
109
111
  response: 'requests.Response',
110
112
  output_stream: Optional['io.TextIOBase'] = None,
111
- resumable: bool = False) -> T:
113
+ resumable: bool = False,
114
+ get_result: bool = True) -> T:
112
115
  ...
113
116
 
114
117
 
115
118
  def stream_response(request_id: Optional[server_common.RequestId[T]],
116
119
  response: 'requests.Response',
117
120
  output_stream: Optional['io.TextIOBase'] = None,
118
- resumable: bool = False) -> Optional[T]:
121
+ resumable: bool = False,
122
+ get_result: bool = True) -> Optional[T]:
119
123
  """Streams the response to the console.
120
124
 
121
125
  Args:
@@ -128,6 +132,9 @@ def stream_response(request_id: Optional[server_common.RequestId[T]],
128
132
  console.
129
133
  resumable: Whether the response is resumable on retry. If True, the
130
134
  streaming will start from the previous failure point on retry.
135
+ get_result: Whether to get the result of the request. This will
136
+ typically be set to False for `--no-follow` flags as requests may
137
+ continue to run for long periods of time without further streaming.
131
138
  """
132
139
 
133
140
  retry_context: Optional[rest.RetryContext] = None
@@ -143,7 +150,7 @@ def stream_response(request_id: Optional[server_common.RequestId[T]],
143
150
  elif line_count > retry_context.line_processed:
144
151
  print(line, flush=True, end='', file=output_stream)
145
152
  retry_context.line_processed = line_count
146
- if request_id is not None:
153
+ if request_id is not None and get_result:
147
154
  return get(request_id)
148
155
  else:
149
156
  return None
@@ -942,10 +949,13 @@ def tail_provision_logs(cluster_name: str,
942
949
  # to return cleanly after printing the tailed lines. If we provided a
943
950
  # non-None request_id here, the get(request_id) in stream_response(
944
951
  # would fail since /provision_logs does not create a request record.
952
+ # By virtue of this, we set get_result to False to block get() from
953
+ # running.
945
954
  stream_response(request_id=None,
946
955
  response=response,
947
956
  output_stream=output_stream,
948
- resumable=(tail == 0))
957
+ resumable=(tail == 0),
958
+ get_result=False)
949
959
  return 0
950
960
 
951
961
 
@@ -2025,6 +2035,8 @@ def stream_and_get(
2025
2035
  Returns:
2026
2036
  The ``Request Returns`` of the specified request. See the documentation
2027
2037
  of the specific requests above for more details.
2038
+ If follow is False, will always return None. See note on
2039
+ stream_response.
2028
2040
 
2029
2041
  Raises:
2030
2042
  Exception: It raises the same exceptions as the specific requests,
@@ -2056,7 +2068,10 @@ def stream_and_get(
2056
2068
  if request_id is None:
2057
2069
  return None
2058
2070
  return get(request_id)
2059
- return stream_response(request_id, response, output_stream)
2071
+ return stream_response(request_id,
2072
+ response,
2073
+ output_stream,
2074
+ get_result=follow)
2060
2075
 
2061
2076
 
2062
2077
  @usage_lib.entrypoint
@@ -2332,7 +2347,7 @@ def _save_config_updates(endpoint: Optional[str] = None,
2332
2347
  config['api_server'][
2333
2348
  'service_account_token'] = service_account_token
2334
2349
 
2335
- common_utils.dump_yaml(str(config_path), config)
2350
+ yaml_utils.dump_yaml(str(config_path), config)
2336
2351
  skypilot_config.reload_config()
2337
2352
 
2338
2353
 
@@ -2348,7 +2363,7 @@ def _clear_api_server_config() -> None:
2348
2363
  config = dict(config)
2349
2364
  del config['api_server']
2350
2365
 
2351
- common_utils.dump_yaml(str(config_path), config, blank=True)
2366
+ yaml_utils.dump_yaml(str(config_path), config, blank=True)
2352
2367
  skypilot_config.reload_config()
2353
2368
 
2354
2369
 
sky/client/sdk_async.py CHANGED
@@ -144,7 +144,8 @@ async def get(request_id: str) -> Any:
144
144
  async def stream_response_async(request_id: Optional[str],
145
145
  response: 'aiohttp.ClientResponse',
146
146
  output_stream: Optional['io.TextIOBase'] = None,
147
- resumable: bool = False) -> Any:
147
+ resumable: bool = False,
148
+ get_result: bool = True) -> Any:
148
149
  """Async version of stream_response that streams the response to the
149
150
  console.
150
151
 
@@ -155,6 +156,9 @@ async def stream_response_async(request_id: Optional[str],
155
156
  console.
156
157
  resumable: Whether the response is resumable on retry. If True, the
157
158
  streaming will start from the previous failure point on retry.
159
+
160
+ Returns:
161
+ Result of request_id if given. Will only return if get_result is True.
158
162
  """
159
163
 
160
164
  retry_context: Optional[rest.RetryContext] = None
@@ -170,7 +174,7 @@ async def stream_response_async(request_id: Optional[str],
170
174
  elif line_count > retry_context.line_processed:
171
175
  print(line, flush=True, end='', file=output_stream)
172
176
  retry_context.line_processed = line_count
173
- if request_id is not None:
177
+ if request_id is not None and get_result:
174
178
  return await get(request_id)
175
179
  except Exception: # pylint: disable=broad-except
176
180
  logger.debug(f'To stream request logs: sky api logs {request_id}')
sky/clouds/aws.py CHANGED
@@ -77,6 +77,103 @@ DEFAULT_SECURITY_GROUP_NAME = f'sky-sg-{common_utils.user_and_hostname_hash()}'
77
77
  # Security group to use when user specified ports in their resources.
78
78
  USER_PORTS_SECURITY_GROUP_NAME = 'sky-sg-{}'
79
79
 
80
+ # GPU instance types that support EFA
81
+ # TODO(hailong): Some CPU instance types also support EFA, may need to support
82
+ # all of them later.
83
+ # TODO(hailong): Add the EFA info in catalog.
84
+ _EFA_INSTANCE_TYPE_PREFIXES = [
85
+ 'g4dn.',
86
+ 'g5.',
87
+ 'g6.',
88
+ 'gr6.',
89
+ 'g6e.',
90
+ 'p4d.',
91
+ 'p4de.',
92
+ 'p5.',
93
+ 'p5e.',
94
+ 'p5en.',
95
+ 'p6-b200.',
96
+ ]
97
+
98
+ # Docker run options for EFA.
99
+ # Refer to https://github.com/ofiwg/libfabric/issues/6437 for updating
100
+ # memlock ulimit
101
+ _EFA_DOCKER_RUN_OPTIONS = [
102
+ '--cap-add=IPC_LOCK',
103
+ '--device=/dev/infiniband',
104
+ '--ulimit memlock=-1:-1',
105
+ ]
106
+
107
+ # AWS EFA image name.
108
+ # Refer to https://docs.aws.amazon.com/dlami/latest/devguide/aws-deep-learning-base-gpu-ami-ubuntu-22-04.html for latest version. # pylint: disable=line-too-long
109
+ # TODO(hailong): may need to update the version later.
110
+ _EFA_IMAGE_NAME = 'Deep Learning Base OSS Nvidia Driver GPU AMI' \
111
+ ' (Ubuntu 22.04) 20250808'
112
+
113
+
114
+ def _is_efa_instance_type(instance_type: str) -> bool:
115
+ """Check if the instance type is in EFA supported instance family."""
116
+ return any(
117
+ instance_type.startswith(prefix)
118
+ for prefix in _EFA_INSTANCE_TYPE_PREFIXES)
119
+
120
+
121
+ @annotations.lru_cache(scope='global', maxsize=128)
122
+ def _get_efa_image_id(region_name: str) -> Optional[str]:
123
+ """Get the EFA image id for the given region."""
124
+ try:
125
+ client = aws.client('ec2', region_name=region_name)
126
+ response = client.describe_images(Filters=[{
127
+ 'Name': 'name',
128
+ 'Values': [_EFA_IMAGE_NAME]
129
+ }])
130
+ if 'Images' not in response:
131
+ return None
132
+ if len(response['Images']) == 0:
133
+ return None
134
+ available_images = [
135
+ img for img in response['Images'] if img['State'] == 'available'
136
+ ]
137
+ if len(available_images) == 0:
138
+ return None
139
+ sorted_images = sorted(available_images,
140
+ key=lambda x: x['CreationDate'],
141
+ reverse=True)
142
+ return sorted_images[0]['ImageId']
143
+ except (aws.botocore_exceptions().NoCredentialsError,
144
+ aws.botocore_exceptions().ProfileNotFound,
145
+ aws.botocore_exceptions().ClientError) as e:
146
+ with ux_utils.print_exception_no_traceback():
147
+ raise ValueError(f'Failed to get EFA image id: {e}') from None
148
+
149
+
150
+ @annotations.lru_cache(scope='global', maxsize=128)
151
+ def _get_max_efa_interfaces(instance_type: str, region_name: str) -> int:
152
+ """Get the maximum number of EFA interfaces for the given instance type."""
153
+ if not _is_efa_instance_type(instance_type):
154
+ return 0
155
+ try:
156
+ client = aws.client('ec2', region_name=region_name)
157
+ response = client.describe_instance_types(
158
+ InstanceTypes=[instance_type],
159
+ Filters=[{
160
+ 'Name': 'network-info.efa-supported',
161
+ 'Values': ['true']
162
+ }])
163
+ if 'InstanceTypes' in response and len(response['InstanceTypes']) > 0:
164
+ network_info = response['InstanceTypes'][0]['NetworkInfo']
165
+ if ('EfaInfo' in network_info and
166
+ 'MaximumEfaInterfaces' in network_info['EfaInfo']):
167
+ return network_info['EfaInfo']['MaximumEfaInterfaces']
168
+ return 0
169
+ except (aws.botocore_exceptions().NoCredentialsError,
170
+ aws.botocore_exceptions().ProfileNotFound,
171
+ aws.botocore_exceptions().ClientError) as e:
172
+ with ux_utils.print_exception_no_traceback():
173
+ raise ValueError(
174
+ f'Failed to get max EFA interfaces for {instance_type}: {e}'
175
+ ) from None
176
+
80
177
 
81
178
  class AWSIdentityType(enum.Enum):
82
179
  """AWS identity type.
@@ -295,8 +392,13 @@ class AWS(clouds.Cloud):
295
392
  image_id: Optional[Dict[Optional[str], str]],
296
393
  region_name: str,
297
394
  instance_type: str,
395
+ enable_efa: bool,
298
396
  ) -> str:
299
397
  if image_id is None:
398
+ if enable_efa:
399
+ efa_image_id = _get_efa_image_id(region_name)
400
+ if efa_image_id:
401
+ return efa_image_id
300
402
  return cls._get_default_ami(region_name, instance_type)
301
403
  if None in image_id:
302
404
  image_id_str = image_id[None]
@@ -499,12 +601,25 @@ class AWS(clouds.Cloud):
499
601
  custom_resources = resources_utils.make_ray_custom_resources_str(
500
602
  acc_dict)
501
603
 
604
+ network_tier = (resources.network_tier if resources.network_tier
605
+ is not None else resources_utils.NetworkTier.STANDARD)
606
+ if network_tier == resources_utils.NetworkTier.BEST:
607
+ max_efa_interfaces = _get_max_efa_interfaces(
608
+ resources.instance_type, region_name)
609
+ enable_efa = max_efa_interfaces > 0
610
+ else:
611
+ max_efa_interfaces = 0
612
+ enable_efa = False
613
+
614
+ docker_run_options = []
502
615
  if resources.extract_docker_image() is not None:
503
616
  image_id_to_use = None
617
+ if enable_efa:
618
+ docker_run_options = _EFA_DOCKER_RUN_OPTIONS
504
619
  else:
505
620
  image_id_to_use = resources.image_id
506
621
  image_id = self._get_image_id(image_id_to_use, region_name,
507
- resources.instance_type)
622
+ resources.instance_type, enable_efa)
508
623
 
509
624
  root_device_name = self.get_image_root_device_name(
510
625
  image_id, region_name)
@@ -563,6 +678,8 @@ class AWS(clouds.Cloud):
563
678
  'security_group': security_group,
564
679
  'security_group_managed_by_skypilot':
565
680
  str(security_group != user_security_group).lower(),
681
+ 'max_efa_interfaces': max_efa_interfaces,
682
+ 'docker_run_options': docker_run_options,
566
683
  **AWS._get_disk_specs(resources.disk_tier)
567
684
  }
568
685
 
sky/core.py CHANGED
@@ -594,10 +594,7 @@ def down(cluster_name: str, purge: bool = False) -> None:
594
594
 
595
595
  usage_lib.record_cluster_name_for_current_operation(cluster_name)
596
596
  backend = backend_utils.get_backend_from_handle(handle)
597
- backend.teardown(handle,
598
- terminate=True,
599
- purge=purge,
600
- explicitly_requested=True)
597
+ backend.teardown(handle, terminate=True, purge=purge)
601
598
 
602
599
 
603
600
  @usage_lib.entrypoint
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-c66a4e8afc46f17b.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/clusters/%5Bcluster%5D/%5Bjob%5D-06afb50d25f7c61f.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/clusters/[cluster]/[job]","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/clusters/%5Bcluster%5D/%5Bjob%5D-06afb50d25f7c61f.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/clusters/[cluster]/[job]","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/4676-9da7fdbde90b5549.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6990-08b2a1cae076a943.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/1121-8afcf719ea87debc.js" defer=""></script><script src="/dashboard/_next/static/chunks/6856-049014c6d43d127b.js" defer=""></script><script src="/dashboard/_next/static/chunks/6601-06114c982db410b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/3015-6c9c09593b1e67b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/9037-89a84fd7fa31362d.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/clusters/%5Bcluster%5D-a0527109c2fab467.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/clusters/[cluster]","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/4676-9da7fdbde90b5549.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6990-08b2a1cae076a943.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/1121-8afcf719ea87debc.js" defer=""></script><script src="/dashboard/_next/static/chunks/6856-049014c6d43d127b.js" defer=""></script><script src="/dashboard/_next/static/chunks/6601-06114c982db410b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/3015-6c9c09593b1e67b6.js" defer=""></script><script src="/dashboard/_next/static/chunks/9037-89a84fd7fa31362d.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/clusters/%5Bcluster%5D-a0527109c2fab467.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/clusters/[cluster]","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/clusters-469814d711d63b1b.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/clusters","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/clusters-469814d711d63b1b.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/clusters","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/config-dfb9bf07b13045f4.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/config","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/config-dfb9bf07b13045f4.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/config","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/index-444f1804401f04ea.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/index-444f1804401f04ea.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra/%5Bcontext%5D-81351f95f3bec08e.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra/[context]","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra/%5Bcontext%5D-81351f95f3bec08e.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra/[context]","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra-c320641c2bcbbea6.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/infra-c320641c2bcbbea6.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/infra","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-dd64309c3fe67ed2.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/7411-b15471acd2cba716.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/6135-4b4d5e824b7f9d3c.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/%5Bjob%5D-dd64309c3fe67ed2.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/[job]","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/pools/%5Bpool%5D-07349868f7905d37.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/-eL7Ky3bxVivzeLHNB9U6/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/pools/[pool]","query":{},"buildId":"-eL7Ky3bxVivzeLHNB9U6","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/dashboard/_next/static/css/4614e06482d7309e.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/4614e06482d7309e.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/dashboard/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js"></script><script src="/dashboard/_next/static/chunks/webpack-6e76f636a048e145.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-cf60a09ccd051a10.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-f15ccb73239a3bf1.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-ce361c6959bc2001.js" defer=""></script><script src="/dashboard/_next/static/chunks/616-3d59f75e2ccf9321.js" defer=""></script><script src="/dashboard/_next/static/chunks/6130-2be46d70a38f1e82.js" defer=""></script><script src="/dashboard/_next/static/chunks/5739-d67458fcb1386c92.js" defer=""></script><script src="/dashboard/_next/static/chunks/1272-1ef0bf0237faccdb.js" defer=""></script><script src="/dashboard/_next/static/chunks/754-d0da8ab45f9509e9.js" defer=""></script><script src="/dashboard/_next/static/chunks/6989-01359c57e018caa4.js" defer=""></script><script src="/dashboard/_next/static/chunks/3850-ff4a9a69d978632b.js" defer=""></script><script src="/dashboard/_next/static/chunks/8969-4a6f1a928fb6d370.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/jobs/pools/%5Bpool%5D-07349868f7905d37.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/hYJYFIxp_ZFONR4wTIJqZ/_ssgManifest.js" defer=""></script></head><body><div id="__next"></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/jobs/pools/[pool]","query":{},"buildId":"hYJYFIxp_ZFONR4wTIJqZ","assetPrefix":"/dashboard","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>