skypilot-nightly 1.0.0.dev20250616__py3-none-any.whl → 1.0.0.dev20250618__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.
Files changed (92) hide show
  1. sky/__init__.py +2 -4
  2. sky/backends/backend_utils.py +7 -0
  3. sky/backends/cloud_vm_ray_backend.py +91 -96
  4. sky/cli.py +5 -6311
  5. sky/client/cli.py +66 -639
  6. sky/client/sdk.py +22 -2
  7. sky/clouds/kubernetes.py +8 -0
  8. sky/clouds/scp.py +7 -26
  9. sky/clouds/utils/scp_utils.py +177 -124
  10. sky/dashboard/out/404.html +1 -1
  11. sky/dashboard/out/_next/static/{OZxMW3bxAJmqgn5f4MdhO → LRpGymRCqq-feuFyoWz4m}/_buildManifest.js +1 -1
  12. sky/dashboard/out/_next/static/chunks/641.c8e452bc5070a630.js +1 -0
  13. sky/dashboard/out/_next/static/chunks/984.ae8c08791d274ca0.js +50 -0
  14. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-36bc0962129f72df.js +6 -0
  15. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-cf490d1fa38f3740.js +16 -0
  16. sky/dashboard/out/_next/static/chunks/pages/users-928edf039219e47b.js +1 -0
  17. sky/dashboard/out/_next/static/chunks/webpack-ebc2404fd6ce581c.js +1 -0
  18. sky/dashboard/out/_next/static/css/6c12ecc3bd2239b6.css +3 -0
  19. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  20. sky/dashboard/out/clusters/[cluster].html +1 -1
  21. sky/dashboard/out/clusters.html +1 -1
  22. sky/dashboard/out/config.html +1 -1
  23. sky/dashboard/out/index.html +1 -1
  24. sky/dashboard/out/infra/[context].html +1 -1
  25. sky/dashboard/out/infra.html +1 -1
  26. sky/dashboard/out/jobs/[job].html +1 -1
  27. sky/dashboard/out/jobs.html +1 -1
  28. sky/dashboard/out/users.html +1 -1
  29. sky/dashboard/out/workspace/new.html +1 -1
  30. sky/dashboard/out/workspaces/[name].html +1 -1
  31. sky/dashboard/out/workspaces.html +1 -1
  32. sky/global_user_state.py +50 -11
  33. sky/jobs/controller.py +98 -31
  34. sky/jobs/scheduler.py +37 -29
  35. sky/jobs/server/core.py +36 -3
  36. sky/jobs/state.py +69 -9
  37. sky/jobs/utils.py +11 -0
  38. sky/logs/__init__.py +17 -0
  39. sky/logs/agent.py +73 -0
  40. sky/logs/gcp.py +91 -0
  41. sky/models.py +1 -0
  42. sky/provision/__init__.py +1 -0
  43. sky/provision/instance_setup.py +35 -0
  44. sky/provision/provisioner.py +11 -0
  45. sky/provision/scp/__init__.py +15 -0
  46. sky/provision/scp/config.py +93 -0
  47. sky/provision/scp/instance.py +528 -0
  48. sky/resources.py +164 -29
  49. sky/server/common.py +21 -9
  50. sky/server/requests/payloads.py +19 -1
  51. sky/server/server.py +121 -29
  52. sky/setup_files/dependencies.py +11 -1
  53. sky/skylet/constants.py +48 -1
  54. sky/skylet/job_lib.py +83 -19
  55. sky/task.py +171 -21
  56. sky/templates/kubernetes-ray.yml.j2 +60 -4
  57. sky/templates/scp-ray.yml.j2 +3 -50
  58. sky/users/permission.py +47 -34
  59. sky/users/rbac.py +10 -1
  60. sky/users/server.py +274 -9
  61. sky/utils/command_runner.py +1 -1
  62. sky/utils/common_utils.py +16 -14
  63. sky/utils/context.py +1 -1
  64. sky/utils/controller_utils.py +12 -3
  65. sky/utils/dag_utils.py +17 -4
  66. sky/utils/kubernetes/deploy_remote_cluster.py +17 -8
  67. sky/utils/schemas.py +83 -5
  68. {skypilot_nightly-1.0.0.dev20250616.dist-info → skypilot_nightly-1.0.0.dev20250618.dist-info}/METADATA +9 -1
  69. {skypilot_nightly-1.0.0.dev20250616.dist-info → skypilot_nightly-1.0.0.dev20250618.dist-info}/RECORD +80 -79
  70. sky/benchmark/__init__.py +0 -0
  71. sky/benchmark/benchmark_state.py +0 -295
  72. sky/benchmark/benchmark_utils.py +0 -641
  73. sky/dashboard/out/_next/static/chunks/600.bd2ed8c076b720ec.js +0 -16
  74. sky/dashboard/out/_next/static/chunks/pages/clusters/[cluster]-59950b2f83b66e48.js +0 -6
  75. sky/dashboard/out/_next/static/chunks/pages/jobs/[job]-b3dbf38b51cb29be.js +0 -16
  76. sky/dashboard/out/_next/static/chunks/pages/users-c69ffcab9d6e5269.js +0 -1
  77. sky/dashboard/out/_next/static/chunks/webpack-1b69b196a4dbffef.js +0 -1
  78. sky/dashboard/out/_next/static/css/8e97adcaacc15293.css +0 -3
  79. sky/skylet/providers/scp/__init__.py +0 -2
  80. sky/skylet/providers/scp/config.py +0 -149
  81. sky/skylet/providers/scp/node_provider.py +0 -578
  82. /sky/dashboard/out/_next/static/{OZxMW3bxAJmqgn5f4MdhO → LRpGymRCqq-feuFyoWz4m}/_ssgManifest.js +0 -0
  83. /sky/dashboard/out/_next/static/chunks/{37-824c707421f6f003.js → 37-3a4d77ad62932eaf.js} +0 -0
  84. /sky/dashboard/out/_next/static/chunks/{843-ab9c4f609239155f.js → 843-b3040e493f6e7947.js} +0 -0
  85. /sky/dashboard/out/_next/static/chunks/{938-385d190b95815e11.js → 938-1493ac755eadeb35.js} +0 -0
  86. /sky/dashboard/out/_next/static/chunks/{973-c807fc34f09c7df3.js → 973-db3c97c2bfbceb65.js} +0 -0
  87. /sky/dashboard/out/_next/static/chunks/pages/{_app-32b2caae3445bf3b.js → _app-c416e87d5c2715cf.js} +0 -0
  88. /sky/dashboard/out/_next/static/chunks/pages/workspaces/{[name]-c8c2191328532b7d.js → [name]-c4ff1ec05e2f3daf.js} +0 -0
  89. {skypilot_nightly-1.0.0.dev20250616.dist-info → skypilot_nightly-1.0.0.dev20250618.dist-info}/WHEEL +0 -0
  90. {skypilot_nightly-1.0.0.dev20250616.dist-info → skypilot_nightly-1.0.0.dev20250618.dist-info}/entry_points.txt +0 -0
  91. {skypilot_nightly-1.0.0.dev20250616.dist-info → skypilot_nightly-1.0.0.dev20250618.dist-info}/licenses/LICENSE +0 -0
  92. {skypilot_nightly-1.0.0.dev20250616.dist-info → skypilot_nightly-1.0.0.dev20250618.dist-info}/top_level.txt +0 -0
