skypilot-nightly 1.0.0.dev2024053101__py3-none-any.whl → 1.0.0.dev2025022801__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 (299) hide show
  1. sky/__init__.py +64 -32
  2. sky/adaptors/aws.py +23 -6
  3. sky/adaptors/azure.py +432 -15
  4. sky/adaptors/cloudflare.py +5 -5
  5. sky/adaptors/common.py +19 -9
  6. sky/adaptors/do.py +20 -0
  7. sky/adaptors/gcp.py +3 -2
  8. sky/adaptors/kubernetes.py +122 -88
  9. sky/adaptors/nebius.py +100 -0
  10. sky/adaptors/oci.py +39 -1
  11. sky/adaptors/vast.py +29 -0
  12. sky/admin_policy.py +101 -0
  13. sky/authentication.py +117 -98
  14. sky/backends/backend.py +52 -20
  15. sky/backends/backend_utils.py +669 -557
  16. sky/backends/cloud_vm_ray_backend.py +1099 -808
  17. sky/backends/local_docker_backend.py +14 -8
  18. sky/backends/wheel_utils.py +38 -20
  19. sky/benchmark/benchmark_utils.py +22 -23
  20. sky/check.py +76 -27
  21. sky/cli.py +1586 -1139
  22. sky/client/__init__.py +1 -0
  23. sky/client/cli.py +5683 -0
  24. sky/client/common.py +345 -0
  25. sky/client/sdk.py +1765 -0
  26. sky/cloud_stores.py +283 -19
  27. sky/clouds/__init__.py +7 -2
  28. sky/clouds/aws.py +303 -112
  29. sky/clouds/azure.py +185 -179
  30. sky/clouds/cloud.py +115 -37
  31. sky/clouds/cudo.py +29 -22
  32. sky/clouds/do.py +313 -0
  33. sky/clouds/fluidstack.py +44 -54
  34. sky/clouds/gcp.py +206 -65
  35. sky/clouds/ibm.py +26 -21
  36. sky/clouds/kubernetes.py +345 -91
  37. sky/clouds/lambda_cloud.py +40 -29
  38. sky/clouds/nebius.py +297 -0
  39. sky/clouds/oci.py +129 -90
  40. sky/clouds/paperspace.py +22 -18
  41. sky/clouds/runpod.py +53 -34
  42. sky/clouds/scp.py +28 -24
  43. sky/clouds/service_catalog/__init__.py +19 -13
  44. sky/clouds/service_catalog/aws_catalog.py +29 -12
  45. sky/clouds/service_catalog/azure_catalog.py +33 -6
  46. sky/clouds/service_catalog/common.py +95 -75
  47. sky/clouds/service_catalog/constants.py +3 -3
  48. sky/clouds/service_catalog/cudo_catalog.py +13 -3
  49. sky/clouds/service_catalog/data_fetchers/fetch_aws.py +36 -21
  50. sky/clouds/service_catalog/data_fetchers/fetch_azure.py +31 -4
  51. sky/clouds/service_catalog/data_fetchers/fetch_cudo.py +8 -117
  52. sky/clouds/service_catalog/data_fetchers/fetch_fluidstack.py +197 -44
  53. sky/clouds/service_catalog/data_fetchers/fetch_gcp.py +224 -36
  54. sky/clouds/service_catalog/data_fetchers/fetch_lambda_cloud.py +44 -24
  55. sky/clouds/service_catalog/data_fetchers/fetch_vast.py +147 -0
  56. sky/clouds/service_catalog/data_fetchers/fetch_vsphere.py +1 -1
  57. sky/clouds/service_catalog/do_catalog.py +111 -0
  58. sky/clouds/service_catalog/fluidstack_catalog.py +2 -2
  59. sky/clouds/service_catalog/gcp_catalog.py +16 -2
  60. sky/clouds/service_catalog/ibm_catalog.py +2 -2
  61. sky/clouds/service_catalog/kubernetes_catalog.py +192 -70
  62. sky/clouds/service_catalog/lambda_catalog.py +8 -3
  63. sky/clouds/service_catalog/nebius_catalog.py +116 -0
  64. sky/clouds/service_catalog/oci_catalog.py +31 -4
  65. sky/clouds/service_catalog/paperspace_catalog.py +2 -2
  66. sky/clouds/service_catalog/runpod_catalog.py +2 -2
  67. sky/clouds/service_catalog/scp_catalog.py +2 -2
  68. sky/clouds/service_catalog/vast_catalog.py +104 -0
  69. sky/clouds/service_catalog/vsphere_catalog.py +2 -2
  70. sky/clouds/utils/aws_utils.py +65 -0
  71. sky/clouds/utils/azure_utils.py +91 -0
  72. sky/clouds/utils/gcp_utils.py +5 -9
  73. sky/clouds/utils/oci_utils.py +47 -5
  74. sky/clouds/utils/scp_utils.py +4 -3
  75. sky/clouds/vast.py +280 -0
  76. sky/clouds/vsphere.py +22 -18
  77. sky/core.py +361 -107
  78. sky/dag.py +41 -28
  79. sky/data/data_transfer.py +37 -0
  80. sky/data/data_utils.py +211 -32
  81. sky/data/mounting_utils.py +182 -30
  82. sky/data/storage.py +2118 -270
  83. sky/data/storage_utils.py +126 -5
  84. sky/exceptions.py +179 -8
  85. sky/execution.py +158 -85
  86. sky/global_user_state.py +150 -34
  87. sky/jobs/__init__.py +12 -10
  88. sky/jobs/client/__init__.py +0 -0
  89. sky/jobs/client/sdk.py +302 -0
  90. sky/jobs/constants.py +49 -11
  91. sky/jobs/controller.py +161 -99
  92. sky/jobs/dashboard/dashboard.py +171 -25
  93. sky/jobs/dashboard/templates/index.html +572 -60
  94. sky/jobs/recovery_strategy.py +157 -156
  95. sky/jobs/scheduler.py +307 -0
  96. sky/jobs/server/__init__.py +1 -0
  97. sky/jobs/server/core.py +598 -0
  98. sky/jobs/server/dashboard_utils.py +69 -0
  99. sky/jobs/server/server.py +190 -0
  100. sky/jobs/state.py +627 -122
  101. sky/jobs/utils.py +615 -206
  102. sky/models.py +27 -0
  103. sky/optimizer.py +142 -83
  104. sky/provision/__init__.py +20 -5
  105. sky/provision/aws/config.py +124 -42
  106. sky/provision/aws/instance.py +130 -53
  107. sky/provision/azure/__init__.py +7 -0
  108. sky/{skylet/providers → provision}/azure/azure-config-template.json +19 -7
  109. sky/provision/azure/config.py +220 -0
  110. sky/provision/azure/instance.py +1012 -37
  111. sky/provision/common.py +31 -3
  112. sky/provision/constants.py +25 -0
  113. sky/provision/cudo/__init__.py +2 -1
  114. sky/provision/cudo/cudo_utils.py +112 -0
  115. sky/provision/cudo/cudo_wrapper.py +37 -16
  116. sky/provision/cudo/instance.py +28 -12
  117. sky/provision/do/__init__.py +11 -0
  118. sky/provision/do/config.py +14 -0
  119. sky/provision/do/constants.py +10 -0
  120. sky/provision/do/instance.py +287 -0
  121. sky/provision/do/utils.py +301 -0
  122. sky/provision/docker_utils.py +82 -46
  123. sky/provision/fluidstack/fluidstack_utils.py +57 -125
  124. sky/provision/fluidstack/instance.py +15 -43
  125. sky/provision/gcp/config.py +19 -9
  126. sky/provision/gcp/constants.py +7 -1
  127. sky/provision/gcp/instance.py +55 -34
  128. sky/provision/gcp/instance_utils.py +339 -80
  129. sky/provision/gcp/mig_utils.py +210 -0
  130. sky/provision/instance_setup.py +172 -133
  131. sky/provision/kubernetes/__init__.py +1 -0
  132. sky/provision/kubernetes/config.py +104 -90
  133. sky/provision/kubernetes/constants.py +8 -0
  134. sky/provision/kubernetes/instance.py +680 -325
  135. sky/provision/kubernetes/manifests/smarter-device-manager-daemonset.yaml +3 -0
  136. sky/provision/kubernetes/network.py +54 -20
  137. sky/provision/kubernetes/network_utils.py +70 -21
  138. sky/provision/kubernetes/utils.py +1370 -251
  139. sky/provision/lambda_cloud/__init__.py +11 -0
  140. sky/provision/lambda_cloud/config.py +10 -0
  141. sky/provision/lambda_cloud/instance.py +265 -0
  142. sky/{clouds/utils → provision/lambda_cloud}/lambda_utils.py +24 -23
  143. sky/provision/logging.py +1 -1
  144. sky/provision/nebius/__init__.py +11 -0
  145. sky/provision/nebius/config.py +11 -0
  146. sky/provision/nebius/instance.py +285 -0
  147. sky/provision/nebius/utils.py +318 -0
  148. sky/provision/oci/__init__.py +15 -0
  149. sky/provision/oci/config.py +51 -0
  150. sky/provision/oci/instance.py +436 -0
  151. sky/provision/oci/query_utils.py +681 -0
  152. sky/provision/paperspace/constants.py +6 -0
  153. sky/provision/paperspace/instance.py +4 -3
  154. sky/provision/paperspace/utils.py +2 -0
  155. sky/provision/provisioner.py +207 -130
  156. sky/provision/runpod/__init__.py +1 -0
  157. sky/provision/runpod/api/__init__.py +3 -0
  158. sky/provision/runpod/api/commands.py +119 -0
  159. sky/provision/runpod/api/pods.py +142 -0
  160. sky/provision/runpod/instance.py +64 -8
  161. sky/provision/runpod/utils.py +239 -23
  162. sky/provision/vast/__init__.py +10 -0
  163. sky/provision/vast/config.py +11 -0
  164. sky/provision/vast/instance.py +247 -0
  165. sky/provision/vast/utils.py +162 -0
  166. sky/provision/vsphere/common/vim_utils.py +1 -1
  167. sky/provision/vsphere/instance.py +8 -18
  168. sky/provision/vsphere/vsphere_utils.py +1 -1
  169. sky/resources.py +247 -102
  170. sky/serve/__init__.py +9 -9
  171. sky/serve/autoscalers.py +361 -299
  172. sky/serve/client/__init__.py +0 -0
  173. sky/serve/client/sdk.py +366 -0
  174. sky/serve/constants.py +12 -3
  175. sky/serve/controller.py +106 -36
  176. sky/serve/load_balancer.py +63 -12
  177. sky/serve/load_balancing_policies.py +84 -2
  178. sky/serve/replica_managers.py +42 -34
  179. sky/serve/serve_state.py +62 -32
  180. sky/serve/serve_utils.py +271 -160
  181. sky/serve/server/__init__.py +0 -0
  182. sky/serve/{core.py → server/core.py} +271 -90
  183. sky/serve/server/server.py +112 -0
  184. sky/serve/service.py +52 -16
  185. sky/serve/service_spec.py +95 -32
  186. sky/server/__init__.py +1 -0
  187. sky/server/common.py +430 -0
  188. sky/server/constants.py +21 -0
  189. sky/server/html/log.html +174 -0
  190. sky/server/requests/__init__.py +0 -0
  191. sky/server/requests/executor.py +472 -0
  192. sky/server/requests/payloads.py +487 -0
  193. sky/server/requests/queues/__init__.py +0 -0
  194. sky/server/requests/queues/mp_queue.py +76 -0
  195. sky/server/requests/requests.py +567 -0
  196. sky/server/requests/serializers/__init__.py +0 -0
  197. sky/server/requests/serializers/decoders.py +192 -0
  198. sky/server/requests/serializers/encoders.py +166 -0
  199. sky/server/server.py +1106 -0
  200. sky/server/stream_utils.py +141 -0
  201. sky/setup_files/MANIFEST.in +2 -5
  202. sky/setup_files/dependencies.py +159 -0
  203. sky/setup_files/setup.py +14 -125
  204. sky/sky_logging.py +59 -14
  205. sky/skylet/autostop_lib.py +2 -2
  206. sky/skylet/constants.py +183 -50
  207. sky/skylet/events.py +22 -10
  208. sky/skylet/job_lib.py +403 -258
  209. sky/skylet/log_lib.py +111 -71
  210. sky/skylet/log_lib.pyi +6 -0
  211. sky/skylet/providers/command_runner.py +6 -8
  212. sky/skylet/providers/ibm/node_provider.py +2 -2
  213. sky/skylet/providers/scp/config.py +11 -3
  214. sky/skylet/providers/scp/node_provider.py +8 -8
  215. sky/skylet/skylet.py +3 -1
  216. sky/skylet/subprocess_daemon.py +69 -17
  217. sky/skypilot_config.py +119 -57
  218. sky/task.py +205 -64
  219. sky/templates/aws-ray.yml.j2 +37 -7
  220. sky/templates/azure-ray.yml.j2 +27 -82
  221. sky/templates/cudo-ray.yml.j2 +7 -3
  222. sky/templates/do-ray.yml.j2 +98 -0
  223. sky/templates/fluidstack-ray.yml.j2 +7 -4
  224. sky/templates/gcp-ray.yml.j2 +26 -6
  225. sky/templates/ibm-ray.yml.j2 +3 -2
  226. sky/templates/jobs-controller.yaml.j2 +46 -11
  227. sky/templates/kubernetes-ingress.yml.j2 +7 -0
  228. sky/templates/kubernetes-loadbalancer.yml.j2 +7 -0
  229. sky/templates/{kubernetes-port-forward-proxy-command.sh.j2 → kubernetes-port-forward-proxy-command.sh} +51 -7
  230. sky/templates/kubernetes-ray.yml.j2 +292 -25
  231. sky/templates/lambda-ray.yml.j2 +30 -40
  232. sky/templates/nebius-ray.yml.j2 +79 -0
  233. sky/templates/oci-ray.yml.j2 +18 -57
  234. sky/templates/paperspace-ray.yml.j2 +10 -6
  235. sky/templates/runpod-ray.yml.j2 +26 -4
  236. sky/templates/scp-ray.yml.j2 +3 -2
  237. sky/templates/sky-serve-controller.yaml.j2 +12 -1
  238. sky/templates/skypilot-server-kubernetes-proxy.sh +36 -0
  239. sky/templates/vast-ray.yml.j2 +70 -0
  240. sky/templates/vsphere-ray.yml.j2 +8 -3
  241. sky/templates/websocket_proxy.py +64 -0
  242. sky/usage/constants.py +10 -1
  243. sky/usage/usage_lib.py +130 -37
  244. sky/utils/accelerator_registry.py +35 -51
  245. sky/utils/admin_policy_utils.py +147 -0
  246. sky/utils/annotations.py +51 -0
  247. sky/utils/cli_utils/status_utils.py +81 -23
  248. sky/utils/cluster_utils.py +356 -0
  249. sky/utils/command_runner.py +452 -89
  250. sky/utils/command_runner.pyi +77 -3
  251. sky/utils/common.py +54 -0
  252. sky/utils/common_utils.py +319 -108
  253. sky/utils/config_utils.py +204 -0
  254. sky/utils/control_master_utils.py +48 -0
  255. sky/utils/controller_utils.py +548 -266
  256. sky/utils/dag_utils.py +93 -32
  257. sky/utils/db_utils.py +18 -4
  258. sky/utils/env_options.py +29 -7
  259. sky/utils/kubernetes/create_cluster.sh +8 -60
  260. sky/utils/kubernetes/deploy_remote_cluster.sh +243 -0
  261. sky/utils/kubernetes/exec_kubeconfig_converter.py +73 -0
  262. sky/utils/kubernetes/generate_kubeconfig.sh +336 -0
  263. sky/utils/kubernetes/gpu_labeler.py +4 -4
  264. sky/utils/kubernetes/k8s_gpu_labeler_job.yaml +4 -3
  265. sky/utils/kubernetes/kubernetes_deploy_utils.py +228 -0
  266. sky/utils/kubernetes/rsync_helper.sh +24 -0
  267. sky/utils/kubernetes/ssh_jump_lifecycle_manager.py +1 -1
  268. sky/utils/log_utils.py +240 -33
  269. sky/utils/message_utils.py +81 -0
  270. sky/utils/registry.py +127 -0
  271. sky/utils/resources_utils.py +94 -22
  272. sky/utils/rich_utils.py +247 -18
  273. sky/utils/schemas.py +284 -64
  274. sky/{status_lib.py → utils/status_lib.py} +12 -7
  275. sky/utils/subprocess_utils.py +212 -46
  276. sky/utils/timeline.py +12 -7
  277. sky/utils/ux_utils.py +168 -15
  278. skypilot_nightly-1.0.0.dev2025022801.dist-info/METADATA +363 -0
  279. skypilot_nightly-1.0.0.dev2025022801.dist-info/RECORD +352 -0
  280. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/WHEEL +1 -1
  281. sky/clouds/cloud_registry.py +0 -31
  282. sky/jobs/core.py +0 -330
  283. sky/skylet/providers/azure/__init__.py +0 -2
  284. sky/skylet/providers/azure/azure-vm-template.json +0 -301
  285. sky/skylet/providers/azure/config.py +0 -170
  286. sky/skylet/providers/azure/node_provider.py +0 -466
  287. sky/skylet/providers/lambda_cloud/__init__.py +0 -2
  288. sky/skylet/providers/lambda_cloud/node_provider.py +0 -320
  289. sky/skylet/providers/oci/__init__.py +0 -2
  290. sky/skylet/providers/oci/node_provider.py +0 -488
  291. sky/skylet/providers/oci/query_helper.py +0 -383
  292. sky/skylet/providers/oci/utils.py +0 -21
  293. sky/utils/cluster_yaml_utils.py +0 -24
  294. sky/utils/kubernetes/generate_static_kubeconfig.sh +0 -137
  295. skypilot_nightly-1.0.0.dev2024053101.dist-info/METADATA +0 -315
  296. skypilot_nightly-1.0.0.dev2024053101.dist-info/RECORD +0 -275
  297. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/LICENSE +0 -0
  298. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/entry_points.txt +0 -0
  299. {skypilot_nightly-1.0.0.dev2024053101.dist-info → skypilot_nightly-1.0.0.dev2025022801.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  """Helper functions for object store mounting in Sky Storage"""
2
2
  import random
3
+ import shlex
3
4
  import textwrap
4
5
  from typing import Optional
5
6
 
@@ -13,6 +14,12 @@ _TYPE_CACHE_TTL = '5s'
13
14
  _RENAME_DIR_LIMIT = 10000
14
15
  # https://github.com/GoogleCloudPlatform/gcsfuse/releases
15
16
  GCSFUSE_VERSION = '2.2.0'
17
+ # https://github.com/Azure/azure-storage-fuse/releases
18
+ BLOBFUSE2_VERSION = '2.2.0'
19
+ _BLOBFUSE_CACHE_ROOT_DIR = '~/.sky/blobfuse2_cache'
20
+ _BLOBFUSE_CACHE_DIR = ('~/.sky/blobfuse2_cache/'
21
+ '{storage_account_name}_{container_name}')
22
+ RCLONE_VERSION = 'v1.68.2'
16
23
 
17
24
 
18
25
  def get_s3_mount_install_cmd() -> str:
@@ -24,12 +31,19 @@ def get_s3_mount_install_cmd() -> str:
24
31
  return install_cmd
25
32
 
26
33
 
27
- def get_s3_mount_cmd(bucket_name: str, mount_path: str) -> str:
34
+ # pylint: disable=invalid-name
35
+ def get_s3_mount_cmd(bucket_name: str,
36
+ mount_path: str,
37
+ _bucket_sub_path: Optional[str] = None) -> str:
28
38
  """Returns a command to mount an S3 bucket using goofys."""
39
+ if _bucket_sub_path is None:
40
+ _bucket_sub_path = ''
41
+ else:
42
+ _bucket_sub_path = f':{_bucket_sub_path}'
29
43
  mount_cmd = ('goofys -o allow_other '
30
44
  f'--stat-cache-ttl {_STAT_CACHE_TTL} '
31
45
  f'--type-cache-ttl {_TYPE_CACHE_TTL} '
32
- f'{bucket_name} {mount_path}')
46
+ f'{bucket_name}{_bucket_sub_path} {mount_path}')
33
47
  return mount_cmd
