def __init__(self): try: self.startup() self.state = StateManager(self.conf) self.loop = asyncio.get_event_loop() self.bpcon = BPConProtocol(self.conf, self.state) self.paxos_server = websockets.serve(self.bpcon.main_loop, self.conf['ip_addr'], self.conf['port'], ssl=self.conf['ssl']) self.loop.run_until_complete(self.paxos_server) log.info("Started BPCon on port {}".format(self.conf['port'])) if self.conf['is_client']: log.debug("is client. making test requests") for x in range(1): self.commit("P,{},hello{}".format(x, x)) self.commit("P,test,value") self.commit("P,test{},value{}".format(x, x)) self.commit("P,test2,value2") self.commit("P,test,value3") self.commit("D,test2,") log.debug("requests complete") except Exception as e: log.info(e)
def __init__(self, resolution, host, port, username, password, split="\n"): global network_log self.log = Log('client') network_log = Log('network') # must have at least one handler self.log.logger.addHandler(logging.NullHandler()) network_log.logger.addHandler(logging.NullHandler()) # opengl must be initialized first self.log.info("Initializing display (windowed at %(resolution)s)", dict(resolution='%dx%d' % resolution)) self._screen = pygame.display.set_mode(resolution, OPENGL | DOUBLEBUF) pygame.display.set_caption('yamosg') self.log.debug( "OpenGL setup (version=\"%(version)s\", vendor=\"%(vendor)s\")", dict(version=glGetString(GL_VERSION), vendor=glGetString(GL_VENDOR))) setup_opengl() Client.cursor_default = pygame.cursors.arrow Client.cursor_capture = pygame.cursors.diamond self._resolution = Vector2i(resolution) self._username = username self._password = password self._split = split self._running = False self._state = StateManager() self._game = GameWidget(self, self._resolution) self._container = Composite(Vector2i(0, 0), self._resolution, children=[self._game]) self._toolbar = Toolbar(self._game) self._window = VBox() self._window.add(self._toolbar, size=LayoutAttachment(Vector2i(1, 0), Vector2i(0, 25))) self._window.add(self._container) self._state.push(GameState(self._resolution, self._window)) self._network = Network(self, host, port) self._command_store = {} self._command_queue = [] self._command_lock = threading.Lock() self._playerid = None self._players = {} self._capture_position = None self._timer = 0 # resizing must be done after state has been created so the event is propagated proper. self._resize(self._resolution)
def get_zpl_printer(self): printer = StateManager.getInstance().printer_zpl # print test request coming out if printer.print_test_request: self.push_task('printstatus') printer.print_test_request = False printer_device = None try: printer_device = Usb(printer.vendor_id, printer.product_id) printer.status = Printer.STATUS_CONNECTED return printer_device except usb.core.USBError: printer.status = Printer.STATUS_DISCONNECTED finally: if printer.status != self.current_printer_status: self.current_printer_status = printer.status if printer_device: self.set_status( 'connected', "Connected to %s (in=0x%02x,out=0x%02x)" % (printer.description, printer_device.in_ep, printer_device.out_ep)) else: self.set_status('disconnected', 'Printer Not Found') # update status in GUI self.printer_status_signal.emit(str(StateManager.ZPL_PRINTER), str(printer.status)) return printer_device
def __init__(self, server, manager): super(TableauStatusMonitor, self).__init__() self.server = server self.system = server.system self.event = self.server.event_control self.rwlock = self.server.upgrade_rwlock self.manager = manager # AgentManager instance self.envid = self.server.environment.envid self.first_degraded_time = None self.sent_degraded_event = False logger.setLevel(self.system[SystemKeys.DEBUG_LEVEL]) # Start fresh: status table session = meta.Session() self.remove_all_status() session.commit() self.stateman = StateManager(self.server)
def startup(self): """ startup routine Loads from cloned state """ # clean working dir and extract config, creds, and state log.info("Cleaning working directory...") command = "rm config.ini && rm -rf data && rm -rf creds" shell(command) log.info("Extracting cloned state...") command = "tar xzf clone.tar.gz" shell(command) # load config log.info("Loading configuration...") self.cm = ConfigManager() self.conf = self.cm.load_config(configFile) # load state log.info("Loading state...") self.state = StateManager(self.conf) self.state.load_state()
def setup_log(): state = StateManager.getInstance() logformat = '%(asctime)s - %(funcName)s - %(levelname)s: %(message)s' if state.is_frozen is False: logging.basicConfig(format=logformat, level=state.log.level, handlers=[logging.StreamHandler()]) else: logging.basicConfig(format=logformat, level=state.log.level, filename=state.get_log().filename, filemode='a')
def __init__(self, resolution, host, port, username, password, split="\n"): global network_log self.log = Log('client') network_log = Log('network') # must have at least one handler self.log.logger.addHandler(logging.NullHandler()) network_log.logger.addHandler(logging.NullHandler()) # opengl must be initialized first self.log.info("Initializing display (windowed at %(resolution)s)", dict(resolution='%dx%d'%resolution)) self._screen = pygame.display.set_mode(resolution, OPENGL|DOUBLEBUF) pygame.display.set_caption('yamosg') self.log.debug("OpenGL setup (version=\"%(version)s\", vendor=\"%(vendor)s\")", dict(version=glGetString(GL_VERSION), vendor=glGetString(GL_VENDOR))) setup_opengl() Client.cursor_default = pygame.cursors.arrow Client.cursor_capture = pygame.cursors.diamond self._resolution = Vector2i(resolution) self._username = username self._password = password self._split = split self._running = False self._state = StateManager() self._game = GameWidget(self, self._resolution) self._container = Composite(Vector2i(0,0), self._resolution, children=[self._game]) self._toolbar = Toolbar(self._game) self._window = VBox() self._window.add(self._toolbar, size=LayoutAttachment(Vector2i(1,0), Vector2i(0,25))) self._window.add(self._container) self._state.push(GameState(self._resolution, self._window)) self._network = Network(self, host, port) self._command_store = {} self._command_queue = [] self._command_lock = threading.Lock() self._playerid = None self._players = {} self._capture_position = None self._timer = 0 # resizing must be done after state has been created so the event is propagated proper. self._resize(self._resolution)
def __init__(self, parent=None): super(LinkBox, self).__init__(parent) self.state = StateManager.getInstance() self.state.set_dialog(self) self.setupUi(self) self.setWindowTitle('LinkBox') self._register_thread() self._register_signal() # attribute registration self.printer_zpl_model = QtGui.QStandardItemModel() self.printer_escpos_model = QtGui.QStandardItemModel() # update status try: self._init_ui() except usb.core.NoBackendError as e: QtWidgets.QMessageBox.question(self, 'System Error', str(e), QtWidgets.QMessageBox.Close) sys.exit()
def run(self): app = HTTPServer() def get_all_subclasses(cls): all_subclasses = [] for subclass in cls.__subclasses__(): all_subclasses.append(subclass) all_subclasses.extend(get_all_subclasses(subclass)) return all_subclasses # register all controller controllers = get_all_subclasses(Controller) for controller in controllers: controller.register(app) app.install(EnableCorsPlugin()) app.install(JSONRPCPlugin()) port = StateManager.getInstance().web_service.port app.run(host='0.0.0.0', port=port, debug=False)
def __init__(self): try: self.startup() self.state = StateManager(self.conf) self.loop = asyncio.get_event_loop() self.bpcon = BPConProtocol(self.conf, self.state) self.paxos_server = websockets.serve(self.bpcon.main_loop, self.conf['ip_addr'], self.conf['port'], ssl=self.conf['ssl']) self.loop.run_until_complete(self.paxos_server) log.info("Started BPCon on port {}".format(self.conf['port'])) if self.conf['is_client']: log.debug("is client. making test requests") for x in range(1): self.commit("P,{},hello{}".format(x,x)) self.commit("P,test,value") self.commit("P,test{},value{}".format(x,x)) self.commit("P,test2,value2") self.commit("P,test,value3") self.commit("D,test2,") log.debug("requests complete") except Exception as e: log.info(e)
class BPConDemo: def __init__(self): try: self.startup() self.state = StateManager(self.conf) self.loop = asyncio.get_event_loop() self.bpcon = BPConProtocol(self.conf, self.state) self.paxos_server = websockets.serve(self.bpcon.main_loop, self.conf['ip_addr'], self.conf['port'], ssl=self.conf['ssl']) self.loop.run_until_complete(self.paxos_server) log.info("Started BPCon on port {}".format(self.conf['port'])) if self.conf['is_client']: log.debug("is client. making test requests") for x in range(1): self.commit("P,{},hello{}".format(x,x)) self.commit("P,test,value") self.commit("P,test{},value{}".format(x,x)) self.commit("P,test2,value2") self.commit("P,test,value3") self.commit("D,test2,") log.debug("requests complete") except Exception as e: log.info(e) def commit(self,msg): self.loop.run_until_complete(self.bpcon_request(msg)) def got_commit_result(self, future): if future.done(): if not future.cancelled(): self.log.info("commit result: {}".format(future.result())) else: self.log.info("future cancelled") else: self.log.info("future not done") @asyncio.coroutine def bpcon_request(self, msg): log.debug("making request: {}".format(msg)) bpcon_task = asyncio.Future() bpcon_task.add_done_callback(self.got_commit_result) try: timer_result = asyncio.wait_for(bpcon_task, 3.0) # timer possibly unneccessary commit_result = yield from self.bpcon.request(msg, bpcon_task) # returns boolean log.info("bpcon request result: {}".format(commit_result)) return commit_result except asyncio.TimeoutError: log.info("bpcon commit timed out") except asyncio.CancelledError: log.info("bpcon commit future cancelled") except Exception as e: log.debug(e) def startup(self): """ startup routine Loads from cloned state """ # clean working dir and extract config, creds, and state log.info("Cleaning working directory...") command = "rm config.ini && rm -rf data && rm -rf creds" shell(command) log.info("Extracting cloned state...") command = "tar xzf clone.tar.gz" shell(command) # load config log.info("Loading configuration...") self.cm = ConfigManager() self.conf = self.cm.load_config(configFile) # load state log.info("Loading state...") self.state = StateManager(self.conf) self.state.load_state() """ def clone(self): #create a copy of db, peers, peer creds, and config #save to compressed archive #used to add new nodes to system try: self.state.image_state() self.cm.save_config() backupdir = "data/" cfile = "config.ini" command = "tar czf clone.tar.gz {} {} creds/".format(cfile,backupdir) shell(command) log.info("clone of state successfully created") except Exception as e: log.info("clone of state failed") def handle_reconfig_request(self, epoch=0): toreturn = self.bpcon.bmsgs if epoch != 0: self.clone() with open('clone.tar.gz', 'r') as fh: toreturn += "<>{}".format(fh.read()) log.debug("cloned state added successfully") return toreturn def make_reconfig_request(self, wss): # epoch = current epoch pass """ def shutdown(self): print("\nShutdown initiated...") print("\nDatabase contents:\n{}".format(self.bpcon.state.db.kvstore)) # save state here self.paxos_server.close()
message: Message = update.message poll_id = int(groups[0]) poll = Poll.load(poll_id) if poll.owner.id == message.from_user.id: send_admin_poll(message, poll) ############################################################################### # conversation: create new poll ############################################################################### QUESTION, FIRST_ANSWER, ANSWERS, = range(3) states = StateManager() def start(bot: Bot, update: Update) -> int: query: CallbackQuery = update.callback_query message: Message = update.message if query is not None: user = query.from_user query.answer() elif message is not None: user = message.from_user else: raise TypeError("unexpected type of update") bot.send_message(
def show_dialog(self): StateManager.getInstance().show_dialog()
class Client: cursor_default = None cursor_capture = None def __init__(self, resolution, host, port, username, password, split="\n"): global network_log self.log = Log('client') network_log = Log('network') # must have at least one handler self.log.logger.addHandler(logging.NullHandler()) network_log.logger.addHandler(logging.NullHandler()) # opengl must be initialized first self.log.info("Initializing display (windowed at %(resolution)s)", dict(resolution='%dx%d' % resolution)) self._screen = pygame.display.set_mode(resolution, OPENGL | DOUBLEBUF) pygame.display.set_caption('yamosg') self.log.debug( "OpenGL setup (version=\"%(version)s\", vendor=\"%(vendor)s\")", dict(version=glGetString(GL_VERSION), vendor=glGetString(GL_VENDOR))) setup_opengl() Client.cursor_default = pygame.cursors.arrow Client.cursor_capture = pygame.cursors.diamond self._resolution = Vector2i(resolution) self._username = username self._password = password self._split = split self._running = False self._state = StateManager() self._game = GameWidget(self, self._resolution) self._container = Composite(Vector2i(0, 0), self._resolution, children=[self._game]) self._toolbar = Toolbar(self._game) self._window = VBox() self._window.add(self._toolbar, size=LayoutAttachment(Vector2i(1, 0), Vector2i(0, 25))) self._window.add(self._container) self._state.push(GameState(self._resolution, self._window)) self._network = Network(self, host, port) self._command_store = {} self._command_queue = [] self._command_lock = threading.Lock() self._playerid = None self._players = {} self._capture_position = None self._timer = 0 # resizing must be done after state has been created so the event is propagated proper. self._resize(self._resolution) def add_window(self, win): self._container.add(win) @event(pygame.QUIT) def quit(self, event=None): self._running = False def is_running(self): return self._running def resolution(self): return self._resolution def run(self): self._running = True self._network.start() while self._running: try: self._flush_queue() self._logic() self._render() except GLError: traceback.print_exc() self.quit() except: traceback.print_exc() @event(pygame.VIDEORESIZE, lambda event: Vector2i(event.w, event.h)) def _resize(self, resolution): self.log.debug("Resolution changed to %dx%d", resolution.x, resolution.y) #self._screen = pygame.display.set_mode(resolution.xy(), OPENGL|DOUBLEBUF|RESIZABLE) setup_opengl() self._resolution = resolution glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, resolution.x, 0, resolution.y, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self._state.resize(resolution) self._game.on_resize(resolution, True) def _flush_queue(self): while True: self._command_lock.acquire() if len(self._command_queue) == 0: self._command_lock.release() break command, args = self._command_queue.pop(0) self._command_lock.release() try: self._dispatch(command, args) except: traceback.print_exc() def _logic(self): global event_table for event in pygame.event.get(): func, adapter = event_table.get(event.type, (None, None)) if func is None: continue func(self, adapter(event)) t = time() if t - self._timer > 1.0: self._toolbar.invalidate() self._timer = t @event(pygame.MOUSEMOTION) def _mousemotion(self, event): pos = Vector2i(event.pos) pos.y = self._resolution.y - pos.y self._state.on_mousemove(pos) @event(pygame.MOUSEBUTTONDOWN) def _mousebuttondown(self, event): pos = Vector2i(event.pos) pos.y = self._resolution.y - pos.y if self._capture_position is not None: if event.button == 1: callback, args, kwargs = self._capture_position try: callback(pos, *args, **kwargs) except: traceback.print_exc() self._capture_position = None pygame.mouse.set_cursor(*Client.cursor_default) return self._state.on_buttondown(pos, event.button) @event(pygame.MOUSEBUTTONUP) def _mousebuttonup(self, event): pos = Vector2i(event.pos) pos.y = self._resolution.y - pos.y self._state.on_buttonup(pos, event.button) def _render(self): glClearColor(1, 0, 0, 0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self._state.render() pygame.display.flip() def _dispatch(self, cmd, args): """ Run command """ global network_log network_log.debug('got %s(%s)', cmd, ', '.join([str(x) for x in args])) try: # Try to get function func = getattr(self, cmd) # See if it is exposed, so a malicious cannot run any func. if not getattr(func, 'exposed'): raise AttributeError # raised to get same handling as a non-existing func. except AttributeError: print 'Malformed or bad command:', cmd, args return except: print 'Unhandled exception when running command:', cmd, args traceback.print_exc() return func(*args) def push_command(self, line): # Run from network thread try: self._command_lock.acquire() tokens = parse_tokens(line) id = tokens[0] if id == 'UNICAST' or id == 'BROADCAST': id, command, args = parse(line) self._command_queue.append((command, args)) elif id in self._command_store: status = tokens[1] args = tuple(tokens[2:]) data = line[len(id) + len(status) + 2:] self._command_store[id].reply(status, args, data) else: raise RuntimeError, 'Got a reply for ID ' + id + ' but no matching request' except: traceback.print_exc() finally: self._command_lock.release() def call(self, command, *args): """ Synchronously call and get reply """ cmd = Command(command, *args) # send command with self._command_lock: self._command_store[cmd.id] = cmd self._network.send(str(cmd) + self._split) # await reply reply = cmd.wait() # delete command with self._command_lock: del self._command_store[cmd.id] return reply @server_call('LIST_OF_ENTITIES', decode=True) def list_of_entities(self, descriptions): self._game.set_entities([Entity(**x) for x in descriptions]) @expose def NEWENT(self, data): decoded = json.loads(data) self._game.add_entity(Entity(**decoded)) @server_call('ENTINFO', 'id', decode=True) def entity_info(self, info): return info @server_call('ENTACTION', 'id', 'action', decode=True) def entity_action(self, info): return info @server_call('PLAYERINFO', 'id', decode=True) def playerinfo(self, info): self._toolbar.set_cash(info['cash']) @expose def CASH(self, amount): self._toolbar.set_cash(int(amount)) @server_call('LOGIN', 'username', 'password', decode=True) def login(self, info): self.playerid = info['id'] self.log.debug('player id is %s', self.playerid) self.playerinfo(self.playerid) @server_call('PLAYERS', decode=True) def players(self, players): return players def player_by_id(self, id): return self._players.get(unicode(id), None) @expose def Hello(self): self.call('SET', 'ENCODER', 'json') try: self.login(username=self._username, password=self._password) except RuntimeError, e: self.log.error(e) self.quit() return self._players = self.players() self.list_of_entities()
def __init__(self, from_user_name, to_user_name, **kwargs): self.to_user_name = to_user_name self.from_user_name = from_user_name self.state = StateManager.get_user_state(from_user_name, to_user_name)
class TableauStatusMonitor(threading.Thread): # pylint: disable=too-many-instance-attributes # Note: If there is a value in the system table, it is # used instead of these defaults. # Default interval for checking tableau status (in seconds) STATUS_REQUEST_INTERVAL_DEFAULT = 30 # Minimum amount of time that must elapse while DEGRADED # before sending out the DEGRADED event. EVENT_DEGRADED_MIN_DEFAULT = 120 # in seconds # Possible return values when attempting to get systeminfo: # Only considered a failure if the http get of the URL # can't accept a connection. Otherwise, Tableau could be up. SYSTEMINFO_SUCCESS = 1 SYSTEMINFO_FAIL = 2 # Remember the url that worked with systeminfo to help determine # if tableau is really stopped when systeminfo fails. systeminfo_url_worked = None statemap = { TableauProcess.STATUS_RUNNING: StateManager.STATE_STARTED, TableauProcess.STATUS_STOPPED: StateManager.STATE_STOPPED, TableauProcess.STATUS_DEGRADED: StateManager.STATE_DEGRADED, TableauProcess.STATUS_UNKNOWN: StateManager.STATE_DISCONNECTED } def __init__(self, server, manager): super(TableauStatusMonitor, self).__init__() self.server = server self.system = server.system self.event = self.server.event_control self.rwlock = self.server.upgrade_rwlock self.manager = manager # AgentManager instance self.envid = self.server.environment.envid self.first_degraded_time = None self.sent_degraded_event = False logger.setLevel(self.system[SystemKeys.DEBUG_LEVEL]) # Start fresh: status table session = meta.Session() self.remove_all_status() session.commit() self.stateman = StateManager(self.server) # Remove all entries to get ready for new status info. def remove_all_status(self): """ Note a session is passed. When updating the status table, we don't want everything to go away (commit) until we've added the new entries. """ # FIXME: Need to figure out how to do this in session.query: # DELETE FROM status USING agent # WHERE status.agentid = agent.agentid # AND agent.domainid = self.domainid; # # This may do it: # # subq = session.query(TableauProcess).\ # join(Agent).\ # filter(Agent.domainid == self.domainid).\ # subquery() # # session.query(TableauProcess).\ # filter(TableauProcess.agentid,in_(subq)).\ # delete() meta.Session.query(TableauProcess).delete() # Intentionally don't commit here. We want the existing # rows to be available until the new rows are inserted and # committed. def _add(self, agentid, name, pid, status): """Note a session is passed. When updating the status table, we do remove_all_status, then slowly add in the new status before doing the commit, so the table is not every empty/building if somebody checks it. """ session = meta.Session() entry = TableauProcess(agentid=agentid, name=name, pid=pid, status=status) # We merge instead of add since 'tabadmin status -v' sometimes # returns duplicate lines. session.merge(entry) def get_tableau_status(self): try: return meta.Session().query(TableauProcess).\ join(Agent).\ filter(Agent.envid == self.envid).\ filter(Agent.agent_type == 'primary').\ filter(TableauProcess.name == 'Status').\ one().status except NoResultFound: return TableauProcess.STATUS_UNKNOWN def _set_main_state(self, prev_tableau_status, tableau_status, agent, body): prev_state = self.stateman.get_state() if tableau_status not in (TableauProcess.STATUS_RUNNING, TableauProcess.STATUS_STOPPED, TableauProcess.STATUS_DEGRADED): logger.error("status-check: Unknown reported tableau_status " + \ "from tableau: %s. prev_state: %s", tableau_status, prev_state) return # fixme: do something more drastic than return? if prev_state not in TRANSITIONS: logger.error("status-check: prev state unexpected: %s", prev_state) return # fixme: do something more drastic than return? # Get our new state and events to send based on the previous # state and new tableau status. new_state_info = TRANSITIONS[prev_state][tableau_status] # Special case (fixme) if prev_state == StateManager.STATE_STARTING_RESTORE: tversion = YmlEntry.get(self.envid, 'version.external', default='8') if tversion[0:1] == '8' and (tversion[1:4] == '.0.' or \ tversion[1:4] == '.1.'): # For pre 8.2, 'tabadmin restore' ends in RUNNING/STARTED # After 8.2 and v9, 'tabadmin restore' ends in STOPPED new_state_info = START_DICT logger.debug("status-check: prev_state: %s, new state info: %s, " + \ "prev_tableau_status %s, tableau_status: %s", prev_state, str(new_state_info), prev_tableau_status, tableau_status) if 'state' in new_state_info and \ new_state_info['state'] != prev_state: self.stateman.update(new_state_info['state']) if 'events' not in new_state_info: events = [] else: events = new_state_info['events'] if type(events) == type(EventControl.INIT_STATE_STARTED): events = [events] self._send_events(events, agent, body) if 'maint-stop' in new_state_info: # Make sure the maint server(s) are stopped if tableau # is not stopped. For example, the user stopped # tableau via 'tabadmin stop' and then restarted it with # 'tabadmin start' without going through the Palette UI. logger.debug("status-check: May stop maint server. " + \ "prev_state: %s, new state info: %s, " + \ "prev_tableau_status %s, tableau_status: %s, " + \ "maint_started: %s", prev_state, str(new_state_info), prev_tableau_status, tableau_status, str(self.server.maint_started)) if not self.server.maint_started: logger.debug("state-check: maint server not running") return self.server.maint("stop") if 'maint-start' in new_state_info: # Make sure the maint server(s) are started if tableau # is stopped. For example, the user stopped # tableau via 'tabadmin stop' and then the controller # started at that point (small chance, but possible). # We want to set the maint_started status. # We assume the user wanted the maint server started, # but can't be sure. logger.debug("status-check: Will start maint server. " + \ "prev_state: %s, new state info: %s, " + \ "prev_tableau_status %s, tableau_status: %s, " + \ "maint_started: %s", prev_state, str(new_state_info), prev_tableau_status, tableau_status, str(self.server.maint_started)) if self.server.maint_started: logger.debug("state-check: maint server already running") return self.server.maint("start") def _send_events(self, events, agent, body): """Send the events according to the old and new states. However, don't send DEGRADED-related events until Tableau has a chance to recover, since that's what it does.""" if events: data = agent.todict() new_degraded_event = False for event in events: if event == EventControl.STATE_STARTED_AFTER_DEGRADED and \ not self.sent_degraded_event: # We were degraded, and are running now, but never # sent out a degraded event, so don't send a # "no more degraded" event either. continue if event != EventControl.STATE_DEGRADED: self.event.gen(event, data) if event == EventControl.INIT_STATE_DEGRADED: # If this is an "INIT_STATE_*" event, we send it, # even if it is degraded. self.sent_degraded_event = False continue new_degraded_event = True # Don't send the DEGRADED event until a minimum period of time # has elapsed with the state still DEGRADED. if not self.first_degraded_time: # Remember the time of the first DEGRADED state. self.first_degraded_time = time.time() continue if self.sent_degraded_event: # Already sent the degraded event continue try: event_degraded_min = self.system[SystemKeys.EVENT_DEGRADED_MIN] except ValueError: event_degraded_min = self.EVENT_DEGRADED_MIN_DEFAULT now = time.time() logger.debug("status-check: now %d, first %d, min %d, diff %d", now, self.first_degraded_time, event_degraded_min, now - self.first_degraded_time) if now - self.first_degraded_time >= event_degraded_min: logger.debug("status-check: Sending degraded") # TODO: check if this fix for exceptions thrown when # line 974 gives us a None body body_items = [] if body is None else body.items() self.event.gen(event, dict(body_items + data.items())) self.sent_degraded_event = True if not new_degraded_event: self.first_degraded_time = None self.sent_degraded_event = False def run(self): try: self.tableau_status_loop() except (SystemExit, KeyboardInterrupt, GeneratorExit): raise except BaseException: line = traceback_string(all_on_one_line=False) edata = {'error': line, 'version': self.server.version} self.event.gen(EventControl.SYSTEM_EXCEPTION, edata) logger.error("status-check: Fatal: " + \ "Exiting tableau_status_loop on exception.") # pylint: disable=protected-access os._exit(93) def tableau_status_loop(self): while True: logger.debug("status-check: About to timeout or " + \ "wait for a new primary to connect") try: system_key = SystemKeys.STATUS_REQUEST_INTERVAL request_interval = self.system[system_key] except ValueError: request_interval = self.STATUS_REQUEST_INTERVAL_DEFAULT new_primary = self.manager.check_status_event.wait(request_interval) logger.debug("status-check: new_primary: %s", new_primary) if new_primary: self.manager.clear_check_status_event() session = meta.Session() try: # Don't do a 'tabadmin status -v' if upgrading acquired = self.rwlock.read_acquire(blocking=False) if not acquired: logger.debug("status-check: Upgrading. Won't run.") continue self.check_status() finally: if acquired: self.rwlock.read_release() session.rollback() meta.Session.remove() def check_status(self): logger.setLevel(self.system[SystemKeys.DEBUG_LEVEL]) # FIXME: Tie agent to domain. agent = self.manager.agent_by_type(AgentManager.AGENT_TYPE_PRIMARY) if not agent: logger.debug("status-check: The primary agent is either " + \ "not connected or not enabled.") return aconn = agent.connection if not aconn: session = meta.Session() logger.debug("status-check: No primary agent currently connected.") self.remove_all_status() session.commit() return # Don't do a 'tabadmin status -v' if the user is doing an action. acquired = aconn.user_action_lock(blocking=False) if not acquired: logger.debug("status-check: Primary agent locked for user " "action. Skipping status check.") return # We don't force the user to delay starting their request # until the 'tabadmin status -v' is finished. aconn.user_action_unlock() self.check_status_with_connection(agent) def _systeminfo_parse(self, agent, systeminfo_xml): # pylint: disable=too-many-return-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=too-many-statements """Returns: SYSTEMINFO_SUCCESS if getting status via systeminfo is fine. Raises an exception if there is a problem with systeminfo. """ logger.debug("_systeminfo_parse: Received: %s", systeminfo_xml) try: root = ET.fromstring(systeminfo_xml) except ET.ParseError as ex: logger.error("_systeminfo_parse: xml parse error: '%s' from '%s':", str(ex), systeminfo_xml) raise SysteminfoException(SysteminfoError.PARSE_FAILURE, "xml parse error: '%s'" % (str(ex))) if root.tag != 'systeminfo': logger.error("_systeminfo_parse: wrong root tag: %s", root.tag) raise SysteminfoException(SysteminfoError.PARSE_FAILURE, "wrong root tag: %s" % root.tag) session = meta.Session() prev_tableau_status = self.get_tableau_status() self.remove_all_status() tableau_status = None failed_proc_str = "" for child in root: if child.tag == 'machines': for machine in child: # print "machine:", machine.attrib if not 'name' in machine.attrib: logger.error("_systeminfo_parse: missing " + \ "'name' in machine attribute: %s", str(machine.attrib)) raise SysteminfoException(SysteminfoError.PARSE_FAILURE, ("missing " + \ "'name' in machine attribute: %s") % \ str(machine.attrib)) host = machine.attrib['name'] agentid = Agent.get_agentid_from_host(self.envid, host) if not agentid: logger.error("_systeminfo_parse: No such" + \ " agent host known (yet/any more?): %s", host) continue machine_agent = Agent.get_by_id(agentid) if machine_agent: machine_displayname = machine_agent.displayname else: machine_displayname = "Unknown" for info in machine: #print " ", info.tag, "attributes:", info.attrib service_name = info.tag if not 'status' in info.attrib: logger.error("_systeminfo_parse: missing " + \ "'status' in machine %s attrib: %s", host, str(info.attrib)) raise SysteminfoException( SysteminfoError.PARSE_FAILURE, ("missing " + \ "'status' in machine %s attrib: %s") % \ (host, str(info.attrib))) if 'worker' in info.attrib: worker_info = info.attrib['worker'] parts = worker_info.split(':') if len(parts) == 1 or not parts[1].isdigit(): # port = -2 logger.error("_systeminfo_parse: missing " + \ "':' or not an integer in " "machine %s for " + \ "worker: %s", host, str(worker_info)) raise SysteminfoException( SysteminfoError.PARSE_FAILURE, ("Missing " + \ "':' or not an integer in " "machine %s for " + \ "worker: %s") % \ (host, str(worker_info))) else: port = int(parts[1]) service_status = info.attrib['status'] # print "service_name:", service_name, "port", port if service_status not in ('Active', 'Passive', 'Busy', 'ReadOnly', 'ActiveSyncing'): # Keep track of failed tableau processes failed_proc_str += ("Machine %s: Process %s is " "%s\n") % \ (machine_displayname, service_name, service_status) self._add(agentid, service_name, port, service_status) logger.debug("system_info_parse: logged: " + \ "%d, %s, %d, %s", agentid, service_name, port, service_status) elif child.tag == 'service': # print "service:", info = child.attrib if not 'status' in info: logger.error("_systeminfo_parse: Missing 'status': %s", str(info)) raise SysteminfoException(SysteminfoError.PARSE_FAILURE, "Missing 'status': %s" % \ str(info)) #print " status:", info['status'] tableau_status = info['status'] if tableau_status in ('Down', 'DecommisionedReadOnly', 'DecomisioningReadOnly', 'DecommissionFailedReadOnly'): tableau_status = TableauProcess.STATUS_DEGRADED elif tableau_status in ('Active', 'Passive', 'Busy', 'ReadOnly', 'ActiveSyncing'): tableau_status = TableauProcess.STATUS_RUNNING elif tableau_status in ('StatusNotAvailable', 'StatusNotAvailableSyncing'): tableau_status = TableauProcess.STATUS_UNKNOWN else: logger.error("_systeminfo_parse: Unexpected status: '%s'", tableau_status) tableau_status = TableauProcess.STATUS_UNKNOWN # Note: The status can never be STOPPED since if Tableau # is stopped, then it won't respond to the systeminfo # GET URL. self._add(agent.agentid, "Status", 0, tableau_status) else: logger.error("_systeminfo_parse: Unexpected child.tag: '%s'", child.tag) if tableau_status is None: logger.error("_systeminfo_parse: Tableau status not valid: %s", str(systeminfo_xml)) session.rollback() raise SysteminfoException(SysteminfoError.PARSE_FAILURE, "Tableau status not valid") if failed_proc_str: # Failed process(es) for the event body = {'info': failed_proc_str} else: body = None self._finish_status(agent, tableau_status, prev_tableau_status, body) return self.SYSTEMINFO_SUCCESS def _systeminfo_url(self): """For now, start with the tableau-server-url, and replace the hostname with 127.0.0.1. Eventually we need to look at the yml, gateway.hosts, ssl.enabled, gateway.ports, and decided both the URL and which host should request systeminfo. (The gateway/web server may not be on the primary.) Returns None if no valid url is available. """ systeminfo_url = self.system[SystemKeys.TABLEAU_INTERNAL_SERVER_URL] if not systeminfo_url: systeminfo_url = self.system[SystemKeys.TABLEAU_SERVER_URL] if not systeminfo_url: logger.error("_systeminfo_get: no url configured.") return None result = urlparse(systeminfo_url) if not result.scheme: logger.error("_systeminfo_get: Bad url: %s", systeminfo_url) return None if result.port: url = "%s://127.0.0.1:%d/admin/systeminfo.xml" % \ (result.scheme, result.port) else: url = "%s://127.0.0.1/admin/systeminfo.xml" % (result.scheme) return url def _systeminfo_get(self, agent): # pylint: disable=too-many-return-statements """Returns: - The xml on success Raises SysteminfoException on error. """ url = self._systeminfo_url() timeout_ms = self.system[SystemKeys.STATUS_SYSTEMINFO_TIMEOUT_MS] try: res = agent.connection.http_send_get(url, timeout=timeout_ms) except (socket.error, IOError, exc.HTTPException, httplib.HTTPException) as ex: logger.info("_systeminfo_get %s failed: %s", url, str(ex)) raise SysteminfoException(SysteminfoError.COMM_FAILURE, "_systeminfo_get %s failed: %s" % \ (url, str(ex))) content_type = res.getheader('Content-Type', '').lower() logger.info("GET %s, Headers: '%s'", url, str(res.getheaders())) if content_type == 'application/x-json': # This extended type indicates the agent generated the JSON, # i.e. there was an error. try: data = json.loads(res.body) except ValueError as ex: logger.error("_systeminfo_get: Bad json returned for %s: %s", url, res.body) raise SysteminfoException(SysteminfoError.JSON_PARSE_FAILURE, "Invalid json returned for %s: %s" % \ (url, res.body)) logger.info("_systeminfo_get: get %s reported failed: %s", url, data) if 'error' in data: if data['error'].find( "Unable to connect to the remote server") != -1: # We had the tableau URL and it wasn't answering. # Tableau is probably down, though could be the # wrong URL/port. raise SysteminfoException(SysteminfoError.CONNECT_FAILURE, ("HTTP GET %s reported failed: %s") % \ (url, data['error'])) if data['error'].find('The operation has timed out') != -1: msgfmt = "HTTP GET Timed out after %.1f seconds on %s" raise SysteminfoException(SysteminfoError.COMM_TIMEDOUT, msgfmt % (timeout_ms/1000., url)) if 'status-code' in data and data['status-code'] == 404: raise SysteminfoException(SysteminfoError.NOT_FOUND, "Page not found: %s" % (url)) msg = "Unexpected response error: %s" % str(data) raise SysteminfoException(SysteminfoError.UNEXPECTED_RESPONSE, msg) return res.body def _set_status_stopped(self, agent): """systeminfo is enabled in tableau, so if it is failing now, assume tableau is stopped.""" prev_tableau_status = self.get_tableau_status() self.remove_all_status() name = "Status" pid = 0 tableau_status = TableauProcess.STATUS_STOPPED self._add(agent.agentid, name, 0, tableau_status) logger.debug("_set_status_stopped: logged: %s, %d, %s", name, pid, tableau_status) self._finish_status(agent, tableau_status, prev_tableau_status, {'stdout': 'systeminfo failed. Assuming Tableau is stopped.'}) def _tableau_systeminfo_enabled(self): """Returns: True: The Tableau configuration has systeminfo enabled. False: The Tableau configuration for systeminfo is disabled.""" yml_val = self.server.yml.get( 'wgserver.systeminfo.allow_referrer_ips', default='') if yml_val.find('127.0.0.1') != -1 or yml_val.find('localhost') != -1: return True return False def check_status_with_connection(self, agent): tableau_systeminfo_enabled = self._tableau_systeminfo_enabled() data = {} systeminfo_url = self._systeminfo_url() tableau_version = YmlEntry.get(self.envid, 'version.external', default='8') systeminfo_api_capable = self.is_systeminfo_api_capable(tableau_version) if systeminfo_url and systeminfo_api_capable and \ self.system[SystemKeys.STATUS_SYSTEMINFO] and \ tableau_systeminfo_enabled: try: # Returns the xml on success xml_result = self._systeminfo_get(agent) # Remember this URL worked self.systeminfo_url_worked = systeminfo_url self._systeminfo_parse(agent, xml_result) # parse the xml # Send an event if appropriate self._systeminfo_eventit(agent, data, systeminfo_url) return except SysteminfoException as ex: prev_state = self.stateman.get_state() if ex.errnum == SysteminfoError.NOT_FOUND and \ self.systeminfo_url_worked == systeminfo_url and \ prev_state in (StateManager.STATE_STOPPED, StateManager.STATE_STOPPING): # Could be the maintenance web server responding with # "Not found" since and tableau is stopped. self._set_status_stopped(agent) logger.info("_system_info: Page not found and " "it previously worked, but the state was %s " "so not sending systeminfo event.", prev_state) return elif ex.errnum == SysteminfoError.CONNECT_FAILURE: logger.info("_system_info: failed to connect") # Be as confident as possible that tableau really is stopped # and the user didn't configure the tableau-server-url # wrong. The tableau-server-url derived url has to work # at least once with systeminfo # before the failure to # get systeminfo should mean that tableau is really stopped. if self.systeminfo_url_worked == systeminfo_url: logger.error("status-check: systeminfo failed while " "enabled in tableau: assuming tableu is " "stopped.") self._set_status_stopped(agent) data['info'] = "Systeminfo failed to connect, but " + \ "connect previously worked. " + \ "Assuming Tableau is stopped." self._systeminfo_eventit(agent, data, systeminfo_url) return # systeminfo didn't work, but we don't know if tableau # being down is the cause. The exception could be due to # a parse error, bad url, timeout, etc. data['error'] = ex.message if ex.errnum == SysteminfoError.PARSE_FAILURE: # Add the raw XML to the error. data['error'] += ' XML: ' + str(xml_result) self._systeminfo_eventit(agent, data, systeminfo_url) if self.system[SystemKeys.STATUS_SYSTEMINFO_ONLY]: logger.info("systeminfo failed but not allowed to use " "tabadmin status -v") self._set_status_unknown(agent, "systeminfo failed but configured to not " "allow use of tabadmin status -v") return # Get tableau status via 'tabadmin status -v' instead. self._get_status_tabadmin(agent) return def is_systeminfo_api_capable(self, tableau_version): """Check whether /admin/systeminfo.xml API is available for checking the status of Tableau processes""" try: tableau_major_ver = int(tableau_version.split(".")[0]) if tableau_major_ver >= 9: return True except ValueError: logger.error("Failed to parse major version number " "from Tableau version: '%s'", tableau_version) return False def _set_status_unknown(self, agent, body): """Remove all status and set tableau status to UNKNOWN.""" prev_tableau_status = self.get_tableau_status() self.remove_all_status() tableau_status = TableauProcess.STATUS_UNKNOWN self._add(agent.agentid, "Status", 0, tableau_status) self._finish_status(agent, tableau_status, prev_tableau_status, body) def _systeminfo_eventit(self, agent, data, systeminfo_url): """Send if event failed/okay event as appropriate.""" notification = self.server.notifications.get("systeminfo") if success(data): if notification.color == 'red': adata = agent.todict() if 'info' in data: adata['info'] = data['info'] if self.system[SystemKeys.STATUS_SYSTEMINFO_SEND_ALERTS]: self.event.gen(EventControl.SYSTEMINFO_OKAY, adata) notification.modification_time = func.now() notification.color = 'green' notification.description = systeminfo_url meta.Session.commit() else: # Failed if notification.color != 'red' or \ notification.description != systeminfo_url: # If the systeminfo_url has changed, then tell them this # one didn't work (either). We can potentially send # multiple of these events if they keep entering bad # URLs. adata = agent.todict() adata['error'] = data['error'] if self.system[SystemKeys.STATUS_SYSTEMINFO_SEND_ALERTS]: self.event.gen(EventControl.SYSTEMINFO_FAILED, adata) notification.modification_time = func.now() notification.color = 'red' notification.description = systeminfo_url meta.Session.commit() def _get_status_tabadmin(self, agent): # pylint: disable=too-many-locals # pylint: disable=too-many-branches # pylint: disable=too-many-statements """Try to get tableau status the old-fashioned way via 'tabadmin status -v'. """ agentid = agent.agentid body = self.server.status_cmd(agent) if 'error' in body: logger.error("status-check: Error from tabadmin status command: %s", str(body)) return if 'exit-status' in body: if body['exit-status']: logger.error("status-check: Failed exit status: %d for " + \ "tabadmin status command: %s", body['exit-status'], str(body)) return else: logger.error("status-check: Missing exit-status from " + \ "tabadmin status command: %s", str(body)) return if not body.has_key('stdout'): # fixme: Probably update the status table to say # something's wrong. logger.error("status-check: No output received for " + \ "status monitor. body: " + str(body)) return stdout = body['stdout'] lines = string.split(stdout, '\n') session = meta.Session() prev_tableau_status = self.get_tableau_status() self.remove_all_status() # Do not commit until after the table is added to. # Otherwise, the table could be empty temporarily. tableau_status = None failed_proc_str = "" machine_agent = Agent.get_by_id(agentid) if machine_agent: machine_displayname = machine_agent.displayname else: machine_displayname = "Unknown" for line in lines: line = line.strip() parts = line.split(' ') # 'Tableau Server Repository Database' (1764) is running. if parts[0] == "'Tableau" and parts[1] == 'Server': if agentid: pattern = r"'Tableau Server (?P<service>.*)'" + \ r"\s(\((?P<pid>[0-9]*)\))?(status)?\s?" + \ r"is\s(?P<status>.*)\." match = re.search(pattern, line) if not match: logger.debug("status-check: unmatched line: " + line) continue service = match.group('service') # "Repository" if not 'service': logger.debug("status-check: empty service in " + \ "line: %s", line) continue pid_str = match.group('pid') # "1764" if pid_str: try: pid = int(pid_str) except StandardError: logger.error("status-check: Bad PID: " + pid_str) continue else: pid = -2 status = match.group('status') # "running" or "running..." if not 'status': logger.debug("status-check: empty 'status' " + \ "in line: %s", line) continue self._add(agentid, service, pid, status) logger.debug("status-check: logged: %s, %d, %s", service, pid, status) if status.find('running') == -1: # Keep track of failed tableau processes failed_proc_str += ("Machine %s: Process %s is " "%s\n") % \ (machine_displayname, service, status) else: # FIXME: log error pass elif parts[0] == 'Status:': server_status = parts[1].strip() if agentid: self._add(agentid, "Status", 0, server_status) if tableau_status == None or server_status == 'DEGRADED': tableau_status = server_status else: # FIXME: log error pass else: line = line.strip() if line[-1:] == ':': # A hostname or IP address is specified: new section host = parts[0].strip().replace(':', '') agentid = Agent.get_agentid_from_host(self.envid, host) machine_agent = Agent.get_by_id(agentid) if machine_agent: machine_displayname = machine_agent.displayname else: machine_displayname = "Unknown" else: # Examples: # "Connection error contacting worker 1" # 'Tableau Server Cluster Controller' is stopped. # 'Tableau Server Repository' status is not available. # 'Tableau Server File Store' status is not available. if not agentid: logger.debug("status-check: Can't log due to " + \ "unknown or disabled agent: %s, %d, %s", line, -1, 'error') else: self._add(agentid, line, -1, 'error') logger.debug("status-check: logged: %s, %d, %s", line, -1, 'error') if tableau_status is None: logger.error("status-check: Tableau status not valid: %s", str(lines)) session.rollback() return if failed_proc_str: # Failed process(es) for the event body['info'] = failed_proc_str self._finish_status(agent, tableau_status, prev_tableau_status, body) def _finish_status(self, agent, tableau_status, prev_tableau_status, body): aconn = agent.connection acquired = aconn.user_action_lock(blocking=False) if not acquired: # If the user_action_lock is taken, that thread should # control the state. We don't update the tableau process # table since state should be consistent with tableau process # status. logger.debug( "status-check: Primary agent locked for user action " + \ "after tabadmin status finished. " + \ "Will not update state or tableau status.") meta.Session.rollback() return logger.debug("status-check: Logging main status: %s", tableau_status) self._set_main_state(prev_tableau_status, tableau_status, agent, body) meta.Session.commit() aconn.user_action_unlock()
class Client: cursor_default = None cursor_capture = None def __init__(self, resolution, host, port, username, password, split="\n"): global network_log self.log = Log('client') network_log = Log('network') # must have at least one handler self.log.logger.addHandler(logging.NullHandler()) network_log.logger.addHandler(logging.NullHandler()) # opengl must be initialized first self.log.info("Initializing display (windowed at %(resolution)s)", dict(resolution='%dx%d'%resolution)) self._screen = pygame.display.set_mode(resolution, OPENGL|DOUBLEBUF) pygame.display.set_caption('yamosg') self.log.debug("OpenGL setup (version=\"%(version)s\", vendor=\"%(vendor)s\")", dict(version=glGetString(GL_VERSION), vendor=glGetString(GL_VENDOR))) setup_opengl() Client.cursor_default = pygame.cursors.arrow Client.cursor_capture = pygame.cursors.diamond self._resolution = Vector2i(resolution) self._username = username self._password = password self._split = split self._running = False self._state = StateManager() self._game = GameWidget(self, self._resolution) self._container = Composite(Vector2i(0,0), self._resolution, children=[self._game]) self._toolbar = Toolbar(self._game) self._window = VBox() self._window.add(self._toolbar, size=LayoutAttachment(Vector2i(1,0), Vector2i(0,25))) self._window.add(self._container) self._state.push(GameState(self._resolution, self._window)) self._network = Network(self, host, port) self._command_store = {} self._command_queue = [] self._command_lock = threading.Lock() self._playerid = None self._players = {} self._capture_position = None self._timer = 0 # resizing must be done after state has been created so the event is propagated proper. self._resize(self._resolution) def add_window(self, win): self._container.add(win) @event(pygame.QUIT) def quit(self, event=None): self._running = False def is_running(self): return self._running def resolution(self): return self._resolution def run(self): self._running = True self._network.start() while self._running: try: self._flush_queue() self._logic() self._render() except GLError: traceback.print_exc() self.quit() except: traceback.print_exc() @event(pygame.VIDEORESIZE, lambda event: Vector2i(event.w, event.h)) def _resize(self, resolution): self.log.debug("Resolution changed to %dx%d", resolution.x, resolution.y) #self._screen = pygame.display.set_mode(resolution.xy(), OPENGL|DOUBLEBUF|RESIZABLE) setup_opengl() self._resolution = resolution glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, resolution.x, 0, resolution.y, -1.0, 1.0); glMatrixMode(GL_MODELVIEW) glLoadIdentity() self._state.resize(resolution) self._game.on_resize(resolution, True) def _flush_queue(self): while True: self._command_lock.acquire() if len(self._command_queue) == 0: self._command_lock.release() break command, args = self._command_queue.pop(0) self._command_lock.release() try: self._dispatch(command, args) except: traceback.print_exc() def _logic(self): global event_table for event in pygame.event.get(): func, adapter = event_table.get(event.type, (None,None)) if func is None: continue func(self, adapter(event)) t = time() if t-self._timer > 1.0: self._toolbar.invalidate() self._timer = t @event(pygame.MOUSEMOTION) def _mousemotion(self, event): pos = Vector2i(event.pos) pos.y = self._resolution.y - pos.y self._state.on_mousemove(pos) @event(pygame.MOUSEBUTTONDOWN) def _mousebuttondown(self, event): pos = Vector2i(event.pos) pos.y = self._resolution.y - pos.y if self._capture_position is not None: if event.button == 1: callback, args, kwargs = self._capture_position try: callback(pos, *args, **kwargs) except: traceback.print_exc() self._capture_position = None pygame.mouse.set_cursor(*Client.cursor_default) return self._state.on_buttondown(pos, event.button) @event(pygame.MOUSEBUTTONUP) def _mousebuttonup(self, event): pos = Vector2i(event.pos) pos.y = self._resolution.y - pos.y self._state.on_buttonup(pos, event.button) def _render(self): glClearColor(1,0,0,0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self._state.render() pygame.display.flip() def _dispatch(self, cmd, args): """ Run command """ global network_log network_log.debug('got %s(%s)', cmd, ', '.join([str(x) for x in args])) try: # Try to get function func = getattr(self, cmd) # See if it is exposed, so a malicious cannot run any func. if not getattr(func, 'exposed'): raise AttributeError # raised to get same handling as a non-existing func. except AttributeError: print 'Malformed or bad command:', cmd, args return except: print 'Unhandled exception when running command:', cmd, args traceback.print_exc() return func(*args) def push_command(self, line): # Run from network thread try: self._command_lock.acquire() tokens = parse_tokens(line) id = tokens[0] if id == 'UNICAST' or id == 'BROADCAST': id, command, args = parse(line) self._command_queue.append((command, args)) elif id in self._command_store: status = tokens[1] args = tuple(tokens[2:]) data = line[len(id)+len(status)+2:] self._command_store[id].reply(status, args, data) else: raise RuntimeError, 'Got a reply for ID ' + id + ' but no matching request' except: traceback.print_exc() finally: self._command_lock.release() def call(self, command, *args): """ Synchronously call and get reply """ cmd = Command(command, *args) # send command with self._command_lock: self._command_store[cmd.id] = cmd self._network.send(str(cmd) + self._split) # await reply reply = cmd.wait() # delete command with self._command_lock: del self._command_store[cmd.id] return reply @server_call('LIST_OF_ENTITIES', decode=True) def list_of_entities(self, descriptions): self._game.set_entities([Entity(**x) for x in descriptions]) @expose def NEWENT(self, data): decoded = json.loads(data) self._game.add_entity(Entity(**decoded)) @server_call('ENTINFO', 'id', decode=True) def entity_info(self, info): return info @server_call('ENTACTION', 'id', 'action', decode=True) def entity_action(self, info): return info @server_call('PLAYERINFO', 'id', decode=True) def playerinfo(self, info): self._toolbar.set_cash(info['cash']) @expose def CASH(self, amount): self._toolbar.set_cash(int(amount)) @server_call('LOGIN', 'username', 'password', decode=True) def login(self, info): self.playerid = info['id'] self.log.debug('player id is %s', self.playerid) self.playerinfo(self.playerid) @server_call('PLAYERS', decode=True) def players(self, players): return players def player_by_id(self, id): return self._players.get(unicode(id), None) @expose def Hello(self): self.call('SET', 'ENCODER', 'json') try: self.login(username=self._username, password=self._password) except RuntimeError, e: self.log.error(e) self.quit() return self._players = self.players() self.list_of_entities()
import sfml as sf from state import StateManager from states.gamestate import GameState """ A card game prototype """ if __name__ == '__main__': window = sf.RenderWindow(sf.VideoMode(1920, 1080), "Card Game", sf.Style.FULLSCREEN) window.vertical_synchronization = True clock = sf.Clock() sm = StateManager() sm.add_state("game", GameState, True) while window.is_open: dt = clock.restart().seconds state = sm.get() for event in window.events: state.handle_event(event) if type(event) == sf.CloseEvent: window.close() state.tick(dt) window.clear() state.draw(window) window.display()
def set_state(self, state="index", meta={}): self.state = StateManager.get_state(self.from_user_name, self.to_user_name, state, meta) StateManager.set_user_state(self.to_user_name, state, meta)
import http.server import socketserver from http import HTTPStatus import numpy as np import torch import json import os import time from state import StateManager, follow PORT = 3000 stateManager = StateManager() #make node id's in order n1,n2... #initialize all nodes (before every routine or seperately) (make initialization codeblock) #synth code and wrap with function #return immediately in rec when no parameters def toggle(ar): ar[0] = not ar[0] return ar[0] envi = {} class MyHandler(http.server.SimpleHTTPRequestHandler): #only works in python 3.7 #def __init__(self, *args): #http.server.SimpleHTTPRequestHandler.__init__(self, *args, directory='/frontend/')
'MOVE_BACKWARD': 2, 'TURN_RIGHT': 3, 'TURN_LEFT': 4, 'CLOSE': 5, #Close flippers 'GRAB': 6, #Close Claw 'STORE': 7, #pick up and ... } #========== MAIN ================================================== if __name__ == '__main__': ''' Logic for RasbPi goes here ''' #========== Connect Arduinos ============================== #Initialize State core = StateManager() num_devices = 2 path = "/dev/" devices = ['ttyACM0', 'ttyACM1', 'ttyACM2'] #potential device names if os.name == "nt": #If os is windows path is empty path = "" devices = ["COM3", "COM4"] #Initialize Serial Information//Attach Arduinos while len(core.added_devices) < num_devices: #until all devices are loaded time.sleep(.25) for device_name in devices: if device_name not in core.added_devices.values(): print('Attemping to connect to ' + device_name + '...')
class BPConDemo: def __init__(self): try: self.startup() self.state = StateManager(self.conf) self.loop = asyncio.get_event_loop() self.bpcon = BPConProtocol(self.conf, self.state) self.paxos_server = websockets.serve(self.bpcon.main_loop, self.conf['ip_addr'], self.conf['port'], ssl=self.conf['ssl']) self.loop.run_until_complete(self.paxos_server) log.info("Started BPCon on port {}".format(self.conf['port'])) if self.conf['is_client']: log.debug("is client. making test requests") for x in range(1): self.commit("P,{},hello{}".format(x, x)) self.commit("P,test,value") self.commit("P,test{},value{}".format(x, x)) self.commit("P,test2,value2") self.commit("P,test,value3") self.commit("D,test2,") log.debug("requests complete") except Exception as e: log.info(e) def commit(self, msg): self.loop.run_until_complete(self.bpcon_request(msg)) def got_commit_result(self, future): if future.done(): if not future.cancelled(): self.log.info("commit result: {}".format(future.result())) else: self.log.info("future cancelled") else: self.log.info("future not done") @asyncio.coroutine def bpcon_request(self, msg): log.debug("making request: {}".format(msg)) bpcon_task = asyncio.Future() bpcon_task.add_done_callback(self.got_commit_result) try: timer_result = asyncio.wait_for(bpcon_task, 3.0) # timer possibly unneccessary commit_result = yield from self.bpcon.request( msg, bpcon_task) # returns boolean log.info("bpcon request result: {}".format(commit_result)) return commit_result except asyncio.TimeoutError: log.info("bpcon commit timed out") except asyncio.CancelledError: log.info("bpcon commit future cancelled") except Exception as e: log.debug(e) def startup(self): """ startup routine Loads from cloned state """ # clean working dir and extract config, creds, and state log.info("Cleaning working directory...") command = "rm config.ini && rm -rf data && rm -rf creds" shell(command) log.info("Extracting cloned state...") command = "tar xzf clone.tar.gz" shell(command) # load config log.info("Loading configuration...") self.cm = ConfigManager() self.conf = self.cm.load_config(configFile) # load state log.info("Loading state...") self.state = StateManager(self.conf) self.state.load_state() """ def clone(self): #create a copy of db, peers, peer creds, and config #save to compressed archive #used to add new nodes to system try: self.state.image_state() self.cm.save_config() backupdir = "data/" cfile = "config.ini" command = "tar czf clone.tar.gz {} {} creds/".format(cfile,backupdir) shell(command) log.info("clone of state successfully created") except Exception as e: log.info("clone of state failed") def handle_reconfig_request(self, epoch=0): toreturn = self.bpcon.bmsgs if epoch != 0: self.clone() with open('clone.tar.gz', 'r') as fh: toreturn += "<>{}".format(fh.read()) log.debug("cloned state added successfully") return toreturn def make_reconfig_request(self, wss): # epoch = current epoch pass """ def shutdown(self): print("\nShutdown initiated...") print("\nDatabase contents:\n{}".format( self.bpcon.state.db.kvstore)) # save state here self.paxos_server.close()