def killProcess(agent, user, password, pid): s = Session(agent, service="ProcessStop") s.authorize(user, password) response = s.doRequest(attributes={"PID" : str(pid)}) return int(ElementTree.fromstring(response).get("ExitCode"))
def stopProcess(address, port, dbPassword): s = Session(address, port=port, service="Monitor") s.authorize("Cloud", dbPassword) s.doConnect() s.send("<Request Action=\"shutdown\"/>") s.close()
def query(self, type, msgBody=None): s = Session(self.getPeer().getConnectStr(), service="Manager") s.authorize(self.getPeer().getDomain().getUser(), self.getPeer().getDomain().getPassword()) pwdResponse = s.doRequest(attributes={"Type": "GetDatabaseCredentials", "Database": self.getDbName()}) pwdXml = ElementTree.fromstring(pwdResponse) pwd = pwdXml.find("Password").text.strip() return queryEngine(self.getAddress(), self.getPort(), type, pwd, msgBody)
def test_timeout(self): """ tests timeout function- includes a print message """ user6 = User(2859459814, '7386', 10000) Session.authorize(self.session, user6, '7386') Session.timeout(self.session, user6, 1597428189999999990.6783) self.assertEqual("Authorization required", Session.get_user_balance(self.session, user6))
def query(self, query_type, msg_body=None): session = Session(self.peer.connect_str, service="Manager") session.authorize(self.peer.domain.user, self.peer.domain.password) pwd_response = session.doRequest(attributes={"Type": "GetDatabaseCredentials", "Database": self.database.name}) pwd_xml = ElementTree.fromstring(pwd_response) pwd = pwd_xml.find("Password").text.strip() return queryEngine(self.address, self.port, query_type, pwd, msg_body)
def query(self, query_type, msg_body=None): session = Session(self.peer.domain.entry_peer.connect_str, service="Manager") session.authorize(self.peer.domain.user, self.peer.domain.password) pwd_response = session.doRequest(attributes={"Type": "GetDatabaseCredentials", "Database": self.database.name}) pwd_xml = ElementTree.fromstring(pwd_response) pwd = pwd_xml.find("Password").text.strip() return queryEngine(self.address, self.port, query_type, pwd, msg_body)
def test_logout(self): """ tests logout function- simple logout, and logout when no one is logged in """ user6 = User(2859459814, '7386', 10000) Session.authorize(self.session, user6, '7386') msg = Session.logout(self.session, user6) self.assertEqual("Account 2859459814 logged out", msg) self.assertEqual("No account is currently authorized", Session.logout(self.session, user6))
def test_deposit(self): """ tests the deposit function- if everything goes well and if authorization is required """ user1 = User(2001377812, '5950', 10000) Session.authorize(self.session, user1, '5950') a = datetime.now() success = Session.deposit(self.session, self.machine, user1, 50, a) self.assertEqual(success, "Current balance: 10050") Session.logout(self.session, user1) self.assertEqual( "Authorization required", Session.deposit(self.session, self.machine, user1, 50, a))
def doDatabaseAction(broker, user, password, db_name, action, child=None): s = Session(broker, service="ChorusManagement") s.authorize(user, password) if child is not None: child = [ child ] s.doConnect(attributes={"Database" : db_name, "Action" : action}, children=child) response = s.recv() checkForError(response) s.close() return response
def test_authorize(self): """ Tests the authorize function- pass, fail and does not exist """ user1 = User(2001377812, '5950', 0) user2 = User(2001377812, '0075', 0) user3 = User(1203939932, '0075', 0) pas = Session.authorize(self.session, user1, '5950') fail = Session.authorize(self.session, user2, '0075') notexist = Session.authorize(self.session, user3, '0075') self.assertEqual(pas, "2001377812 successfully authorized") self.assertEqual(fail, "Authorization failed") self.assertEqual(notexist, "Authorization failed")
def monitorEngine(address, port, dbPassword, listener=None): if not listener: listener = _StandardOutListener() s = Session(address, port=port, service="Monitor") s.authorize("Cloud", dbPassword) monitor = SessionMonitor(s, listener=listener) monitor.start() s.doConnect() return EngineMonitor(monitor, s)
def monitorDomainStats(broker, user, password, listener=None): if not listener: listener = _StandardOutListener() s = Session(broker, service="HostStats") s.authorize(user, password) s.doConnect() checkForError(s.recv()) monitor = SessionMonitor(s, listener=listener) monitor.start() return monitor
def getArchiveHistory(agent, user, password, archive, options=None): s = Session(agent, service="ProcessStart") s.authorize(user, password) option = _OPTION_VALUE_STR % ("--archive", archive) opts = [ ElementTree.fromstring(option) ] if options: for (k,v) in options: if v: option = _OPTION_VALUE_STR % (k, v) else: option = _OPTION_FLAG_STR % k opts.append(ElementTree.fromstring(option)) return s.doRequest(attributes={"Process" : "archiveHistory"}, children=opts)
def startProcess(agent, user, password, db_name, options=None): s = Session(agent, service="ProcessStart") s.authorize(user, password) if not options: options = [] options.append(("--database", db_name)) opts = [] for (k,v) in options: if v: optStr = _OPTION_VALUE_STR % (k, v) else: optStr = _OPTION_FLAG_STR % k opts.append(ElementTree.fromstring(optStr)) return s.doRequest(attributes={"Process" : "server"}, children=opts)
def queryEngine(address, port, target, dbPassword, msgBody=None): s = Session(address, port=port, service="Query") s.authorize("Cloud", dbPassword) s.doConnect() msg = "<Query Target=\"%s\"/>" % target if msgBody is not None: xml = ElementTree.fromstring(msg) xml.append(msgBody) msg = ElementTree.tostring(xml) s.send(msg) response = s.recv() checkForError(response) s.close() return response
def test_balance(self): """ tests the get_user_balance function- positive, negative and zero balance also when authorization is required """ user1 = User(2001377812, '5950', 10000) Session.authorize(self.session, user1, '5950') Session.withdraw(self.session, self.machine, user1, 400, datetime.now()) Session.withdraw(self.session, self.machine, user1, 160, datetime.now()) Session.deposit(self.session, self.machine, user1, 400, datetime.now()) self.assertEqual('Current balance: 9840', Session.get_user_balance(self.session, user1)) user2 = User(2001377812, '5950', 0) Session.authorize(self.session, user2, '5950') self.assertEqual('Current balance: 0', Session.get_user_balance(self.session, user2)) user3 = User(2001377812, '5950', -2020) Session.authorize(self.session, user2, '5950') self.assertEqual('Current balance: -2020', Session.get_user_balance(self.session, user3)) Session.logout(self.session, user3) self.assertEqual("Authorization required", Session.get_user_balance(self.session, user3))
def test_get_history(self): """ tests the get_history function- for empty and valid history, and for authorization required """ user1 = User(2001377812, '5950', 10000) Session.authorize(self.session, user1, '5950') self.assertEqual("No history found", Session.get_history(self.session, user1)) a = datetime.now() Session.withdraw(self.session, self.machine, user1, 400, a) a = a.strftime("%d/%m/%Y %H:%M:%S") b = datetime.now() Session.withdraw(self.session, self.machine, user1, 160, b) b = b.strftime("%d/%m/%Y %H:%M:%S") c = datetime.now() Session.deposit(self.session, self.machine, user1, 400, c) c = c.strftime("%d/%m/%Y %H:%M:%S") x = Session.get_history(self.session, user1) string = "\n%s 400 9840\n%s -160 9440\n%s -400 9600" % (a, b, c) self.assertEqual(string, x) Session.logout(self.session, user1) self.assertEqual("Authorization required", Session.get_history(self.session, user1))
def find_peer(self, address, port=None): """ Find a peer by address @type: address str @type: port int or str @rtype: Peer """ if port is None: if ":" in address: address, port = address.split(":", 2) else: port = self.__entry_peer.port else: if ":" in address: address, _ = address.split(":", 2) ip = socket.gethostbyname(address) inet_sock_addr = ":".join([ip, str(port)]) try: return self.__peers_by_addr[inet_sock_addr] except: pass session = Session(address, port=port, service="Identity") session.authorize(self.__user, self.__password) response = session.doRequest() try: root = ElementTree.fromstring(response) if self.__domain_name != root.get("Domain"): return None peer = self.get_peer(root.get("AgentId")) if peer: self.__peers_by_addr[peer._get_normalized_addr()] = peer return peer except: return None
def _send_domain_message(self, service, attributes=None, text=None, children=None): session = Session(self.__entry_peer.address, port=self.__entry_peer.port, service=service) session.authorize(self.__user, self.__password) return session.doRequest(attributes, text, children)
class Domain(BaseListener): """Represents the NuoDB domain. The domain is the top level NuoDB management object. The domain object provides access to the peers and databases that are contained within. """ def __init__(self, broker_addr, domain_user, domain_pwd, listener=None): """ @type broker_addr str @type domain_user str @type domain_pwd str @type listener """ if not domain_pwd: raise Exception("A password is required to join a domain") self.__session = Session(broker_addr, service="Monitor") self.__session.authorize(domain_user, domain_pwd) self.__user = domain_user self.__password = domain_pwd self.__listener = listener self.__peers = dict() """ @type : dict[str, Peer] """ self.__databases = dict() """ @type : dict[str, Database] """ self.__monitor = SessionMonitor(self.__session, self) # These will be set in handle status after joining the domain self.__domain_name = None """ @type : str """ self.__entry_peer = None """ @type : Peer """ try: self.__session.doConnect() self.__handle_status(self.__session.recv()) except Exception: self.__monitor.close() raise self.__monitor.start() def __str__(self): return self.domain_name + " [Entered through: " + self.entry_peer.connect_str + "]" def disconnect(self): """Disconnect from the domain.""" self.__monitor.close() def _send_domain_message(self, service, attributes=None, text=None, children=None): session = Session(self.__entry_peer.address, port=self.__entry_peer.port, service=service) session.authorize(self.__user, self.__password) return session.doRequest(attributes, text, children) @property def user(self): """Return the domain user.""" return self.__user @property def password(self): """Return the domain password.""" return self.__password @property def domain_name(self): """Return the domain name.""" return self.__domain_name def find_peer(self, address): """ Find a peer by address @type: address str @rtype: Peer """ def get_peer(self, agent_id): """ Return a peer for a given agent_id. @type agent_id str @rtype: Peer """ return self.__peers.get(agent_id) @property def peers(self): """ Return a list of all peers in the domain. @rtype: list[Peer] """ return self.__peers.values() @property def entry_peer(self): """ Return the peer that was used to enter the domain. @rtype: Peer """ return self.__entry_peer def get_database(self, name): """ Return a database by name @type name str @rtype: Database """ return self.__databases.get(name) @property def databases(self): """ Return a list of databases in the domain @rtype: list[Database] """ return self.__databases.values() def create_template(self, template_name, summary, requirements): """Create template by name""" response = self._send_domain_message(**Template.build_create_request(template_name, summary, requirements)) return ElementTree.fromstring(response).tag == Template.success_message def update_template(self, template_name, summary, requirements): """Update template by name""" response = self._send_domain_message(**Template.build_update_request(template_name, summary, requirements)) return ElementTree.fromstring(response).tag == Template.success_message def delete_template(self, template_name): """Delete template by name""" response = self._send_domain_message(**Template.build_delete_request(template_name)) return ElementTree.fromstring(response).tag == Template.success_message def get_template(self, template_name): """Return a template by name""" response = self._send_domain_message(**Template.build_get_request(template_name)) return Template.from_message(response) @property def templates(self): """Return a list of templates in the domain""" response = self._send_domain_message(**Template.build_list_request()) return Template.from_list_message(response) def create_description(self, name, template_name, variables, dba_user, dba_password): response = self._send_domain_message(**Description.build_create_request(name, template_name, variables, dba_user, dba_password)) return ElementTree.fromstring(response).tag == Description.success_message def update_description(self, name, template_name, variables): response = self._send_domain_message(**Description.build_update_request(name, template_name, variables)) return ElementTree.fromstring(response).tag == Description.success_message def delete_description(self, name): response = self._send_domain_message(**Description.build_delete_request(name)) return ElementTree.fromstring(response).tag == Description.success_message def get_description(self, name): response = self._send_domain_message(**Description.build_get_request(name)) return Description.from_message(response) def start_description(self, name): response = self._send_domain_message(**Description.build_start_request(name)) return ElementTree.fromstring(response).tag == Description.success_message def stop_description(self, name): response = self._send_domain_message(**Description.build_stop_request(name)) return ElementTree.fromstring(response).tag == Description.success_message @property def descriptions(self): response = self._send_domain_message(**Description.build_list_request()) return Description.from_list_message(response) def shutdown(self, graceful=True): """Shutdown all databases in the domain. graceful -- (default True) means that the database will first be quiesced and then shutdown. """ for database in self.__databases.itervalues(): database.shutdown(graceful) def message_received(self, root): """Process a management message from the broker. Override from session.BaseListener. """ if root.tag == "Event": event_type = root.get("Type") if event_type == "NewBroker": self.__peer_joined(Peer.from_message(self, root.find("Broker"))) elif event_type == "BrokerExit": self.__peer_left(Peer.from_message(self, root.find("Broker"))) elif event_type == "StatusChanged": status = root.get("Status") process_element = root.find("Process") db = self.__databases[process_element.get("Database")] process = Process.from_message(db, process_element) self.__process_status_changed(process, status) elif event_type == "ProcessFailed": peer = Peer.from_message(self, root.find("Broker")) peer = self.get_peer(peer.id) reason = root.get("Reason") start_id = root.get("StartId") self.__process_failed(peer, start_id, reason) elif event_type == "NewProcess" or event_type == "ProcessExit": process_element = root.find("Process") db_name = process_element.get("Database") if db_name not in self.__databases: self.__databases[db_name] = Database(self, db_name) if self.__listener: try: self.__listener.database_joined(self.__databases[db_name]) except AttributeError: pass if event_type == "NewProcess": start_id = process_element.get("StartId") self.__process_joined(Process.from_message(self.__databases[db_name], process_element), start_id) else: self.__process_left(Process.from_message(self.__databases[db_name], process_element)) def closed(self): """Called when the session is closed. Override from session.BaseListener. """ if self.__listener: try: self.__listener.closed() except AttributeError: pass def __handle_status(self, message): """Handle initial domain status on domain connection. Note that this is ONLY for processing the initial status message. All further update messages are processed by message_received().""" root = ElementTree.fromstring(message) if root.tag != "Status": raise Exception("Expected status message; got " + root.tag) self.__domain_name = root.get("Domain") self.__entry_peer = Peer(self, self.__session.address, root.get("AgentId"), (root.get("Role") == "Broker"), self.__session.port, root.get("Hostname"), root.get("Version")) self.__peer_joined(self.__entry_peer) for child in list(root): if child.tag == "Broker": self.__peer_joined(Peer.from_message(self, child)) for child in list(root): if child.tag == "Database": name = child.get("Name") if self.__listener: try: self.__listener.database_joined(self.__databases[name]) except AttributeError: pass for process_element in list(child): if process_element.tag == "Process": if name not in self.__databases: self.__databases[name] = Database(self, name) self.__process_joined(Process.from_message(self.__databases[name], process_element), None) def __peer_joined(self, peer): """Called when a peer joins the domain.""" self.__peers[peer.id] = peer if self.__listener: try: self.__listener.peer_joined(peer) except AttributeError: pass def __peer_left(self, peer): """Called when a peer leaves the domain.""" del self.__peers[peer.id] if self.__listener: try: self.__listener.peer_left(peer) except AttributeError: pass def __process_joined(self, process, start_id): """Called when a process joins the domain.""" process.database._add_process(process) process.peer._notify_start_id(start_id, process) if self.__listener: try: self.__listener.process_joined(process) except AttributeError: pass def __process_left(self, process): """Called when a process leaves the domain.""" database = process.database database._remove_process(process) process.peer._remove_process(process) if self.__listener: try: self.__listener.process_left(process) except AttributeError: pass if len(database.processes) == 0: del self.__databases[database.name] if self.__listener: try: self.__listener.database_left(database) except AttributeError: pass def __process_failed(self, peer, start_id, reason): """Called when a process in the domain fails.""" peer._notify_start_id(start_id, reason) if self.__listener: try: self.__listener.process_failed(peer, reason) except AttributeError: pass def __process_status_changed(self, process, status): """Called when a process in the domain changes status.""" process._set_status(status) if self.__listener: try: self.__listener.process_status_changed(process, status) except AttributeError: pass def _send_management_message(self, message, peer, process): """Send a management message. Note that this is an initial verison only to support the shutdown routine that doesn't need to watch for return messages ... right now this module is only supporting the tests, which don't need the other management routines at this point, so we'll flesh this out (as in the Java implementation) in the second round when other utilites get updated as well """ root = ElementTree.fromstring("<ManagementRequest AgentId=\"%s\" ProcessId=\"%i\"/>" % (peer.id, process.pid)) root.append(message) self.__session.send(ElementTree.tostring(root))
def main(): """ this is the main function- it creates a machine, and asks the user for input """ machine = Machine() machine.set_balance(10000) session = Session() Session.set_dict(session) input_var = None try: input_var = eval( input("Welcome to the ATM- please enter your user id ")) input_var = int(input_var) except (SyntaxError, NameError, TypeError): print("Not a valid input") if input_var in session.dic: bal = session.dic[input_var][1] try: pin = input("Please enter your pin ") except (SyntaxError, NameError, TypeError): print("Not a valid pin") pin = '0000' user = User(input_var, pin, bal) print((Session.authorize(session, user, pin))) amount = None actions = { 1: ["withdraw", 4], 2: ["deposit", 4], 3: ["get_user_balance", 1], 4: ["get_history", 1], 5: ["logout", 1], 6: ["end", 0] } action = None if session.session_active: #Validating input so we can avoid syntaxerrors try: action = eval( input( "What would you like to do today? Select a number: \n 1: Withdraw \n 2: Deposit \n 3: Check balance \n 4: Check history \n 5. Log out \n 6. Shut down " )) action = int(action) except (SyntaxError, NameError, TypeError): print("Not a valid input") while action: session.timeout(user, time.time()) try: action = int(action) except (SyntaxError, NameError, TypeError): print("Not a valid input") if action not in list(actions.keys()): action = eval(input("Not a valid input, try again ")) else: func = actions[action][0] params = actions[action][1] if params == 4: if func == "withdraw": # Validating input so we can avoid syntaxerrors try: amount = eval( input( "Please enter an amount (multiple of $20) to withdraw " )) amount = int(amount) assert (amount > 0) except (SyntaxError, NameError, TypeError, AssertionError): amount = 0 print("Not a valid amount") else: # Validating input so we can avoid syntaxerrors try: amount = eval( input( "Please enter an amount to deposit ")) amount = int(amount) assert (amount > 0) except (SyntaxError, NameError, AssertionError): amount = 0 print("Not a valid amount") print((getattr(Session, func)(session, machine, user, amount, datetime.now()))) elif params == 1: print((getattr(Session, func)(session, user))) else: print((getattr(Session, func)(session))) try: action = eval( input( "Anything else? Select a number: \n 1: Withdraw \n 2: Deposit \n 3: Check balance \n 4: Check history \n 5. Log out \n 6. End " )) except (SyntaxError, NameError, TypeError): print("Not a valid input- exiting program") print(Session.end(session)) else: print("Sorry, you are not a user of this bank ")
def getState(broker, user, password): s = Session(broker, service="State") s.authorize(user, password) return s.doRequest()
def setLicense(broker, user, password, licenseText): s = Session(broker, service="License") s.authorize(user, password) s.doRequest(attributes={ "Action" : "ApplyLicense" }, text=licenseText)
def getLicense(broker, user, password): s = Session(broker, service="License") s.authorize(user, password) return s.doRequest(attributes={ "Action" : "GetCurrentLicense" })
def _send_domain_message(self, service, attributes=None, text=None, children=None): session = Session(self.__entry_peer.address, port=self.__entry_peer.port, service=service) session.authorize(self.__user, self.__password) return session.doRequest(attributes, text, children)
class Domain(BaseListener): """Represents the NuoDB domain. The domain is the top level NuoDB management object. The domain object provides access to the peers and databases that are contained within. """ def __init__(self, broker_addr, domain_user, domain_pwd, listener=None): """ @type broker_addr str @type domain_user str @type domain_pwd str @type listener """ if not domain_pwd: raise Exception("A password is required to join a domain") self.__session = Session(broker_addr, service="Monitor") self.__session.authorize(domain_user, domain_pwd) self.__user = domain_user self.__password = domain_pwd self.__listener = listener self.__peers = dict() """ @type : dict[str, Peer] """ self.__databases = dict() """ @type : dict[str, Database] """ self.__monitor = SessionMonitor(self.__session, self) # These will be set in handle status after joining the domain self.__domain_name = None """ @type : str """ self.__entry_peer = None """ @type : Peer """ try: self.__session.doConnect() self.__handle_status(self.__session.recv()) except Exception: self.__monitor.close() raise self.__monitor.start() def __str__(self): return self.domain_name + " [Entered through: " + self.entry_peer.connect_str + "]" def disconnect(self): """Disconnect from the domain.""" self.__monitor.close() def _send_domain_message(self, service, attributes=None, text=None, children=None): session = Session(self.__entry_peer.address, port=self.__entry_peer.port, service=service) session.authorize(self.__user, self.__password) return session.doRequest(attributes, text, children) @property def user(self): """Return the domain user.""" return self.__user @property def password(self): """Return the domain password.""" return self.__password @property def domain_name(self): """Return the domain name.""" return self.__domain_name def find_peer(self, address): """ Find a peer by address @type: address str @rtype: Peer """ def get_peer(self, agent_id): """ Return a peer for a given agent_id. @type agent_id str @rtype: Peer """ return self.__peers.get(agent_id) @property def peers(self): """ Return a list of all peers in the domain. @rtype: list[Peer] """ return self.__peers.values() @property def entry_peer(self): """ Return the peer that was used to enter the domain. @rtype: Peer """ return self.__entry_peer def get_database(self, name): """ Return a database by name @type name str @rtype: Database """ return self.__databases.get(name) @property def databases(self): """ Return a list of databases in the domain @rtype: list[Database] """ return self.__databases.values() def create_template(self, template_name, summary, requirements): """Create template by name""" response = self._send_domain_message(**Template.build_create_request(template_name, summary, requirements)) return ElementTree.fromstring(response).tag == Template.success_message def update_template(self, template_name, summary, requirements): """Update template by name""" response = self._send_domain_message(**Template.build_update_request(template_name, summary, requirements)) return ElementTree.fromstring(response).tag == Template.success_message def delete_template(self, template_name): """Delete template by name""" response = self._send_domain_message(**Template.build_delete_request(template_name)) return ElementTree.fromstring(response).tag == Template.success_message def get_template(self, template_name): """Return a template by name""" response = self._send_domain_message(**Template.build_get_request(template_name)) return Template.from_message(response) @property def templates(self): """Return a list of templates in the domain""" response = self._send_domain_message(**Template.build_list_request()) return Template.from_list_message(response) def create_description(self, name, template_name, variables, dba_user, dba_password): response = self._send_domain_message(**Description.build_create_request(name, template_name, variables, dba_user, dba_password)) return ElementTree.fromstring(response).tag == Description.success_message def update_description(self, name, template_name, variables): response = self._send_domain_message(**Description.build_update_request(name, template_name, variables)) return ElementTree.fromstring(response).tag == Description.success_message def delete_description(self, name): response = self._send_domain_message(**Description.build_delete_request(name)) return ElementTree.fromstring(response).tag == Description.success_message def get_description(self, name): response = self._send_domain_message(**Description.build_get_request(name)) return Description.from_message(response) def start_description(self, name): response = self._send_domain_message(**Description.build_start_request(name)) return ElementTree.fromstring(response).tag == Description.success_message def stop_description(self, name): response = self._send_domain_message(**Description.build_stop_request(name)) return ElementTree.fromstring(response).tag == Description.success_message @property def descriptions(self): response = self._send_domain_message(**Description.build_list_request()) return Description.from_list_message(response) def shutdown(self, graceful=True): """Shutdown all databases in the domain. graceful -- (default True) means that the database will first be quiesced and then shutdown. """ for database in self.__databases.itervalues(): database.shutdown(graceful) def message_received(self, root): """Process a management message from the broker. Override from session.BaseListener. """ if root.tag == "Event": event_type = root.get("Type") if event_type == "NewBroker": self.__peer_joined(Peer.from_message(self, root.find("Broker"))) elif event_type == "BrokerExit": self.__peer_left(Peer.from_message(self, root.find("Broker"))) elif event_type == "StatusChanged": status = root.get("Status") process_element = root.find("Process") db = self.__databases[process_element.get("Database")] process = Process.from_message(db, process_element) self.__process_status_changed(process, status) elif event_type == "ProcessFailed": peer = Peer.from_message(self, root.find("Broker")) peer = self.get_peer(peer.id) reason = root.get("Reason") start_id = root.get("StartId") self.__process_failed(peer, start_id, reason) elif event_type == "NewProcess" or event_type == "ProcessExit": process_element = root.find("Process") db_name = process_element.get("Database") if db_name not in self.__databases: self.__databases[db_name] = Database(self, db_name) if self.__listener: try: self.__listener.database_joined(self.__databases[db_name]) except AttributeError: pass if event_type == "NewProcess": start_id = process_element.get("StartId") self.__process_joined(Process.from_message(self.__databases[db_name], process_element), start_id) else: self.__process_left(Process.from_message(self.__databases[db_name], process_element)) def closed(self): """Called when the session is closed. Override from session.BaseListener. """ if self.__listener: try: self.__listener.closed() except AttributeError: pass def __handle_status(self, message): """Handle initial domain status on domain connection. Note that this is ONLY for processing the initial status message. All further update messages are processed by message_received().""" root = ElementTree.fromstring(message) if root.tag != "Status": raise Exception("Expected status message; got " + root.tag) self.__domain_name = root.get("Domain") self.__entry_peer = Peer(self, self.__session.address, root.get("AgentId"), (root.get("Role") == "Broker"), self.__session.port, root.get("Hostname"), root.get("Version")) self.__peer_joined(self.__entry_peer) for child in list(root): if child.tag == "Broker": self.__peer_joined(Peer.from_message(self, child)) for child in list(root): if child.tag == "Database": name = child.get("Name") if self.__listener: try: self.__listener.database_joined(self.__databases[name]) except AttributeError: pass for process_element in list(child): if process_element.tag == "Process": if name not in self.__databases: self.__databases[name] = Database(self, name) self.__process_joined(Process.from_message(self.__databases[name], process_element), None) def __peer_joined(self, peer): """Called when a peer joins the domain.""" self.__peers[peer.id] = peer if self.__listener: try: self.__listener.peer_joined(peer) except AttributeError: pass def __peer_left(self, peer): """Called when a peer leaves the domain.""" del self.__peers[peer.id] if self.__listener: try: self.__listener.peer_left(peer) except AttributeError: pass def __process_joined(self, process, start_id): """Called when a process joins the domain.""" process.database._add_process(process) process.peer._notify_start_id(start_id, process) if self.__listener: try: self.__listener.process_joined(process) except AttributeError: pass def __process_left(self, process): """Called when a process leaves the domain.""" database = process.database database._remove_process(process) process.peer._remove_process(process) if self.__listener: try: self.__listener.process_left(process) except AttributeError: pass if len(database.processes) == 0: del self.__databases[database.name] if self.__listener: try: self.__listener.database_left(database) except AttributeError: pass def __process_failed(self, peer, start_id, reason): """Called when a process in the domain fails.""" peer._notify_start_id(start_id, reason) if self.__listener: try: self.__listener.process_failed(peer, reason) except AttributeError: pass def __process_status_changed(self, process, status): """Called when a process in the domain changes status.""" process._set_status(status) if self.__listener: try: self.__listener.process_status_changed(process, status) except AttributeError: pass def _send_management_message(self, message, peer, process): """Send a management message. Note that this is an initial verison only to support the shutdown routine that doesn't need to watch for return messages ... right now this module is only supporting the tests, which don't need the other management routines at this point, so we'll flesh this out (as in the Java implementation) in the second round when other utilites get updated as well """ root = ElementTree.fromstring("<ManagementRequest AgentId=\"%s\" ProcessId=\"%i\"/>" % (peer.id, process.pid)) root.append(message) self.__session.send(ElementTree.tostring(root))
def test_withdrawal(self): """ tests the deposit function- check overdraft, not multiple of 200, whether the machine is empty, whether the machine has enough money, whether the user has enough money """ user1 = User(7089382418, '0075', 100) Session.authorize(self.session, user1, '0075') a = datetime.now() Session.withdraw(self.session, self.machine, user1, 400, a) b = datetime.now() overdrawn = Session.withdraw(self.session, self.machine, user1, 160, b) self.assertEqual( "Your account is overdrawn! You may not make withdrawals at this time.", overdrawn) user2 = User(2001377812, '5950', 100) Session.authorize(self.session, user2, '5950') c = datetime.now() not_multiple = Session.withdraw(self.session, self.machine, user2, 412, c) self.assertEqual("Unable to process your withdrawal at this time.", not_multiple) self.machine.set_balance(0) empty_machine = Session.withdraw(self.session, self.machine, user2, 412, c) self.assertEqual("Unable to process your withdrawal at this time.", empty_machine) #overdraft tests user3 = User(2001377812, '5950', 100) Session.authorize(self.session, user3, '5950') self.machine.set_balance(120) not_enough_in_machine_or_user = Session.withdraw( self.session, self.machine, user3, 400, c) string = "Unable to dispense full amount requested at this time\n Amount dispensed: 120 \n You have been charged an overdraft fee of $5. Current balance: -25" self.assertEqual(not_enough_in_machine_or_user, string) user4 = User(2001377812, '5950', 100) Session.authorize(self.session, user4, '5950') self.machine.set_balance(10000) not_enough_in_user = Session.withdraw(self.session, self.machine, user4, 300, c) string = "Amount dispensed: 300 \n You have been charged an overdraft fee of $5. Current balance: -205" self.assertEqual(not_enough_in_user, string) user5 = User(2001377812, '5950', 10000) Session.authorize(self.session, user5, '5950') self.machine.set_balance(300) not_enough_money_in_machine = Session.withdraw(self.session, self.machine, user5, 600, c) string = "Unable to dispense full amount requested at this time\n Amount dispensed: 300 \. Current balance: 9700" self.assertEqual(not_enough_money_in_machine, string) #all goes well user6 = User(2001377812, '5950', 10000) Session.authorize(self.session, user6, '5950') self.machine.set_balance(10000) success = Session.withdraw(self.session, self.machine, user6, 600, c) string = "Amount dispensed: 600 \n Current balance: 9400" self.assertEqual(success, string) #authorization required Session.logout(self.session, user6) self.assertEqual( "Authorization required", Session.withdraw(self.session, self.machine, user6, 20, c))
class Domain(BaseListener): def __init__(self, brokerAddr, domainUser, domainPwd, listener=None): if not domainPwd: raise Exception("A password is required to join a domain") self.__session = Session(brokerAddr, service="Monitor") self.__session.authorize(domainUser, domainPwd) self.__user = domainUser self.__password = domainPwd self.__listener = listener self.__peers = dict() self.__databases = dict() self.__monitor = SessionMonitor(self.__session, self) try: self.__session.doConnect() self.__handleStatus(self.__session.recv()) except Exception: self.__monitor.close() raise self.__monitor.start() def __str__(self): return self.getDomainName() + " [Entered through: " + self.getEntryPeer().getConnectStr() + "]" def disconnect(self): self.__monitor.close() def getUser(self): return self.__user def getPassword(self): return self.__password def getDomainName(self): return self.__domainName def getPeer(self, agentId): return self.__peers.get(agentId) def getPeers(self): return self.__peers.itervalues() def getEntryPeer(self): return self.__entryPeer def getDatabase(self, name): return self.__databases.get(name) def getDatabases(self): return self.__databases.itervalues() def getDatabaseCount(self): return len(self.__databases) def shutdown(self, graceful=True): for (dbName, db) in self.__databases.items(): db.shutdown(graceful) def messageReceived(self, root): if root.tag == "Event": eventType = root.get("Type") if eventType == "NewBroker": self.__peerJoined(Peer.fromMessage(self, root.find("Broker"))) elif eventType == "BrokerExit": self.__peerLeft(Peer.fromMessage(self, root.find("Broker"))) elif eventType == "StatusChanged": status = root.get("Status") processElement = root.find("Process") db = self.__databases[processElement.get("Database")] process = Process.fromMessage(db, processElement) self.__processStatusChanged(process, status) elif eventType == "ProcessFailed": peer = Peer.fromMessage(self, root.find("Broker")) peer = self.getPeer(peer.getId()) reason = root.get("Reason") startId = root.get("StartId") self.__processFailed(peer, startId, reason) elif eventType == "NewProcess" or eventType == "ProcessExit": processElement = root.find("Process") dbName = processElement.get("Database") if dbName not in self.__databases: self.__databases[dbName] = Database(self, dbName) if self.__listener: try: self.__listener.databaseJoined(self.__databases[dbName]) except: pass if eventType == "NewProcess": startId = processElement.get("StartId") self.__processJoined(Process.fromMessage(self.__databases[dbName], processElement), startId) else: self.__processLeft(Process.fromMessage(self.__databases[dbName], processElement)) def closed(self): if self.__listener: try: self.__listener.closed() except: pass # NOTE: this is the status provided on initial broker-connection, and not # per-process status updates def __handleStatus(self, message): root = ElementTree.fromstring(message) if root.tag != "Status": raise Exception("Expected status message; got " + root.tag) self.__domainName = root.get("Domain") self.__entryPeer = Peer( self, self.__session.getAddress(), root.get("AgentId"), (root.get("Role") == "Broker"), self.__session.getPort(), root.get("Hostname"), root.get("Version"), ) self.__peerJoined(self.__entryPeer) for child in list(root): if child.tag == "Broker": self.__peerJoined(Peer.fromMessage(self, child)) for child in list(root): if child.tag == "Database": name = child.get("Name") if self.__listener: try: self.__listener.databaseJoined(self.__databases[name]) except: pass for processElement in list(child): if processElement.tag == "Process": if name not in self.__databases: self.__databases[name] = Database(self, name) self.__processJoined(Process.fromMessage(self.__databases[name], processElement), None) def __peerJoined(self, peer): self.__peers[peer.getId()] = peer if self.__listener: try: self.__listener.peerJoined(peer) except: pass def __peerLeft(self, peer): del self.__peers[peer.getId()] if self.__listener: try: self.__listener.peerLeft(peer) except: pass def __processJoined(self, process, startId): process.getDatabase()._addProcess(process) process.getPeer()._notifyStartId(startId, process) if self.__listener: try: self.__listener.processJoined(process) except: pass def __processLeft(self, process): database = process.getDatabase() database._removeProcess(process) process.getPeer()._removeProcess(process) if self.__listener: try: self.__listener.processLeft(process) except: pass if database.getProcessCount() == 0: del self.__databases[database.getName()] if self.__listener: try: self.__listener.databaseLeft(database) except: pass def __processFailed(self, peer, startId, reason): peer._notifyStartId(startId, reason) if self.__listener: try: self.__listener.processFailed(peer, reason) except: pass def __processStatusChanged(self, process, status): process._setStatus(status) if self.__listener: try: self.__listener.processStatusChanged(process, status) except: pass # an initial verison only to support the shutdown routine that doesn't # need to watch for return messages ... right now this module is only # supporting the tests, which don't need the other management routines # at this point, so we'll flesh this out (as in the Java implementation) # in the second round when other utilites get updated as well def _sendManagementMessage(self, message, peer, process): root = ElementTree.fromstring( '<ManagementRequest AgentId="%s" ProcessId="%i"/>' % (peer.getId(), process.getPid()) ) root.append(message) self.__session.send(ElementTree.tostring(root))