34
48
 
35
49
 
@@ -43,28 +57,110 @@ def get_gcs_mount_install_cmd() -> str:
43
57
  return install_cmd
44
58
 
45
59
 
46
- def get_gcs_mount_cmd(bucket_name: str, mount_path: str) -> str:
60
+ # pylint: disable=invalid-name
61
+ def get_gcs_mount_cmd(bucket_name: str,
62
+ mount_path: str,
63
+ _bucket_sub_path: Optional[str] = None) -> str:
47
64
  """Returns a command to mount a GCS bucket using gcsfuse."""
65
+ bucket_sub_path_arg = f'--only-dir {_bucket_sub_path} '\
66
+ if _bucket_sub_path else ''
48
67
  mount_cmd = ('gcsfuse -o allow_other '
49
68
  '--implicit-dirs '
50
69
  f'--stat-cache-capacity {_STAT_CACHE_CAPACITY} '
51
70
  f'--stat-cache-ttl {_STAT_CACHE_TTL} '
52
71
  f'--type-cache-ttl {_TYPE_CACHE_TTL} '
53
72
  f'--rename-dir-limit {_RENAME_DIR_LIMIT} '
73
+ f'{bucket_sub_path_arg}'
54
74
  f'{bucket_name} {mount_path}')
55
75
  return mount_cmd
