def __init__(self) -> None: try: with open("config.json") as configFile: config = json.load(configFile) self.username = os.environ['AMZNFLEXUSERNAME'] self.password = os.environ["AMZNFLEXPWD"] self.desiredWarehouses = config["desiredWarehouses"] if len(config["desiredWarehouses"]) >= 1 else None # list of warehouse ids self.minBlockRate = config["minBlockRate"] self.arrivalBuffer = config["arrivalBuffer"] self.desiredStartHour = config["desiredStartHour"] # start hour in military time self.desiredEndHour = config["desiredEndHour"] # end hour in military time self.retryLimit = config["retryLimit"] # number of jobs retrieval requests to perform self.twilioFromNumber = config["twilioFromNumber"] self.twilioToNumber = config["twilioToNumber"] self.__retryCount = 0 self.__acceptedOffers = [] self.__startTimestamp = time.time() self.__requestHeaders = FlexUnlimited.allHeaders.get("FlexCapacityRequest") self.__requestHeaders["x-amz-access-token"] = self.__getFlexRequestAuthToken() twilioAcctSid = config["twilioAcctSid"] twilioAuthToken = config["twilioAuthToken"] if twilioAcctSid != "" and twilioAuthToken != "" and self.twilioFromNumber != "" and self.twilioToNumber != "": self.twilioClient = Client(twilioAcctSid, twilioAuthToken) else: self.twilioClient = None except KeyError as nullKey: Log.error(f'{nullKey} was not set. Please setup FlexUnlimited as described in the README.') sys.exit() except FileNotFoundError: Log.error("Config file not found. Ensure a properly formatted 'config.json' file exists in the root directory.") sys.exit()
def __acceptOffer(self, offer: Offer): self.__requestHeaders["X-Amz-Date"] = self.__getAmzDate() request = requests.post( FlexUnlimited.routes.get("AcceptOffer"), headers=self.__requestHeaders, json={"offerId": offer.id}) if request.status_code == 200: self.__acceptedOffers.append(offer) if self.twilioClient is not None: self.twilioClient.messages.create( to=self.twilioToNumber, from_=self.twilioFromNumber, body=offer.toString()) Log.info(f"Successfully accepted offer {offer.id}") else: Log.error(f"Unable to accept offer {offer.id}. Request returned status code {request.status_code}")
def __getFlexRequestAuthToken(self) -> str: """ Get authorization token for Flex Capacity requests Returns: An access token as a string """ payload = { "requested_extensions": ["device_info", "customer_info"], "cookies": { "website_cookies": [], "domain": ".amazon.com" }, "registration_data": { "domain": "Device", "app_version": "0.0", "device_type": "A3NWHXTQ4EBCZS", "os_version": "15.2", "device_serial": "B262D48AC3EA4671B288C20F406821B5", "device_model": "iPhone", "app_name": "Amazon Flex", "software_version": "1" }, "auth_data": { "user_id_password": { "user_id": self.username, "password": self.password } }, "user_context_map": { "frc": "AFgQ07+f4rZ1HkMDmsLeD9GlOFoIa9auy7p03s6CSDsZFiskgDYWhSIQyD7S8EUxSMGAGs1gf0e" "\/wlmnvGBZ2Jh7YkvVfXENXnwoQ12acgHysONHR\/oBMWPwNOBg+qY88UlNQ1RXNOv9fgMDJPjr5gvZJs3S5RY9RyAMg7H" "\/sSIEJ9j+TXIE+xnMZrT1lOpEMdQJHV53+pgcJEG2SB4kt8OraJqoZCt7A\/lyWO9RAL1gWlnhEHyEd3" "\/\/t8TNQBKXbjO2G9iFUQs\/s0VqVSchIVzOzT\/BRpe36iFW7XnbGU0N9Q5Y40m+M" "\/kxySQ3h5YWs9kl1PuLGTx3ql1ttSf7nSHLGj342KZJtK3oOjCxVrsjteGRyekpKe6Jagrssjq1QOVNIyRmU428fdl" "\/lWILDAnSFSMZNiOzzQ=="}, "requested_token_type": ["bearer", "mac_dms", "website_cookies"] } try: response = requests.post(FlexUnlimited.routes.get("GetAuthToken"), headers=FlexUnlimited.allHeaders.get("AmazonApiRequest"), json=payload).json() return response.get("response").get("success").get("tokens").get("bearer").get("access_token") except Exception as e: Log.error("Unable to authenticate to Amazon Flex. Please provide a valid Amazon Flex username and password.") sys.exit()
def run(self): Log.info("Starting job search...") while self.__retryCount < self.retryLimit: if not self.__retryCount % 50: print(self.__retryCount, 'requests attempted\n\n') offersResponse = self.__getOffers() if offersResponse.status_code == 200: currentOffers = offersResponse.json().get("offerList") currentOffers.sort(key=lambda pay: int(pay['rateInfo']['priceAmount']), reverse=True) for offer in currentOffers: offerResponseObject = Offer(offerResponseObject=offer) self.__processOffer(offerResponseObject) self.__retryCount += 1 else: Log.error(offersResponse.json()) break Log.info("Job search cycle ending...") Log.info(f"Accepted {len(self.__acceptedOffers)} offers in {time.time() - self.__startTimestamp} seconds")
class ZenStatus(IZen, Client): down = [] hosts = {} log = None def __init__(self): zen = ConfUtil.zen() conf = ConfUtil.zen(__file__) conf['localhost'] = zen['localhost'] self.conf = conf daemon = Util.filename(__file__) self.log = Log(daemon) Client.__init__(self, daemon, self.log) def mail(self, host, success): status = 'up' if success else 'down' mail = DictUtil.copy(self.conf['mail']) mail['subject'] %= status.upper() mail['body'] %= host debug = DebugUtil.mail(self.conf['localhost']['name'], mail) if Mail.sendraw(mail): self.log.info('Mail sent %s' % debug) else: self.log.critical('Mail not sent %s' % debug) def start(self, ip): up = False host = Util.hostname(ip) for _ in range(self.conf['start']['retries']): if 'backup' in self.hosts[host] and self.hosts[host]['backup']: up = True break cmd = ['ssh', ip, 'service', 'serviced', 'start'] check_call(cmd, stderr=PIPE) cmd = ['ssh', ip, 'service', 'serviced', 'status'] output = check_output(cmd, stderr=PIPE) if 'running' not in output: sleep(self.conf['start']['timeout']) continue cmd = ['ssh', ip, 'serviced', 'service', 'start', 'Zenoss.core'] output = check_output(cmd) if 'started' not in output: sleep(self.conf['start']['timeout']) continue up = True break if host in self.down: if up: self.mail(host, True) self.down.remove(host) else: if not up: self.mail(host, False) self.down.append(host) return up def status(self): _hosts = self.hosts.keys() hosts = {h: {} for h in _hosts} for host in sorted(_hosts): if not self.hosts[host]['ping']: hosts[host]['status'] = False self.log.error(host) continue if self.start(self.hosts[host]['ip']): hosts[host]['status'] = True self.log.success(host) else: hosts[host]['status'] = False self.log.error(host) d = {'hosts': hosts} self.send(d) def run(self): try: worker = None self.log.clear() while True: packet = self.recv() self.hosts = packet['hosts'] if worker is not None and worker.is_alive(): continue self.log.clear() worker = Thread(target=self.status) worker.start() except KeyboardInterrupt: pass
class ZenPing(IZen, Client): hosts = {} mails = { 'up' : [], 'down' : [] } down = [] log = None @staticmethod def ping(ip): try: cmd = ['ping', '-c', '1', '-w', '1', '-q', ip] output = check_output(cmd) return ' 0% packet loss' in output except CalledProcessError: return False def __init__(self): zen = ConfUtil.zen() conf = ConfUtil.zen(__file__) conf['localhost'] = zen['localhost'] self.conf = conf daemon = Util.filename(__file__) self.log = Log(daemon) Client.__init__(self, daemon, self.log) def mail(self, up): status = 'up' if up else 'down' mail = DictUtil.copy(self.conf['mail']) mail['subject'] %= status.upper() body = self.mails[status].pop() if len(self.mails[status]) > 0: hosts = ', '.join(self.mails[status]) body = '%s & %s' % (hosts, body) mail['body'] %= body debug = DebugUtil.mail(self.conf['localhost']['name'], mail) if Mail.sendraw(mail): self.log.info('Mail sent %s' % debug) else: self.log.critical('Mail not sent %s' % debug) def run(self): try: self.log.clear() packet = self.recv() self.hosts = packet['hosts'] hosts = {h: {} for h in self.hosts.keys()} while True: for host in sorted(self.hosts): if ZenPing.ping(self.hosts[host]['ip']): if host in self.down: self.down.remove(host) self.mails['up'].append(host) hosts[host]['ping'] = True self.log.success(host) else: if host not in self.down: self.down.append(host) self.mails['down'].append(host) hosts[host]['ping'] = False self.log.error(host) if len(self.mails['down']) > 0: self.mail(False) self.mails['down'] = [] if len(self.mails['up']) > 0: self.mail(True) self.mails['up'] = [] d = {'hosts': hosts} self.send(d) sleep(self.conf['sleep']) self.log.clear() except KeyboardInterrupt: pass