sky/client/sdk.py CHANGED
@@ -1856,6 +1856,7 @@ def api_start(
1856
1856
  deploy: bool = False,
1857
1857
  host: str = '127.0.0.1',
1858
1858
  foreground: bool = False,
1859
+ enable_basic_auth: bool = False,
1859
1860
  ) -> None:
1860
1861
  """Starts the API server.
1861
1862
 
@@ -1869,6 +1870,8 @@ def api_start(
1869
1870
  if deploy is True, to allow remote access.
1870
1871
  foreground: Whether to run the API server in the foreground (run in
1871
1872
  the current process).
1873
+ enable_basic_auth: Whether to enable basic authentication
1874
+ in the API server.
1872
1875
  Returns:
1873
1876
  None
1874
1877
  """
@@ -1887,7 +1890,8 @@ def api_start(
1887
1890
  'from the config file and/or unset the '
1888
1891
  'SKYPILOT_API_SERVER_ENDPOINT environment '
1889
1892
  'variable.')
1890
- server_common.check_server_healthy_or_start_fn(deploy, host, foreground)
1893
+ server_common.check_server_healthy_or_start_fn(deploy, host, foreground,
1894
+ enable_basic_auth)
1891
1895
  if foreground:
1892
1896
  # Explain why current process exited
1893
1897
  logger.info('API server is already running:')
@@ -1990,7 +1994,8 @@ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
1990
1994
  raise click.BadParameter('Endpoint must be a valid URL.')
1991
1995
  endpoint = endpoint.rstrip('/')
1992
1996
 
1993
- server_status = server_common.check_server_healthy(endpoint)
1997
+ server_status, api_server_info = server_common.check_server_healthy(
1998
+ endpoint)
1994
1999
  if server_status == server_common.ApiServerStatus.NEEDS_AUTH or get_token:
1995
2000
  # We detected an auth proxy, so go through the auth proxy cookie flow.
1996
2001
  token: Optional[str] = None
@@ -2121,6 +2126,21 @@ def api_login(endpoint: Optional[str] = None, get_token: bool = False) -> None:
2121
2126
  'w',
2122
2127
  encoding='utf-8') as f:
2123
2128
  f.write(user_hash)