56
76
 
57
77
 
58
- def get_r2_mount_cmd(r2_credentials_path: str, r2_profile_name: str,
59
- endpoint_url: str, bucket_name: str,
60
- mount_path: str) -> str:
78
+ def get_az_mount_install_cmd() -> str:
79
+ """Returns a command to install AZ Container mount utility blobfuse2."""
80
+ install_cmd = ('sudo apt-get update; '
81
+ 'sudo apt-get install -y '
82
+ '-o Dpkg::Options::="--force-confdef" '
83
+ 'fuse3 libfuse3-dev && '
84
+ 'wget -nc https://github.com/Azure/azure-storage-fuse'
85
+ f'/releases/download/blobfuse2-{BLOBFUSE2_VERSION}'
86
+ f'/blobfuse2-{BLOBFUSE2_VERSION}-Debian-11.0.x86_64.deb '
87
+ '-O /tmp/blobfuse2.deb && '
88
+ 'sudo dpkg --install /tmp/blobfuse2.deb && '
89
+ f'mkdir -p {_BLOBFUSE_CACHE_ROOT_DIR};')
90
+
91
+ return install_cmd
92
+
93
+
94
+ # pylint: disable=invalid-name
95
+ def get_az_mount_cmd(container_name: str,
96
+ storage_account_name: str,
97
+ mount_path: str,
98
+ storage_account_key: Optional[str] = None,
99
+ _bucket_sub_path: Optional[str] = None) -> str:
100
+ """Returns a command to mount an AZ Container using blobfuse2.
101
+
102
+ Args:
103
+ container_name: Name of the mounting container.
104
+ storage_account_name: Name of the storage account the given container
105
+ belongs to.
106
+ mount_path: Path where the container will be mounting.
107
+ storage_account_key: Access key for the given storage account.
108
+ _bucket_sub_path: Sub path of the mounting container.
109
+
110
+ Returns:
111
+ str: Command used to mount AZ container with blobfuse2.
112
+ """
113
+ # Storage_account_key is set to None when mounting public container, and
114
+ # mounting public containers are not officially supported by blobfuse2 yet.
115
+ # Setting an empty SAS token value is a suggested workaround.
116
+ # https://github.com/Azure/azure-storage-fuse/issues/1338
117
+ if storage_account_key is None:
118
+ key_env_var = f'AZURE_STORAGE_SAS_TOKEN={shlex.quote(" ")}'
119
+ else:
120
+ key_env_var = ('AZURE_STORAGE_ACCESS_KEY='
121
+ f'{shlex.quote(storage_account_key)}')
122
+
123
+ cache_path = _BLOBFUSE_CACHE_DIR.format(
124
+ storage_account_name=storage_account_name,
125
+ container_name=container_name)
126
+ # The line below ensures the cache directory is new before mounting to
127
+ # avoid "config error in file_cache [temp directory not empty]" error, which
128
+ # can occur after stopping and starting the same cluster on Azure.
129
+ # This helps ensure a clean state for blobfuse2 operations.
130
+ remote_boot_time_cmd = 'date +%s -d "$(uptime -s)"'
131
+ if _bucket_sub_path is None:
132
+ bucket_sub_path_arg = ''
133
+ else:
134
+ bucket_sub_path_arg = f'--subdirectory={_bucket_sub_path}/ '
135
+ # TODO(zpoint): clear old cache that has been created in the previous boot.
136
+ mount_cmd = (f'AZURE_STORAGE_ACCOUNT={storage_account_name} '
137
+ f'{key_env_var} '
138
+ f'blobfuse2 {mount_path} --allow-other --no-symlinks '
139
+ '-o umask=022 -o default_permissions '
140
+ f'--tmp-path {cache_path}_$({remote_boot_time_cmd}) '
141
+ f'{bucket_sub_path_arg}'
142
+ f'--container-name {container_name}')
143
+ return mount_cmd
144
+
145
+
146
+ # pylint: disable=invalid-name
147
+ def get_r2_mount_cmd(r2_credentials_path: str,
148
+ r2_profile_name: str,
149
+ endpoint_url: str,
150
+ bucket_name: str,
151
+ mount_path: str,
152
+ _bucket_sub_path: Optional[str] = None) -> str:
61
153
  """Returns a command to install R2 mount utility goofys."""
