def update_order_status(self, order_number, unit_number, status): """ Update the status of orders ESPA is working on. :param order_number: EE order id :type order_number: string :param unit_number: id for unit to update :type unit_number: string :param status: the EE defined status value :type status: string """ endpoint = 'setunitstatus' payload = dict(apiKey=self.token, orderNumber=order_number, unitStatus=status, firstUnitNumber=unit_number, lastUnitNumber=unit_number) response = self._post(endpoint, payload) error = response.get('error') if not error: return {'success': True, 'message': None, 'status': None} else: # throw exception if non 200 response? logger.error( "Problem updating order status in EE. order_number: {} unit_number: {} status: {} response: {}" .format(order_number, unit_number, status, response)) return {'success': False, 'message': response, 'status': 'Fail'}
def send_all_initial(self, orders): '''Finds all the orders that have not had their initial emails sent and sends them''' for o in orders: if not o.initial_email_sent: try: self.send_initial(o.orderid) o.update('initial_email_sent', datetime.datetime.now()) except SMTPServerDisconnected: logger.error('Unable to send initial email: {}'.format( o.orderid)) return True
def logout(self): """ Remove the users API key from being used in the future :return: bool """ endpoint = 'logout' payload = dict(apiKey=self.token) resp = self._post(endpoint, payload) if resp.get('data'): return True else: logger.error('{} logout failed'.format(self.current_user))
def _parse(response): """ Attempt to parse the JSON response, which always contains additional information that we might not always want to look at (except on error) :param response: requests.models.Response :return: dict """ data = None try: response.raise_for_status() except requests.exceptions.HTTPError as e: logger.error('server reported bad status code: {}' .format(e)) try: data = response.json() except ValueError as e: msg = ('unable to parse JSON response. {}\n' 'traceback:\n{}'.format(e, traceback.format_exc())) logger.error(msg) if data.get('error'): logger.error('{errorCode}: {error}'.format(**data)) if 'data' not in data: logger.error('no data found:\n{}'.format(data)) return data
def get_available_orders(self, contactid=None): """ Return collection of ESPA orders from EE """ endpoint = 'getorderqueue' payload = dict(apiKey=self.token, queueName='espa') response = self._post(endpoint, payload) data = response.get('data') orders = [] if isinstance(data, dict) and 'orders' in data.keys(): if contactid: orders = [ o for o in data.get('orders') if o.get('contactId') == contactid ] else: orders = data.get('orders') else: logger.error( "Problem retrieving available orders from M2M. response: {}". format(response)) return orders
def set_login(self, token): cache_key = self.MC_KEY_FMT.format(resource='login') success = self.cache.set(cache_key, token) if not success: logger.error('LTACachedService: Token not cached')
def get_download_urls(self, product_list, contact_id): ''' Returns a list of named tuples containing the product id, product status, product code, sensor name, and (conditionally) a one time use download url to obtain the product. The download url is only populated if the status of the product is returned as 'available' Keyword args: product_list A list of products to generate a download url for contact_id The id of the user requesting the product urls Returns: A dict of dicts: d[product_name] = {'lta_prod_code': 'T272', 'sensor': 'LANDSAT_8', 'status': 'available', 'download_url': 'http://one_time_use.tar.gz'} ''' def build_request(contact_id, products): # build the request body sb = StringIO() sb.write(self.xml_header) head = ("<downloadSceneList " "xmlns=" "'https://earthexplorer.usgs.gov/schema/downloadSceneList' " "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " "xsi:schemaLocation=" "'https://earthexplorer.usgs.gov/schema/downloadSceneList " "https://earthexplorer.usgs.gov/EE/downloadSceneList.xsd'>") sb.write(head) sb.write("<contactId>{0}</contactId>".format(contact_id)) for p in products: try: product = sensor.instance(p) except sensor.ProductNotImplemented: logger.warn("{0} not implemented, skipping".format(p)) else: sb.write("<scene>") sb.write("<sceneId>{0}</sceneId>" .format(product.product_id)) sb.write("<sensor>{0}</sensor>".format(product.lta_name)) sb.write("</scene>") sb.write("</downloadSceneList>") request_body = sb.getvalue() return request_body def parse_response(response_xml): '''<?xml version="1.0" encoding="UTF-8"?>' <downloadList xmlns="http://host/schema/downloadList" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://host/schema/downloadList http://host/OrderWrapperServicedevsys/downloadList.xsd"> <scene> <sceneId>LC80380292014211LGN00</sceneId> <prodCode>D217</prodCode> <sensor>LANDSAT_8</sensor> <status>available</status> <downloadURL>http://one_time_use.tar.gz</downloadURL> </scene> </downloadList> ''' schema = 'downloadList' # escape the ampersands and get rid of newlines if they exist # was having problems with the sax escape() function #response = response_xml.replace('&', '&').replace('\n', '') #this will get us the list of <scene></scene> elements scene_elements = list(xml.fromstring(response_xml).getchildren()) retval = {} external_hosts = config.url_for('landsat.external').split(',') load_balancer = config.url_for('landsat.datapool') for index, scene in enumerate(list(scene_elements)): name = self.get_xml_item(scene, schema, 'sceneId').text status = self.get_xml_item(scene, schema, 'status').text prod_code = self.get_xml_item(scene, schema, 'prodCode').text sensor = self.get_xml_item(scene, schema, 'sensor').text retval[name] = {'lta_code': prod_code, 'sensor': sensor, 'status': status} #may not be included with every response if not online __dload_url = self.get_xml_item(scene, schema, 'downloadURL') dload_url = None if __dload_url is not None: dload_url = __dload_url.text for external_host in external_hosts: if dload_url.find(external_host) != -1: dload_url = dload_url.replace(external_host, load_balancer.strip()) retval[name]['download_url'] = dload_url return retval # build service url request_url = "{0}/{1}".format(self.url, 'getDownloadURL') payload = build_request(contact_id, product_list) response = requests.post(request_url, data=payload) if response.ok: return parse_response(response.text) else: msg = ('Error retrieving download urls. Reason:{0} Response:{1}\n' 'Contact id:{2}'.format(response.reason, response.text, contact_id)) logger.error(msg) raise RuntimeError(msg)
def get_download_urls(self, product_list, contact_id): """ Returns a list of named tuples containing the product id, product status, product code, sensor name, and (conditionally) a one time use download url to obtain the product. The download url is only populated if the status of the product is returned as 'available' Keyword args: product_list A list of products to generate a download url for contact_id The id of the user requesting the product urls Returns: A dict of dicts: d[product_name] = {'lta_prod_code': 'T272', 'sensor': 'LANDSAT_8', 'status': 'available', 'download_url': 'http://one_time_use.tar.gz'} """ def build_request(contact_id, products): # build the request body sb = StringIO() sb.write(self.xml_header) head = ( "<downloadSceneList " "xmlns=" "'https://earthexplorer.usgs.gov/schema/downloadSceneList' " "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " "xsi:schemaLocation=" "'https://earthexplorer.usgs.gov/schema/downloadSceneList " "https://earthexplorer.usgs.gov/EE/downloadSceneList.xsd'>" ) sb.write(head) sb.write("<contactId>{0}</contactId>".format(contact_id)) for p in products: try: product = sensor.instance(p) except sensor.ProductNotImplemented: logger.warn("{0} not implemented, skipping".format(p)) else: sb.write("<scene>") sb.write("<sceneId>{0}</sceneId>".format(product.product_id)) sb.write("<sensor>{0}</sensor>".format(product.lta_name)) sb.write("</scene>") sb.write("</downloadSceneList>") request_body = sb.getvalue() return request_body def parse_response(response_xml): """<?xml version="1.0" encoding="UTF-8"?>' <downloadList xmlns="http://host/schema/downloadList" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://host/schema/downloadList http://host/OrderWrapperServicedevsys/downloadList.xsd"> <scene> <sceneId>LC80380292014211LGN00</sceneId> <prodCode>D217</prodCode> <sensor>LANDSAT_8</sensor> <status>available</status> <downloadURL>http://one_time_use.tar.gz</downloadURL> </scene> </downloadList> """ __ns = "http://earthexplorer.usgs.gov/schema/downloadList" __ns_prefix = "".join(["{", __ns, "}"]) sceneid_elem = "".join([__ns_prefix, "sceneId"]) prod_code_elem = "".join([__ns_prefix, "prodCode"]) sensor_elem = "".join([__ns_prefix, "sensor"]) status_elem = "".join([__ns_prefix, "status"]) dload_url_elem = "".join([__ns_prefix, "downloadURL"]) # escape the ampersands and get rid of newlines if they exist # was having problems with the sax escape() function # response = response_xml.replace('&', '&').replace('\n', '') # this will get us the list of <scene></scene> elements scene_elements = list(xml.fromstring(response_xml).getchildren()) retval = {} ehost = config.url_for("external_cache") ihosts = config.url_for("internal_cache").split(",") for index, scene in enumerate(list(scene_elements)): name = scene.find(sceneid_elem).text prod_code = scene.find(prod_code_elem).text sensor = scene.find(sensor_elem).text status = scene.find(status_elem).text retval[name] = {"lta_code": prod_code, "sensor": sensor, "status": status} # may not be included with every response if not online __dload_url = scene.find(dload_url_elem) dload_url = None if __dload_url is not None: dload_url = __dload_url.text if dload_url.find(ehost) != -1: dload_url = dload_url.replace(ehost, ihosts[index % 2].strip()) retval[name]["download_url"] = dload_url return retval # build service url request_url = "{0}/{1}".format(self.url, "getDownloadURL") payload = build_request(contact_id, product_list) response = requests.post(request_url, data=payload) if response.ok: return parse_response(response.text) else: msg = "Error retrieving download urls. Reason:{0} Response:{1}\n" "Contact id:{2}".format( response.reason, response.text, contact_id ) logger.error(msg) raise RuntimeError(msg)
def __init__(self, message): logger.error('ERR %s', message) super(LTAError, self).__init__(message)