2129
+ else:
2130
+ # Check if basic auth is enabled
2131
+ if api_server_info.basic_auth_enabled:
2132
+ if api_server_info.user is None:
2133
+ with ux_utils.print_exception_no_traceback():
2134
+ raise ValueError(
2135
+ 'Basic auth is enabled but no valid user is found')
2136
+ # Set the user hash in the local file
2137
+ user_hash = api_server_info.user.get('id')
2138
+ if not user_hash or not common_utils.is_valid_user_hash(user_hash):
2139
+ raise ValueError(f'Invalid user hash: {user_hash}')
2140
+ with open(os.path.expanduser('~/.sky/user_hash'),
2141
+ 'w',
2142
+ encoding='utf-8') as f:
2143
+ f.write(user_hash)
2124
2144
 
2125
2145
  # Set the endpoint in the config file
2126
2146
  config_path = pathlib.Path(
sky/clouds/kubernetes.py CHANGED
@@ -602,6 +602,10 @@ class Kubernetes(clouds.Cloud):
602
602
  None,
603
603
  override_configs=resources.cluster_config_overrides)
604
604
 
605
+ k8s_kueue_local_queue_name = skypilot_config.get_nested(
606
+ ('kubernetes', 'kueue', 'local_queue_name'),
607
+ None,
608
+ override_configs=resources.cluster_config_overrides)
605
609
  deploy_vars = {
606
610
  'instance_type': resources.instance_type,
607
611
  'custom_resources': custom_resources,
@@ -619,6 +623,7 @@ class Kubernetes(clouds.Cloud):
619
623
  'k8s_service_account_name': k8s_service_account_name,
620
624
  'k8s_automount_sa_token': 'true',
621
625
  'k8s_fuse_device_required': fuse_device_required,
626
+ 'k8s_kueue_local_queue_name': k8s_kueue_local_queue_name,
622
627
  # Namespace to run the fusermount-server daemonset in
623
628
  'k8s_skypilot_system_namespace': _SKYPILOT_SYSTEM_NAMESPACE,
624
629
  'k8s_fusermount_shared_dir': _FUSERMOUNT_SHARED_DIR,
@@ -646,6 +651,9 @@ class Kubernetes(clouds.Cloud):
646
651
  (constants.PERSISTENT_SETUP_SCRIPT_PATH),
647
652
  'k8s_high_availability_deployment_run_script_dir':
648
653
  (constants.PERSISTENT_RUN_SCRIPT_DIR),
654
+ 'k8s_high_availability_restarting_signal_file':
655
+ (constants.PERSISTENT_RUN_RESTARTING_SIGNAL_FILE),
656
+ 'sky_python_cmd': constants.SKY_PYTHON_CMD,
649
657
  'k8s_high_availability_storage_class_name':
650
658
  (k8s_ha_storage_class_name),
651
659
  'avoid_label_keys': avoid_label_keys,
sky/clouds/scp.py CHANGED
@@ -59,14 +59,15 @@ class SCP(clouds.Cloud):
59
59
  clouds.CloudImplementationFeatures.CUSTOM_NETWORK_TIER:
60
60
  ('Custom network tier is currently not supported in '
61
61
  f'{_REPR}.'),
62
- clouds.CloudImplementationFeatures.OPEN_PORTS:
63
- (f'Opening ports is currently not supported on {_REPR}.'),
64
62
  clouds.CloudImplementationFeatures.HIGH_AVAILABILITY_CONTROLLERS:
65
63
  (f'High availability controllers are not supported on {_REPR}.'),
66
64
  }
67
65
 
68
66
  _INDENT_PREFIX = ' '
69
67
 
68
+ PROVISIONER_VERSION = clouds.ProvisionerVersion.SKYPILOT
69
+ STATUS_VERSION = clouds.StatusVersion.SKYPILOT
70
+
70
71
  @classmethod
71
72
  def _unsupported_features_for_resources(
72
73
  cls, resources: 'resources_lib.Resources'
@@ -243,7 +244,7 @@ class SCP(clouds.Cloud):
243
244
  clouds='scp')
244
245
  if acc is not None:
245
246
  assert len(acc) == 1, acc
