mirror of
https://github.com/wassname/ray.git
synced 2026-08-09 12:20:09 +08:00
Introduce file_mounts_sync_continuously cluster option (#9544)
* Separate out file_mounts contents hashing into its own separate hash Add an option to continuously sync file_mounts from head node to worker nodes: monitor.py will re-sync file mounts whenver contents change but will only run setup_commands if the config also changes * add test and default value for file_mounts_sync_continuously * format code * Update comments * Add param to skip setup commands when only file_mounts content changed during monitor.py's update tick Fixed so setup commands run when ray up is run and file_mounts content changes * Refactor so that runtime_hash retains previous behavior runtime_hash is almost identical as before this PR. It is used to determine if setup_commands need to run file_mounts_contents_hash is an additional hash of the file_mounts content that is used to detect when only file syncing has to occur. Note: runtime_hash value will have changed from before the PR because we hash the hash of the contents of the file_mounts as a performance optimization * fix issue with hashing a hash * fix bug where trying to set contents hash when it wasn't generated * Fix lint error Fix bug in command_runner where check_output was no longer returning the output of the command * clear out provider between tests to get rid of flakyness * reduce chance of race condition from node_launcher launching a node in the middle of an autoscaler.update call
This commit is contained in:
@@ -47,6 +47,10 @@ class MockProcessRunner:
|
||||
raise Exception("Failing command on purpose")
|
||||
self.calls.append(cmd)
|
||||
|
||||
def check_output(self, cmd):
|
||||
self.check_call(cmd)
|
||||
return "command-output".encode()
|
||||
|
||||
def assert_has_call(self, ip, pattern):
|
||||
out = ""
|
||||
for cmd in self.calls:
|
||||
@@ -285,6 +289,7 @@ class AutoscalingTest(unittest.TestCase):
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
self.provider = None
|
||||
del NODE_PROVIDERS["mock"]
|
||||
shutil.rmtree(self.tmpdir)
|
||||
ray.shutdown()
|
||||
@@ -1083,6 +1088,137 @@ class AutoscalingTest(unittest.TestCase):
|
||||
runner.assert_has_call("172.0.0.{}".format(i), "setup_cmd")
|
||||
runner.assert_has_call("172.0.0.{}".format(i), "start_ray_worker")
|
||||
|
||||
def testContinuousFileMounts(self):
|
||||
file_mount_dir = tempfile.mkdtemp()
|
||||
|
||||
self.provider = MockProvider()
|
||||
config = SMALL_CLUSTER.copy()
|
||||
config["file_mounts"] = {"/home/test-folder": file_mount_dir}
|
||||
config["file_mounts_sync_continuously"] = True
|
||||
config["min_workers"] = 2
|
||||
config["max_workers"] = 2
|
||||
config_path = self.write_config(config)
|
||||
runner = MockProcessRunner()
|
||||
lm = LoadMetrics()
|
||||
autoscaler = StandardAutoscaler(
|
||||
config_path,
|
||||
lm,
|
||||
max_failures=0,
|
||||
process_runner=runner,
|
||||
update_interval_s=0)
|
||||
|
||||
autoscaler.update()
|
||||
self.waitForNodes(2)
|
||||
self.provider.finish_starting_nodes()
|
||||
autoscaler.update()
|
||||
self.waitForNodes(
|
||||
2, tag_filters={TAG_RAY_NODE_STATUS: STATUS_UP_TO_DATE})
|
||||
autoscaler.update()
|
||||
|
||||
for i in [0, 1]:
|
||||
runner.assert_has_call("172.0.0.{}".format(i), "setup_cmd")
|
||||
runner.assert_has_call(
|
||||
"172.0.0.{}".format(i),
|
||||
"{}/ ubuntu@172.0.0.{}:/home/test-folder/".format(
|
||||
file_mount_dir, i))
|
||||
|
||||
runner.clear_history()
|
||||
|
||||
with open(os.path.join(file_mount_dir, "test.txt"), "wb") as temp_file:
|
||||
temp_file.write("hello".encode())
|
||||
|
||||
autoscaler.update()
|
||||
self.waitForNodes(2)
|
||||
self.provider.finish_starting_nodes()
|
||||
autoscaler.update()
|
||||
self.waitForNodes(
|
||||
2, tag_filters={TAG_RAY_NODE_STATUS: STATUS_UP_TO_DATE})
|
||||
autoscaler.update()
|
||||
|
||||
for i in [0, 1]:
|
||||
runner.assert_not_has_call("172.0.0.{}".format(i), "setup_cmd")
|
||||
runner.assert_has_call(
|
||||
"172.0.0.{}".format(i),
|
||||
"{}/ ubuntu@172.0.0.{}:/home/test-folder/".format(
|
||||
file_mount_dir, i))
|
||||
|
||||
def testFileMountsNonContinuous(self):
|
||||
file_mount_dir = tempfile.mkdtemp()
|
||||
|
||||
self.provider = MockProvider()
|
||||
config = SMALL_CLUSTER.copy()
|
||||
config["file_mounts"] = {"/home/test-folder": file_mount_dir}
|
||||
config["min_workers"] = 2
|
||||
config["max_workers"] = 2
|
||||
config_path = self.write_config(config)
|
||||
runner = MockProcessRunner()
|
||||
lm = LoadMetrics()
|
||||
autoscaler = StandardAutoscaler(
|
||||
config_path,
|
||||
lm,
|
||||
max_failures=0,
|
||||
process_runner=runner,
|
||||
update_interval_s=0)
|
||||
|
||||
autoscaler.update()
|
||||
self.waitForNodes(2)
|
||||
self.provider.finish_starting_nodes()
|
||||
autoscaler.update()
|
||||
self.waitForNodes(
|
||||
2, tag_filters={TAG_RAY_NODE_STATUS: STATUS_UP_TO_DATE})
|
||||
autoscaler.update()
|
||||
|
||||
for i in [0, 1]:
|
||||
runner.assert_has_call("172.0.0.{}".format(i), "setup_cmd")
|
||||
runner.assert_has_call(
|
||||
"172.0.0.{}".format(i),
|
||||
"{}/ ubuntu@172.0.0.{}:/home/test-folder/".format(
|
||||
file_mount_dir, i))
|
||||
|
||||
runner.clear_history()
|
||||
|
||||
with open(os.path.join(file_mount_dir, "test.txt"), "wb") as temp_file:
|
||||
temp_file.write("hello".encode())
|
||||
|
||||
autoscaler.update()
|
||||
self.waitForNodes(2)
|
||||
self.provider.finish_starting_nodes()
|
||||
self.waitForNodes(
|
||||
2, tag_filters={TAG_RAY_NODE_STATUS: STATUS_UP_TO_DATE})
|
||||
|
||||
for i in [0, 1]:
|
||||
runner.assert_not_has_call("172.0.0.{}".format(i), "setup_cmd")
|
||||
runner.assert_not_has_call(
|
||||
"172.0.0.{}".format(i),
|
||||
"{}/ ubuntu@172.0.0.{}:/home/test-folder/".format(
|
||||
file_mount_dir, i))
|
||||
|
||||
# Simulate a second `ray up` call
|
||||
from ray.autoscaler import util
|
||||
util._hash_cache = {}
|
||||
runner = MockProcessRunner()
|
||||
lm = LoadMetrics()
|
||||
autoscaler = StandardAutoscaler(
|
||||
config_path,
|
||||
lm,
|
||||
max_failures=0,
|
||||
process_runner=runner,
|
||||
update_interval_s=0)
|
||||
|
||||
autoscaler.update()
|
||||
self.waitForNodes(2)
|
||||
self.provider.finish_starting_nodes()
|
||||
self.waitForNodes(
|
||||
2, tag_filters={TAG_RAY_NODE_STATUS: STATUS_UP_TO_DATE})
|
||||
autoscaler.update()
|
||||
|
||||
for i in [0, 1]:
|
||||
runner.assert_has_call("172.0.0.{}".format(i), "setup_cmd")
|
||||
runner.assert_has_call(
|
||||
"172.0.0.{}".format(i),
|
||||
"{}/ ubuntu@172.0.0.{}:/home/test-folder/".format(
|
||||
file_mount_dir, i))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
Reference in New Issue
Block a user