Пример #1
0
        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
Пример #2
0
    def input_exists(self, product):
        '''Determines if a LPDAAC product is available for download

        Keyword args:
        product - The name of the product

        Returns:
        True/False
        '''
        if isinstance(product, str) or isinstance(product, unicode):
            product = sensor.instance(product)

        result = False

        try:
            url = self.get_download_url(product)
            if 'download_url' in url[product.product_id]:
                url = url[product.product_id]['download_url']
                try:
                    result = utils.connections.is_reachable(url, timeout=1)
                except Exception, e:
                    logger.exception('Exception checking modis input {0}\n '
                                     'Exception:{1}'.format(url, e))
                    return result
        except sensor.ProductNotImplemented:
            logger.warn(
                '{0} is not an implemented LPDAAC product'.format(product))

        return result
Пример #3
0
        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
Пример #4
0
    def decorated(*args, **kwargs):
        white_ls = espa.get_stat_whitelist()
        denied_response = MessagesResponse(errors=['Access Denied'], code=403)
        remote_addr = user_ip_address()

        if ((remote_addr in white_ls or request.remote_addr in white_ls)
                and remote_addr != 'untrackable'):
            return func(*args, **kwargs)
        else:
            logger.warn('*** Not in whitelist ({1}): {0}'.format(
                remote_addr, white_ls))
            return denied_response()
Пример #5
0
    def run(self, name):
        if name not in REPORTS:
            raise NotImplementedError

        query = REPORTS[name]['query']
        if query is not None and len(query) > 0:
            with db_instance() as db:
                db.select(query)
                return db.dictfetchall
        else:
            logger.warn("Query was empty for {0}: {1}".format(name, query))
            return {}
Пример #6
0
    def get_download_urls(self,
                          entity_ids,
                          dataset,
                          products='STANDARD',
                          stage=True,
                          usage='[espa]:sr'):
        """
        Fetch the download location for supplied IDs, replacing the public host
            with an internal network host (to bypass public firewall routing)

        :param product_ids: Landsat Collection IDs ['LC08_..', ...]
        :type product_ids: list
        :param products: download type to grab (STANDARD is for L1-GeoTIFF)
        :type products: str
        :param stage: If true, initiates a data stage command
        :type stage: bool
        :param usage: Identify higher level products this data is used to create
        :type usage: str
        :return: dict
        """
        payload = dict(apiKey=self.token,
                       datasetName=dataset,
                       products=products,
                       entityIds=entity_ids,
                       stage=stage,
                       dataUse=usage)
        resp = self._post('download', payload)
        results = resp.get('data')

        if results:
            # Use the URL taken directly from the M2M JSON API if VIIRS
            if 'VNP' in dataset:
                return {i['entityId']: i['url'] for i in results}
            # For now, let's keep the original M2M download url for sentinel
            elif 'SENTINEL' in dataset:
                return {i['entityId']: i['url'] for i in results}
            # Otherwise use our internal network conversion
            else:
                return self.network_urls(
                    self.network_urls(
                        {i['entityId']: i['url']
                         for i in results}, 'landsat'), 'modis')
        else:
            logger.warn(
                "inventory.get_download_urls - no data in POST response returned for entity_ids: {}, dataset: {}"
                .format(entity_ids, dataset))
Пример #7
0
    def check(self, order, contactid=None):
        ids = sensor.SensorCONST.instances.keys()

        lta_ls = []
        lpdaac_ls = []
        results = {}
        for key in order:
            l1 = ''
            if key in ids:
                inst = sensor.instance(order[key]['inputs'][0])
                l1 = inst.l1_provider

            if l1 == 'dmid':
                lta_ls.extend(order[key]['inputs'])
            elif l1 == 'lpdaac':
                lpdaac_ls.extend(order[key]['inputs'])

        if lta_ls:
            if inventory.available():
                results.update(self.check_dmid(lta_ls, contactid))
            else:
                msg = 'Could not connect to Landsat data source'
                raise InventoryConnectionException(msg)

        if lpdaac_ls:
            if inventory.available():
                logger.warn('Checking M2M Inventory for LP DAAC granules')
                try:
                    results.update(self.check_dmid(lpdaac_ls, contactid))
                except InventoryException:
                    logger.warn("Unable to verify inventory with DMID")
            elif lpdaac.check_lpdaac_available():
                try:
                    results.update(self.check_LPDAAC(lpdaac_ls))
                except InventoryException:
                    logger.warn("Unable to verify inventory with LPDAAC")
            else:
                msg = "Could not connect to any data source to verify LPDAAC products"
                raise InventoryConnectionException(msg)

        not_avail = []
        for key, val in results.items():
            if not val:
                not_avail.append(key)

        if not_avail:
            raise InventoryException(not_avail)