246
- image_id = catalog.get_image_id_from_tag('skypilot:gpu-ubuntu-1804',
247
+ image_id = catalog.get_image_id_from_tag('skypilot:gpu-ubuntu-2204',
247
248
  region_name,
248
249
  clouds='scp')
249
250
  if image_id is not None:
@@ -325,7 +326,7 @@ class SCP(clouds.Cloud):
325
326
  """Checks if the user has access credentials to
326
327
  SCP's compute service."""
327
328
  try:
328
- scp_utils.SCPClient().list_instances()
329
+ scp_utils.SCPClient().get_instances()
329
330
  except (AssertionError, KeyError, scp_utils.SCPClientError,
330
331
  scp_utils.SCPCreationFailError):
331
332
  return False, (
@@ -374,25 +375,5 @@ class SCP(clouds.Cloud):
374
375
  region: Optional[str], zone: Optional[str],
375
376
  **kwargs) -> List[status_lib.ClusterStatus]:
376
377
  del tag_filters, region, zone, kwargs # Unused.
377
-
378
- # TODO: Multi-node is not supported yet.
379
-
380
- status_map = {
381
- 'CREATING': status_lib.ClusterStatus.INIT,
382
- 'EDITING': status_lib.ClusterStatus.INIT,
383
- 'RUNNING': status_lib.ClusterStatus.UP,
384
- 'STARTING': status_lib.ClusterStatus.INIT,
385
- 'RESTARTING': status_lib.ClusterStatus.INIT,
386
- 'STOPPING': status_lib.ClusterStatus.STOPPED,
387
- 'STOPPED': status_lib.ClusterStatus.STOPPED,
388
- 'TERMINATING': None,
389
- 'TERMINATED': None,
390
- }
391
- status_list = []
392
- vms = scp_utils.SCPClient().list_instances()
393
- for node in vms:
394
- if node['virtualServerName'] == name:
395
- node_status = status_map[node['virtualServerState']]
396
- if node_status is not None:
397
- status_list.append(node_status)
398
- return status_list
378
+ # TODO: deprecate this method
379
+ assert False, 'This code path should not be used.'
@@ -184,7 +184,7 @@ class SCPClient:
184
184
 
185
185
  def create_instance(self, instance_config):
186
186
  """Launch new instances."""
187
- url = f'{API_ENDPOINT}/virtual-server/v3/virtual-servers'
187
+ url = f'{API_ENDPOINT}/virtual-server/v4/virtual-servers'
188
188
  return self._post(url, instance_config)
189
189
 
190
190
  @_retry
@@ -226,105 +226,113 @@ class SCPClient:
226
226
  raise_scp_error(response)
227
227
  return response.json()
228
228
 
229
- def create_security_group(self, zone_id, vpc, sg_name):
229
+ def create_security_group(self, zone_id, vpc_id, sg_name):
230
230
  url = f'{API_ENDPOINT}/security-group/v3/security-groups'
231
231
  request_body = {
232
232
  'loggable': False,
233
233
  'securityGroupName': sg_name,
234
234
  'serviceZoneId': zone_id,
235
- 'vpcId': vpc,
236
- 'securityGroupDescription': 'skypilot sg'
235
+ 'vpcId': vpc_id,
236
+ 'securityGroupDescription': 'sky security group'
237
237
  }
238
238
  return self._post(url, request_body)
239
239
 
240
- def add_security_group_in_rule(self, sg_id):
241
- url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules'
242
- request_body = {
243
- 'ruleDirection': 'IN',
244
- 'services': [{
245
- 'serviceType': 'TCP',
246
- 'serviceValue': '22'
247
- }],
248
- 'sourceIpAddresses': ['0.0.0.0/0'],
249
- 'ruleDescription': 'skypilot ssh rule'
250
- }
251
- return self._post(url, request_body)
252
-
253
- def add_security_group_out_rule(self, sg_id):
254
- url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules'
255
- request_body = {
256
- 'ruleDirection': 'OUT',
257
- 'services': [{
258
- 'serviceType': 'TCP',
259
- 'serviceValue': '21'
260
- }, {
261
- 'serviceType': 'TCP',
262
- 'serviceValue': '22'
263
- }, {
264
- 'serviceType': 'TCP',
265
- 'serviceValue': '80'
266
- }, {
267
- 'serviceType': 'TCP',
268
- 'serviceValue': '443'
269
- }],
270
- 'destinationIpAddresses': ['0.0.0.0/0'],
271
- 'ruleDescription': 'skypilot out rule'
272
- }
273
- return self._post(url, request_body)
274
-
275
- def add_firewall_inbound_rule(self, firewall_id, internal_ip):
276
- url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
277
- request_body = {
278
- 'sourceIpAddresses': ['0.0.0.0/0'],
279
- 'destinationIpAddresses': [internal_ip],
280
- 'services': [{
281
- 'serviceType': 'TCP',
282
- 'serviceValue': '22'
283
- }],
284
- 'ruleDirection': 'IN',
285
- 'ruleAction': 'ALLOW',
286
- 'isRuleEnabled': True,
287
- 'ruleLocationType': 'FIRST',
288
- 'ruleDescription': 'description'
289
- }
290
- return self._post(url, request_body)
291
-
292
- def add_firewall_outbound_rule(self, firewall_id, internal_ip):
293
- url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
294
- request_body = {
295
- 'sourceIpAddresses': [internal_ip],
296
- 'destinationIpAddresses': ['0.0.0.0/0'],
297
- 'services': [{
298
- 'serviceType': 'TCP',
299
- 'serviceValue': '21'
300
- }, {
301
- 'serviceType': 'TCP',
302
- 'serviceValue': '22'
303
- }, {
304
- 'serviceType': 'TCP',
305
- 'serviceValue': '80'
306
- }, {
307
- 'serviceType': 'TCP',
308
- 'serviceValue': '443'
309
- }],
310
- 'ruleDirection': 'OUT',
311
- 'ruleAction': 'ALLOW',
312
- 'isRuleEnabled': True,
313
- 'ruleLocationType': 'FIRST',
314
- 'ruleDescription': 'description'
315
- }
316
- return self._post(url, request_body)
240
+ def _security_group_rule_not_exist(self, sg_id, direction, ports):
241
+ response = self.get_security_group_rules(sg_id)
242
+ rules = []
243
+ for rule in response:
244
+ rule_direction = rule['ruleDirection']
245
+ if rule_direction == direction:
246
+ rules.append(rule)
247
+ for rule in rules:
248
+ port_list = ','.join(rule['tcpServices'])
249
+ port = ','.join(ports)
250
+ if port == port_list:
251
+ return False
252
+ return True
253
+
254
+ def add_security_group_rule(self, sg_id, direction,
255
+ ports: Optional[List[str]]):
256
+ if ports is None:
257
+ if direction == 'IN':
258
+ ports = ['22']
259
+ else:
260
+ ports = ['21', '22', '80', '443']
261
+ services = []
262
+ for port in ports:
263
+ services.append({'serviceType': 'TCP', 'serviceValue': port})
264
+ if self._security_group_rule_not_exist(sg_id, direction, ports):
265
+ url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules' # pylint: disable=line-too-long
266
+ if direction == 'IN':
267
+ target_address = 'sourceIpAddresses'
268
+ else:
269
+ target_address = 'destinationIpAddresses'
270
+ request_body = {
271
+ 'ruleDirection': direction,
272
+ 'services': services,
273
+ target_address: ['0.0.0.0/0'],
274
+ 'ruleDescription': 'sky security group rule'
275
+ }
276
+ return self._post(url, request_body)
277
+
278
+ def _firewall_rule_not_exist(self, firewall_id, internal_ip, direction,
279
+ ports):
280
+ response = self.get_firewall_rules(firewall_id)
281
+ rules = []
282
+ for rule in response:
283
+ if direction == 'IN':
284
+ if internal_ip == rule['destinationIpAddresses'][0]:
285
+ rules.append(rule)
286
+ else:
287
+ if internal_ip == rule['sourceIpAddresses'][0]:
288
+ rules.append(rule)
289
+ for rule in rules:
290
+ port_list = ','.join(rule['tcpServices'])
291
+ port = ','.join(ports)
292
+ if port == port_list:
293
+ return False
294
+ return True
295
+
296
+ def add_firewall_rule(self, firewall_id, internal_ip, direction, ports):
297
+ if ports is None:
298
+ if direction == 'IN':
299
+ ports = ['22']
300
+ else:
301
+ ports = ['21', '22', '80', '443']
302
+ services = []
303
+ for port in ports:
304
+ services.append({'serviceType': 'TCP', 'serviceValue': port})
305
+ if self._firewall_rule_not_exist(firewall_id, internal_ip, direction,
306
+ ports):
307
+ url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
308
+ if direction == 'IN':
309
+ source_ip = '0.0.0.0/0'
310
+ destination_ip = internal_ip
311
+ else:
312
+ source_ip = internal_ip
313
+ destination_ip = '0.0.0.0/0'
314
+ request_body = {
315
+ 'sourceIpAddresses': [source_ip],
316
+ 'destinationIpAddresses': [destination_ip],
317
+ 'services': services,
318
+ 'ruleDirection': direction,
319
+ 'ruleAction': 'ALLOW',
320
+ 'isRuleEnabled': True,
321
+ 'ruleLocationType': 'FIRST',
322
+ 'ruleDescription': 'sky firewall rule'
323
+ }
324
+ return self._post(url, request_body)
317
325
 
318
- def terminate_instance(self, vm_id):
319
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{vm_id}'
326
+ def terminate_instance(self, instance_id):
327
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}'
320
328
  return self._delete(url)
