def _cancel(self): """ Cancel on-going storlet execution """ client = SBusClient(self.storlet_pipe_path) try: resp = client.cancel(self.task_id) if not resp.status: raise StorletRuntimeException('Failed to cancel task') except SBusClientException: raise StorletRuntimeException('Failed to cancel task')
def activate_storlet_daemon(self, sreq, cache_updated=True): storlet_daemon_status = \ self.get_storlet_daemon_status(sreq.storlet_main) if (storlet_daemon_status == -1): # We failed to send a command to the factory. # Best we can do is execute the container. self.logger.debug('Failed to check Storlet daemon status, ' 'restart Docker container') try: self.restart() except StorletTimeout: raise StorletRuntimeException('Docker container is ' 'not responsive') storlet_daemon_status = 0 if (cache_updated is True and storlet_daemon_status == 1): # The cache was updated while the daemon is running we need to # stop it. self.logger.debug('The cache was updated, and the storlet daemon ' 'is running. Stopping daemon') res = self.stop_storlet_daemon(sreq.storlet_main) if res != 1: try: self.restart() except StorletTimeout: raise StorletRuntimeException('Docker container is ' 'not responsive') else: self.logger.debug('Deamon stopped') storlet_daemon_status = 0 if (storlet_daemon_status == 0): self.logger.debug('Going to start storlet daemon!') # TODO(takashi): This is not needed for python application classpath = self._get_storlet_classpath( sreq.storlet_main, sreq.storlet_id, sreq.dependencies) daemon_status = self.start_storlet_daemon( classpath, sreq.storlet_main, sreq.storlet_language, sreq.options.get("storlet_language_version")) if daemon_status != 1: self.logger.error('Daemon start Failed, returned code is %d' % daemon_status) raise StorletRuntimeException('Daemon start failed') else: self.logger.debug('Daemon started')
def _wait_for_read_with_timeout(self, fd): """ Wait while the read file descriptor gets ready :param fd: File descriptor to read :raises StorletTimeout: Exception raised when it times out to cancel the existing task :raises StorletRuntimeException: Exception raised when it fails to cancel the existing task """ try: with StorletTimeout(self.timeout): r, w, e = select.select([fd], [], []) except StorletTimeout: exc_type, exc_value, exc_traceback = sys.exc_info() # When there is a task already running, we should cancel it. if self.task_id: try: self._cancel() except StorletRuntimeException: self.logger.warning( 'Task %s timed out, but failed to get canceled' % self.task_id) pass six.reraise(exc_type, exc_value, exc_traceback) if fd not in r: raise StorletRuntimeException('Read fd is not ready')
def _send_execute_command(self): """ Send execute command to the remote daemon factory to invoke storlet execution """ client = SBusClient(self.storlet_pipe_path) try: resp = client.execute(self.srequest.params, self.remote_fds) if not resp.status: raise StorletRuntimeException("Failed to send execute command") if not resp.task_id: raise StorletRuntimeException("Missing task id") else: self.task_id = resp.task_id except SBusClientException: raise StorletRuntimeException("Failed to send execute command")
def _send_execute_command(self): """ Send execute command to the remote daemon factory to invoke storlet execution """ dtg = SBusExecuteDatagram( SBUS_CMD_EXECUTE, self.remote_fds, self.srequest.params) rc = SBus.send(self.storlet_pipe_path, dtg) if (rc < 0): raise StorletRuntimeException("Failed to send execute command")
def _wait_for_write_with_timeout(self, fd): """ Wait while the write file descriptor gets ready :param fd: File descriptor to write :raises StorletTimeout: Exception raised when it times out to cancel the existing task :raises StorletRuntimeException: Exception raised when it fails to cancel the existing task """ with StorletTimeout(self.timeout): r, w, e = select.select([], [fd], []) if fd not in w: raise StorletRuntimeException('Write fd is not ready')
def _read_metadata(self): """ Read metadata in the storlet execution result from fd :returns: a dict of metadata """ self._wait_for_read_with_timeout(self.metadata_read_fd) flat_json = os.read(self.metadata_read_fd, MAX_METADATA_SIZE) os.close(self.metadata_read_fd) try: return json.loads(flat_json) except ValueError: self.logger.exception('Failed to load metadata from json') raise StorletRuntimeException('Got invalid format about metadata')
def _parse_sandbox_factory_answer(self, str_answer): """ Parse answer string received from container side :param str_answer: answer string :returns: (status, message) """ two_tokens = str_answer.split(':', 1) if len(two_tokens) != 2: self.logger.error('Got wrong format about answer over sbus: %s' % str_answer) raise StorletRuntimeException('Got wrong answer') status = (two_tokens[0] == 'True') return status, two_tokens[1]
def _cancel(self): """ Cancel on-going storlet execution """ with _open_pipe() as (read_fd, write_fd): dtg = SBusServiceDatagram( sbus_cmd.SBUS_CMD_CANCEL, [write_fd], [FDMetadata(sbus_fd.SBUS_FD_SERVICE_OUT).to_dict()], None, self.task_id) rc = SBus.send(self.storlet_pipe_path, dtg) if (rc < 0): raise StorletRuntimeException('Failed to cancel task') # TODO(takashi): Check the response here os.read(read_fd, 10)
def _restart(self, docker_image_name): """ Restarts the scope's sandbox using the specified docker image :param docker_image_name: name of the docker image to start :raises StorletRuntimeException: when failed to restart the container """ if self.docker_repo: docker_image_name = '%s/%s' % (self.docker_repo, docker_image_name) docker_container_name = '%s_%s' % (self.docker_image_name_prefix, self.scope) pipe_mount = '%s:%s' % (self.paths.host_pipe_dir, self.paths.sandbox_pipe_dir) storlet_mount = '%s:%s:ro' % (self.paths.host_storlet_base_dir, self.paths.sandbox_storlet_base_dir) storlet_native_lib_mount = '%s:%s:ro' % ( self.paths.host_storlet_native_lib_dir, self.paths.sandbox_storlet_native_lib_dir) storlet_native_bin_mount = '%s:%s:ro' % ( self.paths.host_storlet_native_bin_dir, self.paths.sandbox_storlet_native_bin_dir) cmd = [os.path.join(self.paths.host_restart_script_dir, 'restart_docker_container'), docker_container_name, docker_image_name, pipe_mount, storlet_mount, storlet_native_lib_mount, storlet_native_bin_mount] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() if stdout: if not isinstance(stdout, str): stdout = stdout.decode("utf-8") self.logger.debug('STDOUT: %s' % stdout.replace('\n', '#012')) if stderr: if not isinstance(stderr, str): stderr = stderr.decode("utf-8") self.logger.error('STDERR: %s' % stderr.replace('\n', '#012')) if proc.returncode: raise StorletRuntimeException('Failed to restart docker container')
def dummy_wait_failure(*args, **kwargs): raise StorletRuntimeException()