154
+ if _bucket_sub_path is None:
155
+ _bucket_sub_path = ''
156
+ else:
157
+ _bucket_sub_path = f':{_bucket_sub_path}'
62
158
  mount_cmd = (f'AWS_SHARED_CREDENTIALS_FILE={r2_credentials_path} '
63
159
  f'AWS_PROFILE={r2_profile_name} goofys -o allow_other '
64
160
  f'--stat-cache-ttl {_STAT_CACHE_TTL} '
65
161
  f'--type-cache-ttl {_TYPE_CACHE_TTL} '
66
162
  f'--endpoint {endpoint_url} '
67
- f'{bucket_name} {mount_path}')
163
+ f'{bucket_name}{_bucket_sub_path} {mount_path}')
68
164
  return mount_cmd
69
165
 
70
166
 
@@ -76,9 +172,12 @@ def get_cos_mount_install_cmd() -> str:
76
172
  return install_cmd
77
173
 
78
174
 
79
- def get_cos_mount_cmd(rclone_config_data: str, rclone_config_path: str,
80
- bucket_rclone_profile: str, bucket_name: str,
81
- mount_path: str) -> str:
175
+ def get_cos_mount_cmd(rclone_config_data: str,
176
+ rclone_config_path: str,
177
+ bucket_rclone_profile: str,
178
+ bucket_name: str,
179
+ mount_path: str,
180
+ _bucket_sub_path: Optional[str] = None) -> str:
82
181
  """Returns a command to mount an IBM COS bucket using rclone."""