321
329
 
322
- def list_instances(self) -> List[dict]:
330
+ def get_instances(self) -> List[dict]:
323
331
  """List existing instances."""
324
332
  url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers'
325
333
  return self._get(url)
326
334
 
327
- def list_catalog(self) -> Dict[str, Any]:
335
+ def get_catalog(self) -> Dict[str, Any]:
328
336
  """List offered instances and their availability."""
329
337
  response = requests.get(f'{API_ENDPOINT}/instance-types',
330
338
  headers=self.headers)
@@ -362,89 +370,134 @@ class SCPClient:
362
370
  self.headers['X-Cmp-Timestamp'] = self.timestamp
363
371
 
364
372
  def set_signature(self, method: str, url: str) -> None:
365
-
366
373
  self.signature = self.get_signature(url=url, method=method)
367
374
  self.headers['X-Cmp-Signature'] = self.signature
368
375
 
369
- def list_nic_details(self, virtual_server_id) -> List[dict]:
370
- """List existing instances."""
371
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{virtual_server_id}/nics' # pylint: disable=line-too-long
376
+ def get_nic(self, instance_id) -> List[dict]:
377
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}/nics' # pylint: disable=line-too-long
372
378
  return self._get(url)
373
379
 
374
- def get_external_ip(self, virtual_server_id, ip):
375
- nic_details_list = self.list_nic_details(
376
- virtual_server_id=virtual_server_id)
377
- for nic_details in nic_details_list:
378
- if (nic_details['ip'] == ip and
379
- nic_details['subnetType'] == 'PUBLIC'):
380
- return nic_details['natIp']
380
+ def get_external_ip(self, instance_id, ip):
381
+ nics = self.get_nic(instance_id=instance_id)
382
+ for nic in nics:
383
+ if (nic['ip'] == ip and nic['subnetType'] == 'PUBLIC'):
384
+ return nic['natIp']
381
385
  return None
