Ejemplo n.º 1
0
    def get(self, index_id=None, object_key_name=None):
        """Perform GET request and generate response."""
        if index_id is None:
            self._logger.error("Index Id is required.")
            return False, None
        if object_key_name is None:
            self._logger.error("Key is required")
            return False, None

        # The URL quoting functions focus on taking program data and making it safe for use as URL components by quoting special characters and appropriately encoding non-ASCII text.
        # https://docs.python.org/3/library/urllib.parse.html
        # For example if index_id is 'AAAAAAAAAHg=-AwAQAAAAAAA=' and object_key_name is "testobject+"
        # urllib.parse.quote(index_id, safe='') and urllib.parse.quote(object_key_name) yields 'testobject%2B' respectively
        # And request_uri is
        # '/indexes/AAAAAAAAAHg%3D-AwAQAAAAAAA%3D/testobject%2B'

        request_uri = '/indexes/' + \
            urllib.parse.quote(index_id, safe='') + '/' + \
            urllib.parse.quote(object_key_name)

        query_params = ""
        body = ""
        headers = self.s3_util.prepare_signed_header('GET', request_uri,
                                                     query_params, body)

        if (headers['Authorization'] is None):
            self._logger.error("Failed to generate v4 signature")
            return False, None

        try:
            response = super(CORTXS3KVApi, self).get(request_uri,
                                                     headers=headers)
        except ConnectionRefusedError as ex:
            IEMutil("ERROR", IEMutil.S3_CONN_FAILURE,
                    IEMutil.S3_CONN_FAILURE_STR)
            self._logger.error(repr(ex))
            return False, CORTXS3ErrorResponse(502, "", "ConnectionRefused")
        except Exception as ex:
            self._logger.error(repr(ex))
            return False, CORTXS3ErrorResponse(500, "", "InternalServerError")

        if response['status'] == 200:
            self._logger.info("Get kv operation successfully.")
            return True, CORTXS3GetKVResponse(object_key_name,
                                              response['body'])
        else:
            self._logger.info('Failed to get kv details.')
            return False, CORTXS3ErrorResponse(response['status'],
                                               response['reason'],
                                               response['body'])
def test_object_metadata_exists_mismatches():
    """Test if ObjectRecoveryValidator should attempt delete for object oid """
    index_api_mock = Mock(spec=CORTXS3IndexApi)
    kv_api_mock = Mock(spec=CORTXS3KVApi)
    object_api_mock = Mock(spec=CORTXS3ObjectApi)

    ol_res_val = {
        'ACL': '',
        'Bucket-Name': 'mybucket',
        'Object-Name': 'test_object',
        'Object-URI': 'mybucket\\test_object',
        'create_timestamp': '2020-03-17T11:02:13.000Z',
        'layout_id': 9,
        'motr_oid': 'TAifBwAAAHg=-AQAAAAAA2lk='
    }

    index_content = {
        'Delimiter': '',
        'Index-Id': 'AAAAAAAAAHg=-BAAQAAAAAAA=',
        'IsTruncated': 'false',
        'Keys': [{
            'Key': 'test_object',
            'Value': ol_res_val
        }],
        'Marker': '',
        'MaxKeys': '1000',
        'NextMarker': '',
        'Prefix': ''
    }

    index_response = CORTXS3ListIndexResponse(
        json.dumps(index_content).encode())
    object_key = ol_res_val["Object-Name"]
    # oid mismatches in object metadata
    object_metadata = ol_res_val

    kv_response = CORTXS3GetKVResponse(object_key,
                                       json.dumps(object_metadata).encode())

    index_api_mock.list.return_value = True, index_response
    kv_api_mock.get.return_value = True, kv_response
    object_api_mock.delete.return_value = True, {}

    config = CORTXS3Config()
    probable_delete_records = {'Key': 'Tgj8AgAAAAA=-dQAAAAAABCY=', \
        'Value':'{"motr_process_fid":"<0x7200000000000000:0>","create_timestamp":"2020-03-16T16:24:04.000Z", \
        "force_delete":"false","global_instance_id":"TAifBwAAAAA=-AAAAAAAA2lk=","is_multipart":"false", \
        "object_key_in_index":"object_1","object_layout_id":9,"pv_id":"AQAAAAAAAHYKAAAAAAAAAA==","object_list_index_oid":"TAifBwAAAHg=-AQAAAAAA2lk=", \
        "objects_version_list_index_oid":"TAifBwAAAHg=-AwAAAAAA2lk=","old_oid":"AAAAAAAAAAA=-AAAAAAAAAAA=", \
        "version_key_in_index":"object_1/18446742489333709430"}\n'                                                                  }

    validator = ObjectRecoveryValidator(config,
                                        probable_delete_records,
                                        objectapi=object_api_mock,
                                        kvapi=kv_api_mock,
                                        indexapi=index_api_mock)

    #Mock 'process_probable_delete_record'
    validator.process_probable_delete_record = MagicMock(return_value=True)

    validator.process_results()

    # Assert that object oid delete and leak index entry delete
    # is triggered if metadata doesn't exists.
    validator.process_probable_delete_record.assert_called == True