def test_is_available_by_id(self): # img = DockerImage(self.TEST_REPOSITORY, image_id=self.TEST_IMAGE_ID) # self.assertTrue(img.is_available) # self._is_test_image(img) nimg = DockerImage(self.TEST_REPOSITORY, image_id="deadface") self.assertFalse(nimg.is_available())
def __init__(self, tag=BLENDER_DOCKER_TAG, image_id=None): image = DockerImage(image_id=id) if image_id \ else DockerImage(self.BLENDER_DOCKER_IMAGE, tag=tag) DockerEnvironment.__init__(self, [image]) self.short_description = "Blender (www.blender.org)" self.main_program_file = find_task_script(self.APP_DIR, self.SCRIPT_NAME)
def test_is_available_by_repo(self): # img = DockerImage(repository=self.TEST_REPOSITORY, tag=self.TEST_TAG) # self.assertTrue(img.is_available()) # self.assertEqual(img.name, "{}:{}".format(self.TEST_REPOSITORY, self.TEST_TAG)) nimg = DockerImage("imapp/xzy") self.assertFalse(nimg.is_available())
def test_is_available_by_id_and_tag(self): img = DockerImage(self.TEST_REPOSITORY, tag=self.TEST_TAG, image_id=self.TEST_ENV_ID) self.assertTrue(img.is_available()) nimg = DockerImage(self.TEST_REPOSITORY, tag="bogus", image_id=self.TEST_ENV_ID) self.assertFalse(nimg.is_available()) nimg2 = DockerImage(self.TEST_REPOSITORY, tag=self.TEST_TAG, image_id="deadface") self.assertFalse(nimg2.is_available())
def test_wrong_image_repository_specified(self): task = self._create_test_task() task.header.docker_images = [DockerImage("%$#@!!!")] task_thread, error_msg, out_dir = self._run_docker_task(task) if task_thread: assert not task_thread.result assert isinstance(error_msg, str)
def __init__(self, subtask_id: str, # pylint: disable=too-many-arguments docker_images: List[Union[DockerImage, Dict, Tuple]], src_code: str, extra_data: Dict, dir_mapping: DockerDirMapping, timeout: int, check_mem: bool = False) -> None: if not docker_images: raise AttributeError("docker images is None") super(DockerTaskThread, self).__init__( subtask_id=subtask_id, src_code=src_code, extra_data=extra_data, res_path=str(dir_mapping.resources), tmp_path=str(dir_mapping.temporary), timeout=timeout ) # Find available image self.image = None logger.debug("Checking docker images %s", docker_images) for img in docker_images: img = DockerImage.build(img) if img.is_available(): self.image = img break self.job: Optional[DockerJob] = None self.check_mem = check_mem self.dir_mapping = dir_mapping
def __init__(self) -> None: super().__init__(additional_images=[ DockerImage( repository=BlenderEnvironment.DOCKER_IMAGE, tag=BlenderEnvironment.DOCKER_TAG, ) ])
def test_wrong_image_repository_specified(self): task = self._get_test_task() task.docker_images = [DockerImage("%$#@!!!")] task_thread = self._run_task(task) if task_thread: self.assertFalse(task_thread.result) self.assertIsInstance(task_thread.error_msg, str) self.assertTrue(task_thread.error_msg)
def test_docker_environment(self): with self.assertRaises(AttributeError): DockerEnvironment(None) de = DockerEnvironment( [DockerImage("golemfactory/blender", tag="1.3")]) self.assertTrue(de.supported()) self.assertTrue(de.description().startswith( 'Default environment for generic tasks without any additional requirements.' )) self.assertTrue(de.check_docker_images())
def test_docker_environment(self): with self.assertRaises(TypeError): DockerEnvironment(None) with self.assertRaises(RuntimeTypeError): DockerEnvironmentMock(additional_images=["aaa"]) de = DockerEnvironmentMock( additional_images=[DockerImage("golemfactory/blender", tag="1.4")]) self.assertTrue(de.check_support()) self.assertTrue(de.check_docker_images())
def __init__(self, tag=None, image_id=None, additional_images: List[DockerImage] = None): if tag is None: tag = self.DOCKER_TAG image = DockerImage(image_id=image_id) if image_id \ else DockerImage(self.DOCKER_IMAGE, tag=tag) Environment.__init__(self) self.main_program_file = find_task_script(self.APP_DIR, self.SCRIPT_NAME) self.docker_images = [image] if additional_images: self.docker_images += additional_images if self.SHORT_DESCRIPTION: self.short_description = self.SHORT_DESCRIPTION
def test_is_available_by_repo_and_tag(self): img = DockerImage(self.TEST_REPOSITORY, tag=self.TEST_TAG) self.assertTrue(img.is_available()) self._is_test_image(img) nimg = DockerImage(self.TEST_REPOSITORY, tag="bogus") self.assertFalse(nimg.is_available())
def test_termination(self): script = "import time\ntime.sleep(20)" task_server = Mock() task_server.config_desc = ClientConfigDescriptor() task_server.client.datadir = self.test_dir task_server.benchmark_manager = Mock() task_server.benchmark_manager.benchmarks_needed.return_value = False task_server.client.get_node_name.return_value = "test_node" task_server.get_task_computer_root.return_value = \ task_server.client.datadir task_computer = TaskComputer(task_server, use_docker_manager=False) image = DockerImage("golemfactory/base", tag="1.2") with self.assertRaises(AttributeError): dir_mapping = DockerTaskThread.generate_dir_mapping( self.resources_dir, self.output_dir) DockerTaskThread("subtask_id", None, script, None, dir_mapping, timeout=30) def test(): dir_mapping = DockerTaskThread.generate_dir_mapping( self.resources_dir, self.output_dir) tt = DockerTaskThread("subtask_id", [image], script, None, "test task thread", dir_mapping, timeout=30) task_computer.counting_thread = tt task_computer.counting_task = True tt.setDaemon(True) tt.start() time.sleep(1) started = time.time() parent_thread = Thread(target=test) parent_thread.start() time.sleep(1) ct = task_computer.counting_thread while ct and ct.is_alive(): task_computer.run() if time.time() - started > 15: self.fail("Job timed out") else: ct = task_computer.counting_thread time.sleep(1)
def setUp(self): main_dir = get_local_datadir('tests-' + str(uuid.uuid4())) if not os.path.exists(main_dir): os.makedirs(main_dir) self.test_dir = tempfile.mkdtemp(dir=main_dir) self.work_dir = tempfile.mkdtemp(prefix="golem-", dir=self.test_dir) self.resources_dir = tempfile.mkdtemp(prefix="golem-", dir=self.test_dir) self.output_dir = tempfile.mkdtemp(prefix="golem-", dir=self.test_dir) if not is_windows(): os.chmod(self.test_dir, 0770) self.image = DockerImage(self._get_test_repository(), tag=self._get_test_tag()) self.test_job = None
def test_cmp_name_and_tag(self): img = DockerImage(self.TEST_REPOSITORY, tag=self.TEST_TAG, image_id=self.TEST_IMAGE_ID) img2 = DockerImage(self.TEST_REPOSITORY, tag=self.TEST_TAG) assert img.cmp_name_and_tag(img2) assert img2.cmp_name_and_tag(img) img3 = DockerImage(self.TEST_REPOSITORY, tag="bogus", image_id=self.TEST_IMAGE_ID) assert not img.cmp_name_and_tag(img3) assert not img3.cmp_name_and_tag(img) img4 = DockerImage("golemfactory/xyz", tag=self.TEST_TAG, image_id=self.TEST_IMAGE_ID) assert not img.cmp_name_and_tag(img4) assert not img4.cmp_name_and_tag(img)
def __compute_task(self, subtask_id, docker_images, src_code, extra_data, subtask_deadline): task_id = self.assigned_subtask['task_id'] task_header = self.task_server.task_keeper.task_headers.get(task_id) if not task_header: logger.warning("Subtask '%s' of task '%s' cannot be computed: " "task header has been unexpectedly removed", subtask_id, task_id) return self.session_closed() deadline = min(task_header.deadline, subtask_deadline) task_timeout = deadline_to_timeout(deadline) unique_str = str(uuid.uuid4()) logger.info("Starting computation of subtask %r (task: %r, deadline: " "%r, docker images: %r)", subtask_id, task_id, deadline, docker_images) self.reset(counting_task=task_id) with self.dir_lock: resource_dir = self.resource_manager.get_resource_dir(task_id) temp_dir = os.path.join( self.resource_manager.get_temporary_dir(task_id), unique_str) # self.dir_manager.clear_temporary(task_id) if not os.path.exists(temp_dir): os.makedirs(temp_dir) if docker_images: docker_images = [DockerImage(**did) for did in docker_images] dir_mapping = DockerTaskThread.generate_dir_mapping(resource_dir, temp_dir) tt = DockerTaskThread(subtask_id, docker_images, src_code, extra_data, dir_mapping, task_timeout) elif self.support_direct_computation: tt = PyTaskThread(subtask_id, src_code, extra_data, resource_dir, temp_dir, task_timeout) else: logger.error("Cannot run PyTaskThread in this version") subtask = self.assigned_subtask self.assigned_subtask = None self.task_server.send_task_failed( subtask_id, subtask['task_id'], "Host direct task not supported", ) self.counting_task = None if self.finished_cb: self.finished_cb() return with self.lock: self.counting_thread = tt tt.start().addBoth(lambda _: self.task_computed(tt))
def test_termination(self): script = "import time\ntime.sleep(20)" task_server = Mock() task_server.config_desc = ClientConfigDescriptor() task_server.config_desc.estimated_blender_performance = 2000.0 task_server.config_desc.estimated_lux_performance = 2000.0 task_server.client.datadir = self.test_dir task_server.client.get_node_name.return_value = "test_node" task_server.get_task_computer_root.return_value = task_server.client.datadir task_computer = TaskComputer("node", task_server, use_docker_machine_manager=False) image = DockerImage("golemfactory/base", tag="1.2") with self.assertRaises(AttributeError): DockerTaskThread(task_computer, "subtask_id", None, self.work_dir, script, None, "test task thread", self.resources_dir, self.output_dir, timeout=30) def test(): tt = DockerTaskThread(task_computer, "subtask_id", [image], self.work_dir, script, None, "test task thread", self.resources_dir, self.output_dir, timeout=30) task_computer.current_computations.append(tt) task_computer.counting_task = True tt.setDaemon(True) tt.start() time.sleep(1) started = time.time() parent_thread = Thread(target=test) parent_thread.start() time.sleep(1) ct = task_computer.current_computations[0] while ct and ct.is_alive(): task_computer.run() if time.time() - started > 15: self.fail("Job timed out") elif task_computer.current_computations: ct = task_computer.current_computations[0] else: ct = None time.sleep(1)
def test_react_to_task_to_compute(self): conn = Mock() ts = TaskSession(conn) ts.key_id = "KEY_ID" ts.task_manager = Mock() ts.task_computer = Mock() ts.task_server = Mock() ts.task_server.get_subtask_ttl.return_value = 31313 env = Mock() env.docker_images = [DockerImage("dockerix/xii", tag="323")] env.allow_custom_main_program_file = False env.get_source_code.return_value = None ts.task_server.get_environment_by_id.return_value = env def __reset_mocks(): ts.task_manager.reset_mock() ts.task_computer.reset_mock() conn.reset_mock() # msg.ctd is None -> failure msg = MessageTaskToCompute() with self.assertLogs(logger, level="WARNING"): ts._react_to_task_to_compute(msg) ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # No source code in the local environment -> failure __reset_mocks() ctd = ComputeTaskDef() ctd.key_id = "KEY_ID" ctd.subtask_id = "SUBTASKID" ctd.task_owner = Node() ctd.task_owner.key = "KEY_ID" ctd.return_address = "10.10.10.10" ctd.return_port = 1112 ctd.docker_images = [DockerImage("dockerix/xiii", tag="323")] msg = MessageTaskToCompute(ctd) ts._react_to_task_to_compute(msg) ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Source code from local environment -> proper execution __reset_mocks() env.get_source_code.return_value = "print 'Hello world'" ts._react_to_task_to_compute(msg) ts.task_manager.comp_task_keeper.receive_subtask.assert_called_with( ctd) ts.task_computer.session_closed.assert_not_called() ts.task_server.add_task_session.assert_called_with("SUBTASKID", ts) ts.task_computer.task_given.assert_called_with(ctd) conn.close.assert_not_called() # Wrong key id -> failure __reset_mocks() ctd.key_id = "KEY_ID2" ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Wrong task owner key id -> failure __reset_mocks() ctd.key_id = "KEY_ID" ctd.task_owner.key = "KEY_ID2" ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Wrong return port -> failure __reset_mocks() ctd.task_owner.key = "KEY_ID" ctd.return_port = 0 ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Proper port and key -> proper execution __reset_mocks() ctd.task_owner.key = "KEY_ID" ctd.return_port = 1319 ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) conn.close.assert_not_called() # Allow custom code / no code in ComputeTaskDef -> failure __reset_mocks() env.allow_custom_main_program_file = True ctd.src_code = "" ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Allow custom code / code in ComputerTaskDef -> proper execution __reset_mocks() ctd.src_code = "print 'Hello world!'" ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) ts.task_computer.session_closed.assert_not_called() ts.task_server.add_task_session.assert_called_with("SUBTASKID", ts) ts.task_computer.task_given.assert_called_with(ctd) conn.close.assert_not_called() # No environment available -> failure __reset_mocks() ts.task_server.get_environment_by_id.return_value = None ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) assert ts.err_msg.startswith("Wrong environment") ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Envrionment is Docker environment but with different images -> failure __reset_mocks() ts.task_server.get_environment_by_id.return_value = \ DockerEnvironment([DockerImage("dockerix/xii", tag="323"), DockerImage("dockerix/xiii", tag="325"), DockerImage("dockerix/xiii")]) ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) assert ts.err_msg.startswith("Wrong docker images") ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Envrionment is Docker environment with proper images, but no srouce code -> failure __reset_mocks() de = DockerEnvironment([ DockerImage("dockerix/xii", tag="323"), DockerImage("dockerix/xiii", tag="325"), DockerImage("dockerix/xiii", tag="323") ]) ts.task_server.get_environment_by_id.return_value = de ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) assert ts.err_msg.startswith("No source code") ts.task_manager.comp_task_keeper.receive_subtask.assert_not_called() ts.task_computer.session_closed.assert_called_with() assert conn.close.called # Proper Docker environment with source code __reset_mocks() file_name = os.path.join(self.path, "main_program_file") with open(file_name, 'w') as f: f.write("Hello world!") de.main_program_file = file_name ts._react_to_task_to_compute(MessageTaskToCompute(ctd)) ts.task_server.add_task_session.assert_called_with("SUBTASKID", ts) ts.task_computer.task_given.assert_called_with(ctd) conn.close.assert_not_called()
def setUp(self): # pylint: disable=R0915 super().setUp() dm = DockerTaskThread.docker_manager = DockerManager.install() dm.update_config(status_callback=mock.Mock(), done_callback=mock.Mock(), work_dir=self.new_path, in_background=True) self.blender_reference_generator = BlenderReferenceGenerator() self.golem_dir = get_golem_path() self.resources = [ 'tests/apps/blender/verification/test_data/bmw.blend' ] self.computer = ComputerAdapter() self.subtask_info = dict() self.subtask_info['res_x'] = 150 self.subtask_info['res_y'] = 150 self.subtask_info['samples'] = 35 self.subtask_info['use_frames'] = False self.subtask_info['end_task'] = 1 self.subtask_info['total_tasks'] = 1 self.subtask_info['node_id'] = 'deadbeef' self.subtask_info['frames'] = [1] self.subtask_info['start_task'] = 1 self.subtask_info[ 'subtask_id'] = '250771152547690738285326338136457465' self.subtask_info['crop_window'] = (0.0, 1.0, 0.0, 1.0) self.subtask_info['output_format'] = 'PNG' self.subtask_info['all_frames'] = [1] self.subtask_info['script_src'] = '' self.subtask_info['tmp_dir'] = self.tempdir self.subtask_info['subtask_timeout'] = 600 self.subtask_info['scene_file'] = '/golem/resources/bmw.blend' self.subtask_info['path_root'] = os.path.dirname(self.resources[0]) self.subtask_info['parts'] = 1 self.subtask_info['outfilebasename'] = 'GolemTask' self.subtask_info['owner'] = "deadbeef" self.subtask_info['ctd'] = dict() self.subtask_info['ctd']['deadline'] = time.time() + 3600 self.subtask_info['ctd']['docker_images'] = [ DockerImage('golemfactory/blender', tag='1.4').to_dict() ] self.subtask_info['ctd']['extra_data'] = dict() self.subtask_info['ctd']['extra_data']['end_task'] = \ self.subtask_info['end_task'] self.subtask_info['ctd']['extra_data']['frames'] = \ self.subtask_info['frames'] self.subtask_info['ctd']['extra_data']['outfilebasename'] = \ self.subtask_info['outfilebasename'] self.subtask_info['ctd']['extra_data']['output_format'] = \ self.subtask_info['output_format'] self.subtask_info['ctd']['extra_data']['path_root'] = \ self.subtask_info['path_root'] self.subtask_info['ctd']['extra_data']['scene_file'] = \ self.subtask_info['scene_file'] self.subtask_info['ctd']['extra_data']['script_src'] = \ self.subtask_info['script_src'] self.subtask_info['ctd']['extra_data']['start_task'] = \ self.subtask_info['start_task'] self.subtask_info['ctd']['extra_data']['total_tasks'] = \ self.subtask_info['total_tasks'] self.subtask_info['ctd']['short_description'] = '' self.subtask_info['ctd']['src_code'] = open( os.path.join( self.golem_dir, 'apps/blender/resources/scripts/docker_blendertask.py'), 'r').read() self.subtask_info['ctd']['subtask_id'] = self.subtask_info[ 'subtask_id']