382
386
 
383
- def list_zones(self) -> List[dict]:
387
+ def get_zones(self) -> List[dict]:
384
388
  url = f'{API_ENDPOINT}/project/v3/projects/{self.project_id}/zones'
385
389
  return self._get(url)
386
390
 
387
- def list_products(self, service_zone_id) -> List[dict]:
388
- url = f'{API_ENDPOINT}/product/v2/zones/{service_zone_id}/products'
389
- return self._get(url)
390
-
391
- def list_product_groups(self, service_zone_id) -> List[dict]:
392
- url = f'{API_ENDPOINT}/product/v2/zones/{service_zone_id}/product-groups' # pylint: disable=line-too-long
393
- return self._get(url)
394
-
395
- def list_vpcs(self, service_zone_id) -> List[dict]:
391
+ def get_vpcs(self, service_zone_id) -> List[dict]:
396
392
  url = f'{API_ENDPOINT}/vpc/v2/vpcs?serviceZoneId={service_zone_id}'
397
393
  return self._get(url)
398
394
 
399
- def list_subnets(self) -> List[dict]:
395
+ def get_subnets(self) -> List[dict]:
400
396
  url = f'{API_ENDPOINT}/subnet/v2/subnets?subnetTypes=PUBLIC'
401
397
  return self._get(url)
402
398
 
403
- def del_security_group(self, sg_id):
399
+ def delete_security_group(self, sg_id):
404
400
  url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}'
405
401
  return self._delete(url)
406
402
 
407
- def del_firwall_rules(self, firewall_id, rule_id_list):
403
+ def delete_firewall_rule(self, firewall_id, rule_ids):
408
404
  url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
409
- request_body = {'ruleDeletionType': 'PARTIAL', 'ruleIds': rule_id_list}
405
+ request_body = {'ruleDeletionType': 'PARTIAL', 'ruleIds': rule_ids}
410
406
  return self._delete(url, request_body=request_body)
411
407
 
412
- def list_security_groups(self, vpc_id=None, sg_name=None):
408
+ def get_security_groups(self, vpc_id=None, sg_name=None):
413
409
  url = f'{API_ENDPOINT}/security-group/v2/security-groups'
414
410
  parameter = []
415
411
  if vpc_id is not None:
416
412
  parameter.append('vpcId=' + vpc_id)
417
413
  if sg_name is not None:
418
414
  parameter.append('securityGroupName=' + sg_name)
419
- if parameter:
415
+ if len(parameter) > 0:
420
416
  url = url + '?' + '&'.join(parameter)
421
417
  return self._get(url)
422
418
 
423
- def list_igw(self):
419
+ def get_internet_gateway(self):
424
420
  url = f'{API_ENDPOINT}/internet-gateway/v2/internet-gateways'
425
421
  return self._get(url)
426
422
 
427
- def get_vm_info(self, vm_id):
428
- url = f'{API_ENDPOINT}/virtual-server/v3/virtual-servers/{vm_id}'
429
- return self._get(url, contents_key=None)
430
-
431
- def get_firewal_rule_info(self, firewall_id, rule_id):
423
+ def get_firewall_rule_info(self, firewall_id, rule_id):
432
424
  url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules/{rule_id}' # pylint: disable=line-too-long
433
425
  return self._get(url, contents_key=None)
434
426
 
435
- def list_firwalls(self):
427
+ def get_firewalls(self):
436
428
  url = f'{API_ENDPOINT}/firewall/v2/firewalls'
437
429
  return self._get(url)
438
430
 
439
- def list_service_zone_names(self):
431
+ def get_service_zone_names(self):
440
432
  url = f'{API_ENDPOINT}/project/v3/projects/{self.project_id}/zones'
441
433
  zone_contents = self._get(url)
442
434
  return [content['serviceZoneName'] for content in zone_contents]
443
435
 
444
- def start_instance(self, vm_id):
445
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{vm_id}/start'
436
+ def start_instance(self, instance_id):
437
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}/start' # pylint: disable=line-too-long
446
438
  return self._post(url=url, request_body={})
