def wait_for_daemon_to_initialize(self, storlet_name): """ Send a Ping service datagram. Validate that Daemon response is correct. Give up after the predefined number of attempts (5) :param storlet_name: Storlet name we are checking the daemon for :returns: daemon status (True, False) """ storlet_pipe_name = self.storlet_name_to_pipe_name[storlet_name] self.logger.debug('Send PING command to {0} via {1}'.format( storlet_name, storlet_pipe_name)) client = SBusClient(storlet_pipe_name) for i in range(self.NUM_OF_TRIES_PINGING_STARTING_DAEMON): try: resp = client.ping() if resp.status: self.logger.debug( 'The storlet daemon {0} is started'.format( storlet_name)) return True except SBusClientSendError: pass except SBusClientException: self.logger.exception('Failed to send sbus command') break time.sleep(1) return False
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 shutdown_process(self, storlet_name): """ send HALT command to storlet daemon :param storlet_name: Storlet name we are checking the daemon for :raises SDaemonError: when wailed to shutdown the storlet daemon """ self.logger.debug( 'Shutdown the storlet daemon {0}'.format(storlet_name)) dmn_pid = self.storlet_name_to_pid.get(storlet_name) if dmn_pid is None: raise SDaemonError( 'PID of the storlet daemon {0} is not found'.format( storlet_name)) self.logger.debug('PID of the storlet daemon {0} is {1}'.format( storlet_name, dmn_pid)) storlet_pipe_name = self.storlet_name_to_pipe_name[storlet_name] self.logger.debug('Send HALT command to {0} via {1}'.format( storlet_name, storlet_pipe_name)) client = SBusClient(storlet_pipe_name) try: resp = client.halt() if not resp.status: self.logger.error('Failed to send sbus command: %s' % resp.message) raise SDaemonError( 'Failed to send halt to {0}'.format(storlet_name)) except SBusClientException: self.logger.exception('Failed to send sbus command') raise SDaemonError( 'Failed to send halt command to the storlet daemon {0}'.format( storlet_name)) try: os.waitpid(dmn_pid, 0) self.storlet_name_to_pid.pop(storlet_name) self.logger.debug( 'The storlet daemon {0} is stopped'.format(storlet_name)) except OSError: self.logger.exception( 'Error when waiting the storlet daemon {0}'.format( storlet_name)) raise SDaemonError( 'Failed to wait the storlet daemon {0}'.format(storlet_name))
def get_storlet_daemon_status(self, storlet_id): """ Get the status of SDaemon process in the scope's sandbox """ pipe_path = self.paths.host_factory_pipe client = SBusClient(pipe_path) try: resp = client.daemon_status(storlet_id) if resp.status: return 1 else: self.logger.error('Failed to get status about storlet ' 'daemon: %s' % resp.message) return 0 except SBusClientException: return -1
def stop_storlet_daemon(self, storlet_id): """ Stop SDaemon process in the scope's sandbox """ pipe_path = self.paths.host_factory_pipe client = SBusClient(pipe_path) try: resp = client.stop_daemon(storlet_id) if resp.status: return 1 else: self.logger.error('Failed to stop storlet daemon: %s' % resp.message) return 0 except SBusClientException: return -1
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 ping(self): """ Ping to daemon factory process inside container :returns: 1 when the daemon factory is responsive 0 when the daemon factory is not responsive -1 when it fails to send command to the process """ pipe_path = self.paths.host_factory_pipe client = SBusClient(pipe_path) try: resp = client.ping() if resp.status: return 1 else: self.logger.error('Failed to ping to daemon factory: %s' % resp.message) return 0 except SBusClientException: return -1
def start_storlet_daemon( self, spath, storlet_id, language, language_version=None): """ Start SDaemon process in the scope's sandbox """ pipe_path = self.paths.host_factory_pipe client = SBusClient(pipe_path) try: resp = client.start_daemon( language.lower(), spath, storlet_id, self.paths.get_sbox_storlet_pipe(storlet_id), self.storlet_daemon_debug_level, self.storlet_daemon_thread_pool_size, language_version) if resp.status: return 1 else: self.logger.error('Failed to start storlet daemon: %s' % resp.message) return 0 except SBusClientException: return -1
def main(): argv = sys.argv # TODO(takashi): Add more detailed help message if len(argv) < 3: print('sbus <command> <pipe_path>') sys.exit(EXIT_ERROR) command = argv[1] pipe_path = argv[2] if not os.path.exists(pipe_path): print('ERROR: Pipe file %s does not exist' % pipe_path) sys.exit(EXIT_ERROR) client = SBusClient(pipe_path) try: handler = getattr(client, command) # TODO(takashi): Currently this only works for ping or halt. # We need to pass more parameters like storlet_name # to implement the other command types. resp = handler() except (AttributeError, NotImplementedError): print('ERROR: Command %s is not supported' % command) sys.exit(EXIT_ERROR) except SBusClientException as err: print('ERROR: Failed to send sbus command %s to %s: %s' % (command, pipe_path, err)) sys.exit(EXIT_ERROR) except Exception as err: print('ERROR: Unknown error: %s' % err) sys.exit(EXIT_ERROR) print('Response: %s: %s' % (resp.status, resp.message)) if resp.status: print('OK') sys.exit(EXIT_SUCCESS) else: print('ERROR: Got error response') sys.exit(EXIT_ERROR)
def setUp(self): self.pipe_path = 'pipe_path' self.client = SBusClient(self.pipe_path, 4)
class TestSBusClient(unittest.TestCase): def setUp(self): self.pipe_path = 'pipe_path' self.client = SBusClient(self.pipe_path, 4) def test_parse_response(self): raw_resp = json.dumps({'status': True, 'message': 'OK'}) resp = self.client._parse_response(raw_resp) self.assertTrue(resp.status) self.assertEqual('OK', resp.message) raw_resp = json.dumps({'status': False, 'message': 'ERROR'}) resp = self.client._parse_response(raw_resp) self.assertFalse(resp.status) self.assertEqual('ERROR', resp.message) raw_resp = json.dumps({'status': True, 'message': 'Sample:Message'}) resp = self.client._parse_response(raw_resp) self.assertTrue(resp.status) self.assertEqual('Sample:Message', resp.message) with self.assertRaises(SBusClientMalformedResponse): self.client._parse_response('Foo') raw_resp = json.dumps({'status': True}) with self.assertRaises(SBusClientMalformedResponse): self.client._parse_response(raw_resp) raw_resp = json.dumps({'message': 'foo'}) with self.assertRaises(SBusClientMalformedResponse): self.client._parse_response(raw_resp) def _check_all_pipes_closed(self, pipes): # Make sure that pipes are not empty self.assertGreater(len(pipes), 0) for _pipe in pipes: self.assertTrue(_pipe[0].closed) self.assertTrue(_pipe[1].closed) def _test_service_request(self, method, *args, **kwargs): raw_resp = json.dumps( {'status': True, 'message': 'OK'}).encode("utf-8") with _mock_os_pipe([raw_resp]) as pipes, _mock_sbus(0): resp = method(*args, **kwargs) self.assertTrue(resp.status) self.assertEqual('OK', resp.message) self._check_all_pipes_closed(pipes) raw_resp = json.dumps( {'status': False, 'message': 'ERROR'}).encode("utf-8") with _mock_os_pipe([raw_resp]) as pipes, _mock_sbus(0): resp = method(*args, **kwargs) self.assertFalse(resp.status) self.assertEqual('ERROR', resp.message) self._check_all_pipes_closed(pipes) raw_resp = json.dumps( {'status': True, 'message': 'OK'}).encode("utf-8") with _mock_os_pipe([raw_resp]) as pipes, _mock_sbus(-1): with self.assertRaises(SBusClientSendError): method(*args, **kwargs) self._check_all_pipes_closed(pipes) # TODO(takashi): Add IOError case with _mock_os_pipe([b'Foo']) as pipes, _mock_sbus(0): with self.assertRaises(SBusClientMalformedResponse): method(*args, **kwargs) self._check_all_pipes_closed(pipes) def test_ping(self): self._test_service_request(self.client.ping) def test_start_daemon(self): self._test_service_request( self.client.start_daemon, 'java', 'path/to/storlet', 'storleta', 'path/to/uds', 'INFO', '10', '11') def test_stop_daemon(self): self._test_service_request(self.client.stop_daemon, 'storleta') def test_stop_daemons(self): self._test_service_request(self.client.stop_daemons) def test_halt(self): self._test_service_request(self.client.halt) def test_daemon_status(self): self._test_service_request(self.client.daemon_status, 'storleta') def test_cancel(self): self._test_service_request(self.client.cancel, 'taskid')