Пример #8
0
                try:
                    response = requests.head(url)
                    if response.ok is True:
                        result = True
                except Exception, e:
                    logger.exception('Exception checking modis input {0}\n '
                                     'Exception:{1}'
                                     .format(url, e))
                    return result
                finally:
                    if response is not None:
                        response.close()
                        response = None

        except sensor.ProductNotImplemented:
            logger.warn('{0} is not an implemented LPDAAC product'
                        .format(product))

        return result

    def get_download_url(self, product):

        url = {}

        #be nice and accept a string
        if isinstance(product, str) or isinstance(product, unicode):
            product = sensor.instance(product)

        #also be nice and accept a sensor.Modis object
        if isinstance(product, sensor.Modis):

            path = self._build_modis_input_file_path(product)
Пример #9
0
class OrderWrapperServiceClient(LTAService):
    '''LTA's OrderWrapper Service is a business process service that handles
    populating demographics and interacting with the inventory properly when
    callers order data.  It is implemented as a REST style service that passes
    schema-bound XML as the payload.

    This is the preferred method for ordering data from the LTA (instead of
    calling TRAM services directly), as there are multiple service calls that
    must be performed when placing orders, and only the LTA team really know
    what those calls are.  Their services are largely undocumented.
    '''
    service_name = 'orderservice'

    def __init__(self, *args, **kwargs):
        super(OrderWrapperServiceClient, self).__init__(*args, **kwargs)

    def verify_scenes(self, scene_list):
        ''' Checks to make sure the scene list is valid, where valid means
        the scene ids supplied exist in the Landsat inventory and are orderable

        Keyword args:
        scene_list A list of scenes to be verified

        Returns:
        A dictionary with keys matching the scene list and values are 'true'
        if valid, and 'false' if not.

        Return value example:
        dictionary = dict()
        dictionary['LT51490212007234IKR00'] = True
        dictionary['asdf'] = False
        ...
        ...
        ...

        '''

        #build the service + operation url
        request_url = '{0}/verifyScenes'.format(self.url)

        #build the request body
        sb = StringIO()
        sb.write(self.xml_header)

        head = ("<sceneList "
                "xmlns='https://earthexplorer.usgs.gov/schema/sceneList' "
                "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
                "xsi:schemaLocation="
                "'https://earthexplorer.usgs.gov/schema/sceneList "
                "https://earthexplorer.usgs.gov/EE/sceneList.xsd'>")

        sb.write(head)

        for s in scene_list:
            product = sensor.instance(s)
            sb.write("<sceneId sensor='{0}'>{1}</sceneId>"
                     .format(product.lta_name, s.upper()))

        sb.write("</sceneList>")

        request_body = sb.getvalue()

        #set the required headers
        headers = dict()
        headers['Content-Type'] = 'application/xml'
        headers['Content-Length'] = len(request_body)

        #send the request and check return status
        #print "*** request_url: ", request_url
        #print "*** request_body: ", request_body
        #print "*** headers: ", headers
        __response = requests.post(request_url,
                                   data=request_body,
                                   headers=headers)

        response = None

        if __response.ok:
            response = __response.content
        else:
            msg = StringIO()
            msg.write("Error in lta.OrderWrapperServiceClient.verify_scenes\n")
            msg.write("Non 200 response code from service\n")
            msg.write("Response code was:{0}".format( __response.status_code))
            msg.write("Reason:{0}".format(__response.reason))
            # Return the code and reason as an exception
            raise Exception(msg.getvalue())

        __response.close()

        #parse, transform and return response
        retval = dict()
        response = response.replace('&', '&amp;')
        response = response.replace('\n', '')

        root = xml.fromstring(response)
        scenes = root.getchildren()

        for s in list(scenes):
            if s.attrib['valid'] == 'true':
                status = True
            else:
                status = False

            retval[s.text] = status

        return retval

    def order_scenes(self, scene_list, contact_id, priority=5):
        ''' Orders scenes through OrderWrapperService

        Keyword args:
        scene_list A list of scene ids to order
        contactId  The EE user id that is ordering the data
        priority   The priority placed on the backend ordering system.
                   Landsat has asked us to set the priority to 5 for all ESPA
                   orders.

        Returns:
        A dictionary containing the lta_order_id and up to three lists of scene
        ids, organized by their status.  If there are no scenes in the
        ordered status, the ordered list and the lta_order_id will not be
        present.  If there are no scenes in either the invalid or available
        status, then those respective lists will not be present.

        Example 1 (Scenes in each status):
        {
            'lta_order_id': 'abc123456',
            'ordered': ['scene1', 'scene2', 'scene3'],
            'invalid': ['scene4', 'scene5', 'scene6'],
            'available': ['scene7', 'scene8', 'scene9']
         }

        Example 2 (No scenes ordered):
        {
            'invalid': ['scene1', 'scene2', 'scene3'],
            'available': ['scene4', 'scene5', 'scene6']
        }

        Example 3 (No scenes available):
        {
            'lta_order_id': 'abc123456',
            'ordered': ['scene1', 'scene2', 'scene3'],
            'invalid': ['scene4', 'scene5', 'scene6']
        }
        '''

        # build service url
        request_url = '{0}/submitOrder'.format(self.url)

        def build_request(contact_id, priority, product_list):
            # build the request body
            sb = StringIO()
            sb.write(self.xml_header)

            head = ("<orderParameters "
                    "xmlns="
                    "'https://earthexplorer.usgs.gov/schema/orderParameters' "
                    "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
                    "xsi:schemaLocation="
                    "'https://earthexplorer.usgs.gov/schema/orderParameters "
                    "https://earthexplorer.usgs.gov/EE/orderParameters.xsd'>")

            sb.write(head)
            sb.write('<contactId>{0}</contactId>'.format(contact_id))
            sb.write('<requestor>ESPA</requestor>')

            # 1111111 is a dummy value.
            sb.write('<externalReferenceNumber>{0}</externalReferenceNumber>'
                     .format(1111111))

            sb.write('<priority>{0}</priority>'.format(priority))

            product_info = self.get_download_urls(product_list, contact_id)

            for p in product_info.keys():

                try:
                    sensor.instance(p)
                except sensor.ProductNotImplemented, pne:
                    raise pne
                else:
                    sb.write('<scene>')
                    sb.write('<sceneId>{0}</sceneId>'.format(p))
                    sb.write('<prodCode>{0}</prodCode>'
                             .format(product_info[p]['lta_code']))
                    sb.write('<sensor>{0}</sensor>'
                             .format(product_info[p]['sensor']))
                    sb.write('</scene>')

            sb.write('</orderParameters>')

            request_body = sb.getvalue()

            return request_body

        payload = build_request(contact_id, priority, scene_list)
        # set the required headers
        headers = dict()
        headers['Content-Type'] = 'application/xml'
        headers['Content-Length'] = len(payload)

        # send the request and check response

        __response = requests.post(request_url, data=payload, headers=headers)

        if __response.ok:
            response = __response.content
        else:
            logger.critical('Non 200 response from lta.order_scenes, '
                            'Response:{0}, '
                            'Request:{1}'.format(__response.content, payload))
            msg = StringIO()
            msg.write('Error in lta.OrderWrapperServiceClient.order_scenes\n')
            msg.write('Non 200 response code from service\n')
            msg.write('Response code was:{0}'.format(__response.status_code))
            msg.write('Reason:{0}'.format(__response.reason))
            
            raise Exception(msg.getvalue())

        __response.close()

        # parse the response
        '''
        Example response for scenes

        <?xml version="1.0" encoding="UTF-8"?>
        <orderStatus xmlns="http://earthexplorer.usgs.gov/schema/orderStatus"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://host/schema/orderStatus
            http://host/OrderWrapperServicedevsys/orderStatus.xsd">

            <scene>
                <sceneId>LT51490212007234IKR00</sceneId>
                <prodCode>T273</prodCode>
                <sensor>LANDSAT_TM</sensor>
                <status>ordered</status>
                <orderNumber>0621405213419</orderNumber>
            </scene>

            <scene>
                <sceneId>LE70290302013153EDC00</sceneId>
                <prodCode>T271</prodCode>
                <sensor>LANDSAT_ETM_SLC_OFF</sensor>
                <status>available</status>
                <downloadURL>http://one_time_use.tar.gz</downloadURL>
            </scene>

            <scene>
                <sceneId>LE70290302003142EDC00</sceneId>
                <prodCode>T272</prodCode>
                <sensor>LANDSAT_ETM_PLUS</sensor>
                <status>invalid</status>
            </scene>

        </orderStatus>
        '''

        logger.warn('Ordering scenes SOAP response:{0}'.format(response))

        # since the xml is namespaced there is a namespace prefix for every
        # element we are looking for.  Build those values to make the code
        # a little more sane
        schema = 'orderStatus'
        # leave this here for now.  We aren't using it yet but will when EE
        # straightens out their urls + internal dowloading capability
        #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.replace('&', '&amp;').replace('\n', '')

        #this will get us the list of <scene></scene> elements
        scene_elements = xml.fromstring(response).getchildren()

        # the dictionary we will return as the response
        # contains the lta_order_id at the top (if anything is ordered)
        # and possibly three lists of scenes, one for each status
        # retval['available'] = list()
        # retval['invalid'] = list()
        # retval['ordered'] = list()
        retval = dict()

        for scene in scene_elements:

            name = self.get_xml_item(scene, schema, 'sceneId').text
            status = self.get_xml_item(scene, schema, 'status').text

            if status == 'available':
                values = retval.get(status, []) + [name]
                retval.update(available=values)
            elif status == 'invalid':
                retval.update(invalid=retval.get(status, []) + [name])
            elif status == 'ordered':
                retval.update(ordered=retval.get(status, []) + [name])
                order_num = self.get_xml_item(scene, schema, 'orderNumber').text
                values = retval.get('lta_order_id', ()) + (order_num,)
                retval.update(lta_order_id=values)

        return retval