447
439
 
448
- def stop_instance(self, vm_id):
449
- url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{vm_id}/stop'
440
+ def stop_instance(self, instance_id):
441
+ url = f'{API_ENDPOINT}/virtual-server/v2/virtual-servers/{instance_id}/stop' # pylint: disable=line-too-long
450
442
  return self._post(url=url, request_body={})
443
+
444
+ def get_security_group_rules(self, sg_id):
445
+ url = f'{API_ENDPOINT}/security-group/v2/security-groups/{sg_id}/rules'
446
+ return self._get(url)
447
+
448
+ def get_firewall_rules(self, firewall_id):
449
+ url = f'{API_ENDPOINT}/firewall/v2/firewalls/{firewall_id}/rules'
450
+ return self._get(url)
451
+
452
+ def get_instance_info(self, instance_id):
453
+ url = f'{API_ENDPOINT}/virtual-server/v3/virtual-servers/{instance_id}'
454
+ return self._get(url=url, contents_key=None)
455
+
456
+ def create_vpc(self, zone_id):
457
+ vpc_name = 'skyvpc' + zone_id[5:10]
458
+ request_body = {
459
+ 'serviceZoneId': zone_id,
460
+ 'vpcName': vpc_name,
461
+ 'vpcDescription': 'sky vpc'
462
+ }
463
+ url = f'{API_ENDPOINT}/vpc/v3/vpcs'
464
+ return self._post(url, request_body)
465
+
466
+ def create_subnet(self, vpc_id, zone_id):
467
+ subnet_name = 'skysubnet' + zone_id[5:10]
468
+ request_body = {
469
+ 'subnetCidrBlock': '192.168.0.0/24',
470
+ 'subnetName': subnet_name,
471
+ 'subnetType': 'PUBLIC',
472
+ 'vpcId': vpc_id,
473
+ 'subnetDescription': 'sky subnet'
474
+ }
475
+ url = f'{API_ENDPOINT}/subnet/v2/subnets'
476
+ return self._post(url, request_body)
477
+
478
+ def create_internet_gateway(self, vpc_id):
479
+ request_body = {
480
+ 'firewallEnabled': True,
481
+ 'firewallLoggable': False,
482
+ 'internetGatewayType': 'SHARED',
483
+ 'vpcId': vpc_id,
484
+ 'internetGatewayDescription': 'sky internet gateway'
485
+ }
486
+ url = f'{API_ENDPOINT}/internet-gateway/v4/internet-gateways'
487
+ return self._post(url, request_body)
488
+
489
+ def get_vpc_info(self, vpc_id):
490
+ url = f'{API_ENDPOINT}/vpc/v2/vpcs/{vpc_id}'
491
+ return self._get(url=url, contents_key=None)
492
+
493
+ def get_subnet_info(self, subnet_id):
494
+ url = f'{API_ENDPOINT}/subnet/v2/subnets/{subnet_id}'
495
+ return self._get(url=url, contents_key=None)
496
+
497
+ def get_internet_gateway_info(self, internet_gateway_id):
498
+ url = f'{API_ENDPOINT}/internet-gateway/v2/internet-gateways/{internet_gateway_id}' # pylint: disable=line-too-long
499
+ return self._get(url=url, contents_key=None)
500
+
501
+ def get_key_pairs(self):
502
+ url = f'{API_ENDPOINT}/key-pair/v1/key-pairs'
503
+ return self._get(url=url, contents_key=None)
@@ -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/8e97adcaacc15293.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/8e97adcaacc15293.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-1b69b196a4dbffef.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-32b2caae3445bf3b.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/OZxMW3bxAJmqgn5f4MdhO/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/OZxMW3bxAJmqgn5f4MdhO/_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":"OZxMW3bxAJmqgn5f4MdhO","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/6c12ecc3bd2239b6.css" as="style"/><link rel="stylesheet" href="/dashboard/_next/static/css/6c12ecc3bd2239b6.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-ebc2404fd6ce581c.js" defer=""></script><script src="/dashboard/_next/static/chunks/framework-87d061ee6ed71b28.js" defer=""></script><script src="/dashboard/_next/static/chunks/main-e0e2335212e72357.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_app-c416e87d5c2715cf.js" defer=""></script><script src="/dashboard/_next/static/chunks/pages/_error-1be831200e60c5c0.js" defer=""></script><script src="/dashboard/_next/static/LRpGymRCqq-feuFyoWz4m/_buildManifest.js" defer=""></script><script src="/dashboard/_next/static/LRpGymRCqq-feuFyoWz4m/_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":"LRpGymRCqq-feuFyoWz4m","assetPrefix":"/dashboard","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
@@ -1 +1 @@
1
- self.__BUILD_MANIFEST=function(s,c,e,a,t,n,r,u,b,i,j,k,f){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-6b0d9e5031b70c58.js"],"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],"/clusters":["static/chunks/pages/clusters-82a651dbad53ec6e.js"],"/clusters/[cluster]":[s,c,e,a,t,r,b,n,i,u,j,k,f,"static/chunks/37-824c707421f6f003.js","static/chunks/pages/clusters/[cluster]-59950b2f83b66e48.js"],"/clusters/[cluster]/[job]":[s,c,e,a,t,n,"static/chunks/pages/clusters/[cluster]/[job]-89216c616dbaa9c5.js"],"/config":["static/chunks/pages/config-497a35a7ed49734a.js"],"/infra":["static/chunks/pages/infra-780860bcc1103945.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-d2910be98e9227cb.js"],"/jobs":["static/chunks/pages/jobs-336ab80e270ce2ce.js"],"/jobs/[job]":[s,c,e,a,t,r,n,u,"static/chunks/pages/jobs/[job]-b3dbf38b51cb29be.js"],"/users":["static/chunks/pages/users-c69ffcab9d6e5269.js"],"/workspace/new":["static/chunks/pages/workspace/new-31aa8bdcb7592635.js"],"/workspaces":["static/chunks/pages/workspaces-82e6601baa5dd280.js"],"/workspaces/[name]":[s,c,e,a,t,r,b,n,i,u,j,k,f,"static/chunks/843-ab9c4f609239155f.js","static/chunks/pages/workspaces/[name]-c8c2191328532b7d.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/[job]","/users","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-d6128fa9e7cae6e6.js","static/chunks/760-a89d354797ce7af5.js","static/chunks/799-3625946b2ec2eb30.js","static/chunks/804-4c9fc53aa74bc191.js","static/chunks/664-047bc03493fda379.js","static/chunks/470-4d1a5dbe58a8a2b9.js","static/chunks/798-c0525dc3f21e488d.js","static/chunks/969-20d54a9d998dc102.js","static/chunks/947-6620842ef80ae879.js","static/chunks/901-b424d293275e1fd7.js","static/chunks/856-c2c39c0912285e54.js","static/chunks/973-c807fc34f09c7df3.js","static/chunks/938-385d190b95815e11.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
1
+ self.__BUILD_MANIFEST=function(s,c,e,a,t,n,r,u,i,b,j,k,f){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":["static/chunks/pages/index-6b0d9e5031b70c58.js"],"/_error":["static/chunks/pages/_error-1be831200e60c5c0.js"],"/clusters":["static/chunks/pages/clusters-82a651dbad53ec6e.js"],"/clusters/[cluster]":[s,c,e,a,t,r,i,n,b,u,j,k,f,"static/chunks/37-3a4d77ad62932eaf.js","static/chunks/pages/clusters/[cluster]-36bc0962129f72df.js"],"/clusters/[cluster]/[job]":[s,c,e,a,t,n,"static/chunks/pages/clusters/[cluster]/[job]-89216c616dbaa9c5.js"],"/config":["static/chunks/pages/config-497a35a7ed49734a.js"],"/infra":["static/chunks/pages/infra-780860bcc1103945.js"],"/infra/[context]":["static/chunks/pages/infra/[context]-d2910be98e9227cb.js"],"/jobs":["static/chunks/pages/jobs-336ab80e270ce2ce.js"],"/jobs/[job]":[s,c,e,a,t,r,n,u,"static/chunks/pages/jobs/[job]-cf490d1fa38f3740.js"],"/users":["static/chunks/pages/users-928edf039219e47b.js"],"/workspace/new":["static/chunks/pages/workspace/new-31aa8bdcb7592635.js"],"/workspaces":["static/chunks/pages/workspaces-82e6601baa5dd280.js"],"/workspaces/[name]":[s,c,e,a,t,r,i,n,b,u,j,k,f,"static/chunks/843-b3040e493f6e7947.js","static/chunks/pages/workspaces/[name]-c4ff1ec05e2f3daf.js"],sortedPages:["/","/_app","/_error","/clusters","/clusters/[cluster]","/clusters/[cluster]/[job]","/config","/infra","/infra/[context]","/jobs","/jobs/[job]","/users","/workspace/new","/workspaces","/workspaces/[name]"]}}("static/chunks/616-d6128fa9e7cae6e6.js","static/chunks/760-a89d354797ce7af5.js","static/chunks/799-3625946b2ec2eb30.js","static/chunks/804-4c9fc53aa74bc191.js","static/chunks/664-047bc03493fda379.js","static/chunks/470-4d1a5dbe58a8a2b9.js","static/chunks/798-c0525dc3f21e488d.js","static/chunks/969-20d54a9d998dc102.js","static/chunks/947-6620842ef80ae879.js","static/chunks/901-b424d293275e1fd7.js","static/chunks/856-c2c39c0912285e54.js","static/chunks/973-db3c97c2bfbceb65.js","static/chunks/938-1493ac755eadeb35.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();