def main(): """ The entry point of daemon_factory process """ parser = argparse.ArgumentParser( description='Factory process to manage storlet daemons') parser.add_argument('sbus_path', help='the path to unix domain socket') parser.add_argument('log_level', help='log level') parser.add_argument('container_id', help='container id') opts = parser.parse_args() # Initialize logger logger = get_logger("daemon-factory", opts.log_level, opts.container_id) logger.debug("Daemon factory started") try: SBus.start_logger("DEBUG", container_id=opts.container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of daemon_factory factory = StorletDaemonFactory(opts.sbus_path, logger, opts.container_id) # Start the main loop sys.exit(factory.main_loop()) except Exception: logger.eception('Unhandled exception') sys.exit(EXIT_FAILURE)
def main_loop(self): """ Main loop to run storlet application :returns: EXIT_SUCCESS when the loop exists normally EXIT_FAILURE when some error occurd in main loop """ sbus = SBus() fd = sbus.create(self.sbus_path) if fd < 0: self.logger.error("Failed to create SBus. exiting.") return EXIT_FAILURE while True: rc = sbus.listen(fd) if rc < 0: self.logger.error("Failed to wait on SBus. exiting.") return EXIT_FAILURE dtg = sbus.receive(fd) if dtg is None: self.logger.error("Failed to receive message. exiting") return EXIT_FAILURE if not self.dispatch_command(dtg): break self.logger.debug('Leaving main loop') self._terminate() return EXIT_SUCCESS
def main(argv): """ The entry point of daemon_factory process :param argv: parameters given from command line """ if (len(argv) != 5): usage() return EXIT_FAILURE storlet_name = argv[0] sbus_path = argv[1] log_level = argv[2] pool_size = argv[3] container_id = argv[4] # Initialize logger logger = start_logger("storlets-daemon", log_level, container_id) logger.debug("Storlet Daemon started") SBus.start_logger("DEBUG", container_id=container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of storlet daemon try: daemon = Daemon(storlet_name, sbus_path, logger, pool_size) except Exception as e: logger.error(e.message) return EXIT_FAILURE # Start the main loop return daemon.main_loop()
def main_loop(self): """ Main loop to run storlet application """ sbus = SBus() fd = sbus.create(self.sbus_path) if fd < 0: self.logger.error("Failed to create SBus. exiting.") return EXIT_FAILURE while True: rc = sbus.listen(fd) if rc < 0: self.logger.error("Failed to wait on SBus. exiting.") return EXIT_FAILURE dtg = sbus.receive(fd) if dtg is None: self.logger.error("Failed to receive message. exiting") return EXIT_FAILURE if not self.dispatch_command(dtg): break self.logger.debug('Leaving main loop') self._wait_all_child_processes() return EXIT_SUCCESS
def main(argv): """ The entry point of daemon_factory process :param argv: parameters given from command line """ if (len(argv) != 3): usage() return EXIT_FAILURE pipe_path = argv[0] log_level = argv[1] container_id = argv[2] # Initialize logger logger = start_logger("daemon-factory", log_level, container_id) logger.debug("Daemon factory started") SBus.start_logger("DEBUG", container_id=container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of daemon_factory factory = DaemonFactory(pipe_path, logger, container_id) # Start the main loop return factory.main_loop()
def _request(self, command, params=None, task_id=None, extra_fds=None): read_fd, write_fd = os.pipe() try: try: sfds = \ [SBusFileDescriptor(SBUS_FD_SERVICE_OUT, write_fd)] + \ (extra_fds or []) datagram = build_datagram(command, sfds, params, task_id) rc = SBus.send(self.socket_path, datagram) if rc < 0: raise SBusClientSendError( 'Faild to send command(%s) to socket %s' % (datagram.command, self.socket_path)) finally: # We already sent the write fd to remote, so should close it # in local side before reading response os.close(write_fd) reply = b'' while True: try: buf = os.read(read_fd, self.chunk_size) except IOError: raise SBusClientIOError( 'Failed to read data from read pipe') if not buf: break reply = reply + buf finally: os.close(read_fd) if not isinstance(reply, str): reply = reply.decode('utf-8') return self._parse_response(reply)
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)) read_fd, write_fd = os.pipe() try: dtg = SBusDatagram.create_service_datagram( SBUS_CMD_PING, write_fd) for i in range(self.NUM_OF_TRIES_PINGING_STARTING_DAEMON): ret = SBus.send(storlet_pipe_name, dtg) if ret >= 0: resp = os.read(read_fd, 128) if resp.startswith('True'): return True time.sleep(1) else: return False finally: os.close(read_fd) os.close(write_fd)
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() with _open_pipe() as (read_fd, write_fd): dtg = SBusServiceDatagram( sbus_cmd.SBUS_CMD_PING, [write_fd], [FDMetadata(sbus_fd.SBUS_FD_SERVICE_OUT).to_dict()]) rc = SBus.send(pipe_path, dtg) if (rc < 0): return -1 reply = os.read(read_fd, 10) res, error_txt = self._parse_sandbox_factory_answer(reply) if res is True: return 1 self.logger.error('Failed to ping to daemon factory: %s' % error_txt) return 0
def get_storlet_daemon_status(self, storlet_id): """ Get the status of SDaemon process in the scope's sandbox """ with _open_pipe() as (read_fd, write_fd): dtg = SBusServiceDatagram( sbus_cmd.SBUS_CMD_DAEMON_STATUS, [write_fd], [FDMetadata(sbus_fd.SBUS_FD_SERVICE_OUT).to_dict()], {'storlet_name': storlet_id}) pipe_path = self.paths.host_factory_pipe() rc = SBus.send(pipe_path, dtg) if (rc < 0): self.logger.info("Failed to send status command to %s %s" % (self.scope, storlet_id)) return -1 reply = os.read(read_fd, 10) res, error_txt = self._parse_sandbox_factory_answer(reply) if res is True: return 1 self.logger.error('Failed to get status about storlet daemon: %s' % error_txt) return 0
def start_storlet_daemon(self, spath, storlet_id, language): """ Start SDaemon process in the scope's sandbox """ prms = {'daemon_language': language.lower(), 'storlet_path': spath, 'storlet_name': storlet_id, 'uds_path': self.paths.sbox_storlet_pipe(storlet_id), 'log_level': self.storlet_daemon_debug_level, 'pool_size': self.storlet_daemon_thread_pool_size} with _open_pipe() as (read_fd, write_fd): dtg = SBusDatagram.create_service_datagram( sbus_cmd.SBUS_CMD_START_DAEMON, write_fd, prms) pipe_path = self.paths.host_factory_pipe() rc = SBus.send(pipe_path, dtg) # TODO(takashi): Why we should rond rc into -1? if (rc < 0): return -1 reply = os.read(read_fd, 10) res, error_txt = self._parse_sandbox_factory_answer(reply) if res is True: return 1 self.logger.error('Failed to start storlet daemon: %s' % error_txt) return 0
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() with _open_pipe() as (read_fd, write_fd): dtg = SBusDatagram.create_service_datagram( sbus_cmd.SBUS_CMD_PING, write_fd) rc = SBus.send(pipe_path, dtg) if (rc < 0): return -1 reply = os.read(read_fd, 10) res, error_txt = self._parse_sandbox_factory_answer(reply) if res is True: return 1 self.logger.error('Failed to ping to daemon factory: %s' % error_txt) return 0
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 main(): """ The entry point of daemon_factory process """ parser = argparse.ArgumentParser( description='Daemon process to execute storlet applications') parser.add_argument('storlet_name', help='storlet name') parser.add_argument('sbus_path', help='the path to unix domain socket') parser.add_argument('log_level', help='log level') parser.add_argument('pool_size', type=int, help='the maximun thread numbers used swapns for ' 'one storlet application') parser.add_argument('container_id', help='container id') opts = parser.parse_args() # Initialize logger logger = get_logger("storlets-daemon", opts.log_level, opts.container_id) logger.debug("Storlet Daemon started") try: SBus.start_logger("DEBUG", container_id=opts.container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of storlet daemon daemon = StorletDaemon(opts.storlet_name, opts.sbus_path, logger, opts.pool_size) # Start the main loop sys.exit(daemon.main_loop()) except Exception: logger.error('Unhandled exception') sys.exit(EXIT_FAILURE)
def _send_execute_command(self): """ Send execute command to the remote daemon factory to invoke storlet execution """ dtg = SBusDatagram( sbus_cmd.SBUS_CMD_EXECUTE, self.remote_fds, self.remote_fds_metadata, self.srequest.params) rc = SBus.send(self.storlet_pipe_path, dtg) if (rc < 0): raise StorletRuntimeException("Failed to send execute command")
def main_loop(self): """ The 'internal' loop. Listen to SBus, receive datagram, dispatch command, report back. :returns: exit status (SUCCESS/FAILURE) """ # Create SBus. Listen and process requests sbus = SBus() fd = sbus.create(self.pipe_path) if fd < 0: self.logger.error("Failed to create SBus. exiting.") return EXIT_FAILURE while True: rc = sbus.listen(fd) if rc < 0: self.logger.error("Failed to wait on SBus. exiting.") return EXIT_FAILURE self.logger.debug("Wait returned") dtg = sbus.receive(fd) # TODO(eranr): # Should we really be exitting here. # If so should we exit the container altogether, so # that it gets restarted? if dtg is None: self.logger.error("Failed to receive message. exiting.") return EXIT_FAILURE if not self.dispatch_command(dtg): break # We left the main loop for some reason. Terminating. self.logger.debug('Leaving main loop') return EXIT_SUCCESS
def _cancel(self): """ Cancel on-going storlet execution """ with _open_pipe() as (read_fd, write_fd): dtg = SBusDatagram.create_service_datagram( sbus_cmd.SBUS_CMD_CANCEL, write_fd, 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 reponse here os.read(read_fd, 10)
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 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) self.logger.debug('Storlet Daemon PID is {0}'.format(dmn_pid)) if dmn_pid is None: raise SDaemonError('{0} is not found'.format(storlet_name)) 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)) read_fd, write_fd = os.pipe() try: dtg = SBusDatagram.create_service_datagram( SBUS_CMD_HALT, write_fd) rc = SBus.send(storlet_pipe_name, dtg) os.close(write_fd) if rc < 0: raise SDaemonError( 'Failed to send halt to {0}'.format(storlet_name)) resp = os.read(read_fd, 128) if not resp.startswith('True'): raise SDaemonError( 'Failed to send halt to {0}'.format(storlet_name)) finally: os.close(read_fd) try: os.waitpid(dmn_pid, 0) self.storlet_name_to_pid.pop(storlet_name) except OSError: self.logger.exception( 'Error when waiting the storlet daemon {0}'.format( storlet_name)) raise SDaemonError('Failed to wait {0}'.format(storlet_name))
def main(argv): if len(argv) < 2: print_usage(argv) return daemon_factory_pipe_name = argv[1] try: fi, fo = os.pipe() halt_dtg = SBusDatagram.create_service_datagram( SBUS_CMD_HALT, fo) n_status = SBus.send(daemon_factory_pipe_name, halt_dtg) if n_status < 0: print('Sending failed') else: print('Sending succeeded') cmd_response = os.read(fi, 256) print(cmd_response) finally: os.close(fi) os.close(fo)
def main(argv): if len(argv) < 2: print_usage(argv) return daemon_factory_pipe_name = argv[1] try: fi, fo = os.pipe() halt_dtg = SBusServiceDatagram( SBUS_CMD_HALT, [fo], [FDMetadata(SBUS_FD_SERVICE_OUT).to_dict()]) n_status = SBus.send(daemon_factory_pipe_name, halt_dtg) if n_status < 0: print('Sending failed') else: print('Sending succeeded') cmd_response = os.read(fi, 256) print(cmd_response) finally: os.close(fi) os.close(fo)
def stop_storlet_daemon(self, storlet_id): """ Stop SDaemon process in the scope's sandbox """ with _open_pipe() as (read_fd, write_fd): dtg = SBusDatagram.create_service_datagram( sbus_cmd.SBUS_CMD_STOP_DAEMON, write_fd, {'storlet_name': storlet_id}) pipe_path = self.paths.host_factory_pipe() rc = SBus.send(pipe_path, dtg) if (rc < 0): self.logger.info("Failed to send status command to %s %s" % (self.scope, storlet_id)) return -1 reply = os.read(read_fd, 10) res, error_txt = self._parse_sandbox_factory_answer(reply) if res is True: return 1 self.logger.error('Failed to stop storlet daemon: %s' % error_txt) return 0
def start_storlet_daemon( self, spath, storlet_id, language, language_version=None): """ Start SDaemon process in the scope's sandbox """ prms = {'daemon_language': language.lower(), 'storlet_path': spath, 'storlet_name': storlet_id, 'uds_path': self.paths.sbox_storlet_pipe(storlet_id), 'log_level': self.storlet_daemon_debug_level, 'pool_size': self.storlet_daemon_thread_pool_size} if language_version: prms.update({'daemon_language_version': language_version}) with _open_pipe() as (read_fd, write_fd): dtg = SBusServiceDatagram( sbus_cmd.SBUS_CMD_START_DAEMON, [write_fd], [FDMetadata(sbus_fd.SBUS_FD_SERVICE_OUT).to_dict()], prms) pipe_path = self.paths.host_factory_pipe() rc = SBus.send(pipe_path, dtg) # TODO(takashi): Why we should rond rc into -1? if (rc < 0): return -1 reply = os.read(read_fd, 10) res, error_txt = self._parse_sandbox_factory_answer(reply) if res is True: return 1 self.logger.error('Failed to start storlet daemon: %s' % error_txt) return 0