Пример #10
0
class OrderDeliveryServiceClient(LTASoapService):
    '''EE SOAP Service client to find orders for ESPA which originated in EE'''

    service_name = 'orderdelivery'

    def __init__(self, *args, **kwargs):
        super(OrderDeliveryServiceClient, self).__init__(*args, **kwargs)

    def get_available_orders(self):
        ''' Returns all the orders that were submitted for ESPA through EE

        Returns:
        A dictionary of lists that contain dictionaries

        response[ordernumber, email, contactid] = [
            {'sceneid':orderingId, 'unit_num':unitNbr},
            {...}
        ]
        '''
        rtn = dict()
        # resp = self.client.factory.create("getAvailableOrdersResponse")

        try:
            resp = self.client.service.getAvailableOrders("ESPA")
        except Exception, e:
            raise e

        #if there were none jusgetAvailt return
        if len(resp.units) == 0:
            return rtn

        #return these to the caller.
        for u in resp.units.unit:

            #ignore anything that is not for us
            if str(u.productCode).lower() not in ('sr01', 'sr02', 'sr03', 'sr04', 'sr05'):

                logger.warn('{0} is not an ESPA product. Order[{1}] Unit[{2}]'
                            'Product code[{3}]... ignoring'
                             .format(u.orderingId, u.orderNbr,
                                     u.unitNbr, u.productCode))
                # continue

            # get the processing parameters
            pp = u.processingParam

            try:
                email = pp[pp.index("<email>") + 7:pp.index("</email>")]
            except:
                logger.warn('Could not find an email address for '
                            'unit {0} in order {1] : rejecting'
                            .format(u.unitNbr,u.orderNbr))

                # we didn't get an email... fail the order
                resp = OrderUpdateServiceClient().update_order(u.orderNbr,
                                                               u.unitNbr,
                                                               "R")
                # we didn't get a response from the service
                if not resp.success:
                    raise Exception('Could not update order[{0}] unit[{1}] '
                                    'to status:F. Error message:{2} '
                                    'Error status code:{3}'
                                    .format(u.orderNbr,
                                            u.unitNbr,
                                            resp.message,
                                            resp.status))
                else:
                    continue

            try:
                # get the contact id
                cid = pp[pp.index("<contactid>") + 11:pp.index("</contactid>")]
            except:
                logger.warn('Could not find a contactid for unit {0} in '
                            'order {1}... rejecting'
                            .format(u.unitNbr, u.orderNbr))

                # didn't get an email... fail the order
                resp = OrderUpdateServiceClient().update_order(u.orderNbr,
                                                               u.unitNbr,
                                                               "R")
                # didn't get a response from the service
                if not resp.success:
                    raise Exception('Could not update unit {0} in order {1} '
                                    'to status:F. Error message:{2} '
                                    'Error status code:{3}'
                                    .format(u.orderNbr,
                                            u.unitNbr,
                                            resp.message,
                                            resp.status))
                else:
                    continue

            # This is a dictionary that contains a list of dictionaries
            key = (str(u.orderNbr), str(email), str(cid))

            if not key in rtn:
                rtn[key] = list()

            rtn[key].append({'sceneid': str(u.orderingId),
                             'unit_num': int(u.unitNbr)}
                            )

        return rtn