83
182
  # creates a fusermount soft link on older (<22) Ubuntu systems for
84
183
  # rclone's mount utility.
@@ -90,14 +189,80 @@ def get_cos_mount_cmd(rclone_config_data: str, rclone_config_path: str,
90
189
  'mkdir -p ~/.config/rclone/ && '
91
190
  f'echo "{rclone_config_data}" >> '
92
191
  f'{rclone_config_path}')
192
+ if _bucket_sub_path is None:
193
+ sub_path_arg = f'{bucket_name}/{_bucket_sub_path}'
194
+ else:
195
+ sub_path_arg = f'/{bucket_name}'
93
196
  # --daemon will keep the mounting process running in the background.
94
197
  mount_cmd = (f'{configure_rclone_profile} && '
95
198
  'rclone mount '
96
- f'{bucket_rclone_profile}:{bucket_name} {mount_path} '
199
+ f'{bucket_rclone_profile}:{sub_path_arg} {mount_path} '
97
200
  '--daemon')
98
201
  return mount_cmd
99
202
 
100
203
 
204
+ def get_rclone_install_cmd() -> str:
205
+ """ RClone installation for both apt-get and rpm.
206
+ This would be common command.
207
+ """
208
+ # pylint: disable=line-too-long
209
+ install_cmd = (
210
+ f'(which dpkg > /dev/null 2>&1 && (which rclone > /dev/null || (cd ~ > /dev/null'
211
+ f' && curl -O https://downloads.rclone.org/{RCLONE_VERSION}/rclone-{RCLONE_VERSION}-linux-amd64.deb'
212
+ f' && sudo dpkg -i rclone-{RCLONE_VERSION}-linux-amd64.deb'
213
+ f' && rm -f rclone-{RCLONE_VERSION}-linux-amd64.deb)))'
214
+ f' || (which rclone > /dev/null || (cd ~ > /dev/null'
215
+ f' && curl -O https://downloads.rclone.org/{RCLONE_VERSION}/rclone-{RCLONE_VERSION}-linux-amd64.rpm'
216
+ f' && sudo yum --nogpgcheck install rclone-{RCLONE_VERSION}-linux-amd64.rpm -y'
217
+ f' && rm -f rclone-{RCLONE_VERSION}-linux-amd64.rpm))')
218
+ return install_cmd
219
+
220
+
221
+ def get_oci_mount_cmd(mount_path: str, store_name: str, region: str,
222
+ namespace: str, compartment: str, config_file: str,
223
+ config_profile: str) -> str:
224
+ """ OCI specific RClone mount command for oci object storage. """
225
+ # pylint: disable=line-too-long
226
+ mount_cmd = (
227
+ f'sudo chown -R `whoami` {mount_path}'
228
+ f' && rclone config create oos_{store_name} oracleobjectstorage'
229
+ f' provider user_principal_auth namespace {namespace}'
230
+ f' compartment {compartment} region {region}'
231
+ f' oci-config-file {config_file}'
232
+ f' oci-config-profile {config_profile}'
233
+ f' && sed -i "s/oci-config-file/config_file/g;'
234
+ f' s/oci-config-profile/config_profile/g" ~/.config/rclone/rclone.conf'
235
+ f' && ([ ! -f /bin/fusermount3 ] && sudo ln -s /bin/fusermount /bin/fusermount3 || true)'
236
+ f' && (grep -q {mount_path} /proc/mounts || rclone mount oos_{store_name}:{store_name} {mount_path} --daemon --allow-non-empty)'
237
+ )
238
+ return mount_cmd
239
+
240
+
241
+ def get_rclone_version_check_cmd() -> str:
242
+ """ RClone version check. This would be common command. """
243
+ return f'rclone --version | grep -q {RCLONE_VERSION}'
244
+
245
+
246
+ def _get_mount_binary(mount_cmd: str) -> str:
247
+ """Returns mounting binary in string given as the mount command.
248
+
249
+ Args:
250
+ mount_cmd: Command used to mount a cloud storage.
251
+
252
+ Returns:
253
+ str: Name of the binary used to mount a cloud storage.
254
+ """
255
+ if 'goofys' in mount_cmd:
256
+ return 'goofys'
257
+ elif 'gcsfuse' in mount_cmd:
258
+ return 'gcsfuse'
259
+ elif 'blobfuse2' in mount_cmd:
260
+ return 'blobfuse2'
261
+ else:
262
+ assert 'rclone' in mount_cmd
263
+ return 'rclone'
264
+
265
+
101
266
  def get_mounting_script(
102
267
  mount_path: str,
103
268
  mount_cmd: str,
@@ -121,8 +286,7 @@ def get_mounting_script(
121
286
  Returns:
122
287
  str: Mounting script as a str.
123
288
  """
124
-
125
- mount_binary = mount_cmd.split()[0]
289
+ mount_binary = _get_mount_binary(mount_cmd)
126
290
  installed_check = f'[ -x "$(command -v {mount_binary})" ]'
127
291
  if version_check_cmd is not None:
128
292
  installed_check += f' && {version_check_cmd}'
@@ -130,7 +294,7 @@ def get_mounting_script(
130
294
  script = textwrap.dedent(f"""
131
295
  #!/usr/bin/env bash
132
296
  set -e
133
-
297
+
134
298
  {command_runner.ALIAS_SUDO_TO_EMPTY_FOR_ROOT_CMD}
135
299
 
136
300
  MOUNT_PATH={mount_path}
@@ -197,23 +361,11 @@ def get_mounting_command(
197
361
  script = get_mounting_script(mount_path, mount_cmd, install_cmd,
198
362
  version_check_cmd)
199
363
 
200
- # TODO(romilb): Get direct bash script to work like so:
201
- # command = f'bash <<-\EOL' \
202
- # f'{script}' \
203
- # 'EOL'
204
-
205
- # TODO(romilb): This heredoc should have EOF after script, but it
206
- # fails with sky's ssh pipeline. Instead, we don't use EOF and use )
207
- # as the end of heredoc. This raises a warning (here-document delimited
208
- # by end-of-file) that can be safely ignored.
209
-
210
364
  # While these commands are run sequentially for each storage object,
211
365
  # we add random int to be on the safer side and avoid collisions.
212
366
  script_path = f'~/.sky/mount_{random.randint(0, 1000000)}.sh'
213
- first_line = r'(cat <<-\EOF > {}'.format(script_path)
214
- command = (f'{first_line}'
215
- f'{script}'
216
- f') && chmod +x {script_path}'
217
- f' && bash {script_path}'
218
- f' && rm {script_path}')
367
+ command = (f'echo {shlex.quote(script)} > {script_path} && '
368
+ f'chmod +x {script_path} && '
369
+ f'bash {script_path} && '
370
+ f'rm {script_path}')
219
371
  return command