def setUp(self):
        super(TestReconstructorRebuild, self).setUp()
        # create EC container
        headers = {'X-Storage-Policy': self.policy.name}
        client.put_container(self.url,
                             self.token,
                             self.container_name,
                             headers=headers)

        # PUT object and POST some metadata
        self.proxy_put()
        self.headers_post = {
            self._make_name('x-object-meta-').decode('utf8'):
            self._make_name('meta-bar-').decode('utf8')
        }
        client.post_object(self.url,
                           self.token,
                           self.container_name,
                           self.object_name,
                           headers=dict(self.headers_post))

        self.opart, self.onodes = self.object_ring.get_nodes(
            self.account, self.container_name, self.object_name)

        # stash frag etags and metadata for later comparison
        self.frag_headers, self.frag_etags = self._assert_all_nodes_have_frag()
        for node_index, hdrs in self.frag_headers.items():
            # sanity check
            self.assertIn(
                'X-Backend-Durable-Timestamp', hdrs,
                'Missing durable timestamp in %r' % self.frag_headers)
Example #2
0
def _set_headers(storage_url, auth_token, container, object_name, deleted):
    try:
        header = client.head_object(storage_url, auth_token, container,
                                    object_name)
        new_header = {
            'X-Object-Meta-Deleted': deleted,
            'X-Object-Meta-Format': header['x-object-meta-format'],
            'X-Object-Meta-Resolution': header['x-object-meta-resolution'],
            'X-Object-Meta-Name': header['x-object-meta-name'],
            'X-Object-Meta-Type': header['x-object-meta-type']
        }
        copy_of = None
        if header['x-object-meta-type'] == 'thumbnail':
            new_header['X-Object-Meta-Original'] = header[
                'x-object-meta-original']
            copy_of = header['x-object-meta-original']
        if header['x-object-meta-type'] == 'original':
            new_header['X-Object-Meta-Thumb'] = header['x-object-meta-thumb']
            copy_of = header['x-object-meta-thumb']
        client.post_object(storage_url,
                           auth_token,
                           container,
                           object_name,
                           headers=new_header)
        return copy_of
    except swift_exception.ClientException as e:
        raise e
    except Exception as e:
        raise e
    def test_unicode_ok(self):
        conn = c.http_connection(u'http://www.test.com/')
        args = (u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91')
        text = u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91'
        headers = {'X-Header1': text,
                   b'X-Header2': 'value',
                   'X-2': '1', 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr',
                   'X-Object-Meta-Header-not-encoded': text,
                   b'X-Object-Meta-Header-encoded': 'value'}

        resp = MockHttpResponse()
        conn[1].getresponse = resp.fake_response
        conn[1]._request = resp._fake_request
        c.post_object(*args, headers=headers, http_conn=conn)
        # Test for RFC-2616 encoded symbols
        self.assertIn(('a-b', b".x:yz mn:kl:qr"), resp.buffer)
        # Test unicode header
        self.assertIn(('x-header1', text.encode('utf8')),
                      resp.buffer)
        self.assertIn((b'x-object-meta-header-not-encoded',
                      text.encode('utf8')), resp.buffer)
        self.assertIn((b'x-object-meta-header-encoded', b'value'),
                      resp.buffer)
        self.assertIn((b'x-header2', b'value'), resp.buffer)
    def setUp(self):
        super(TestReconstructorRebuild, self).setUp()
        self.container_name = 'container-%s' % uuid.uuid4()
        self.object_name = 'object-%s' % uuid.uuid4()
        # sanity
        self.assertEqual(self.policy.policy_type, EC_POLICY)
        self.reconstructor = Manager(["object-reconstructor"])

        # create EC container
        headers = {'X-Storage-Policy': self.policy.name}
        client.put_container(self.url, self.token, self.container_name,
                             headers=headers)

        # PUT object and POST some metadata
        contents = Body()
        headers = {'x-object-meta-foo': 'meta-foo'}
        self.headers_post = {'x-object-meta-bar': 'meta-bar'}

        self.etag = client.put_object(self.url, self.token,
                                      self.container_name,
                                      self.object_name,
                                      contents=contents, headers=headers)
        client.post_object(self.url, self.token, self.container_name,
                           self.object_name, headers=dict(self.headers_post))

        self.opart, self.onodes = self.object_ring.get_nodes(
            self.account, self.container_name, self.object_name)

        # stash frag etags and metadata for later comparison
        self.frag_headers, self.frag_etags = self._assert_all_nodes_have_frag()
        for node_index, hdrs in self.frag_headers.items():
            # sanity check
            self.assertIn(
                'X-Backend-Durable-Timestamp', hdrs,
                'Missing durable timestamp in %r' % self.frag_headers)
Example #5
0
    def test_unicode_ok(self):
        conn = c.http_connection(u'http://www.test.com/')
        args = (u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91')
        text = u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91'
        headers = {
            'X-Header1': text,
            b'X-Header2': 'value',
            'X-2': '1',
            'X-3': {
                'a': 'b'
            },
            'a-b': '.x:yz mn:kl:qr',
            'X-Object-Meta-Header-not-encoded': text,
            b'X-Object-Meta-Header-encoded': 'value'
        }

        resp = MockHttpResponse()
        conn[1].getresponse = resp.fake_response
        conn[1]._request = resp._fake_request
        c.post_object(*args, headers=headers, http_conn=conn)
        # Test for RFC-2616 encoded symbols
        self.assertIn(('a-b', b".x:yz mn:kl:qr"), resp.buffer)
        # Test unicode header
        self.assertIn(('x-header1', text.encode('utf8')), resp.buffer)
        self.assertIn(
            (b'x-object-meta-header-not-encoded', text.encode('utf8')),
            resp.buffer)
        self.assertIn((b'x-object-meta-header-encoded', b'value'), resp.buffer)
        self.assertIn((b'x-header2', b'value'), resp.buffer)
Example #6
0
def convert(vid_format, videos, local_file, container, storage_url, auth_token, this_id, id_original, c):
    temp_file = videos[vid_format]['temp_file']
    headers = _get_video_headers(storage_url, auth_token, container, this_id)
    conv = c.convert(local_file, temp_file, videos[vid_format]['options'])
    for ftimecode in conv:
        timecode = int(ftimecode * 100)
        if timecode == 100:
            break
        video_keys[id_original][vid_format + 'status'] = int(timecode)
        headers['X-Object-Meta-Status'] = timecode
        client.post_object(storage_url, auth_token, container, this_id, headers=headers)
        print "Converting %s (%f) ...%s\n" % (vid_format, timecode, local_file)
    if os.path.exists(temp_file):
        size = os.path.getsize(temp_file)
        print '\n\nSIZE: ', size, '\n\n'
    headers = _get_video_headers(storage_url, auth_token, container, this_id)
    headers['X-Object-Meta-Content-Type'] = 'video/' + vid_format
    headers['X-Object-Meta-Status'] = 100
    try:
        with open(temp_file, 'r+b') as f:
            client.put_object(storage_url, auth_token, container, this_id, f, headers=headers)
    except swift_exception.ClientException as e:
        storage_url, auth_token = _reauthorize(request)
        with open(temp_file, 'r+b') as f:
            client.put_object(storage_url, auth_token, container, this_id, f, headers=headers)
    video_keys[id_original][vid_format + 'status'] = 100
    if os.path.exists(temp_file):
        os.remove(temp_file)
 def test_server_error(self):
     body = 'c' * 60
     c.http_connection = self.fake_http_connection(500, body=body)
     args = ('http://www.test.com', 'asdf', 'asdf', 'asdf', {})
     self.assertRaises(c.ClientException, c.post_object, *args)
     try:
         c.post_object(*args)
     except c.ClientException as e:
         self.assertEqual(e.http_response_content, body)
 def test_server_error(self):
     body = 'c' * 60
     c.http_connection = self.fake_http_connection(500, body=body)
     args = ('http://www.test.com', 'asdf', 'asdf', 'asdf', {})
     self.assertRaises(c.ClientException, c.post_object, *args)
     try:
         c.post_object(*args)
     except c.ClientException as e:
         self.assertEquals(e.http_response_content, body)
Example #9
0
 def commitMeta(self):
     if self._commitList != {}:
         post_object(
             self._url,
             self._token,
             Configuration.container_name,
             self._objId,
             self._commitList)
     self._commitList = {}
Example #10
0
    def test_sync_unexpired_object_metadata(self):
        # verify that metadata can be sync'd to a frag that has missed a POST
        # and consequently that frag appears to be expired, when in fact the
        # POST removed the x-delete-at header
        client.put_container(self.url, self.token, self.container_name,
                             headers={'x-storage-policy': self.policy.name})
        opart, onodes = self.object_ring.get_nodes(
            self.account, self.container_name, self.object_name)
        delete_at = int(time.time() + 3)
        contents = 'body-%s' % uuid.uuid4()
        headers = {'x-delete-at': delete_at}
        client.put_object(self.url, self.token, self.container_name,
                          self.object_name, headers=headers, contents=contents)
        # fail a primary
        post_fail_node = random.choice(onodes)
        post_fail_path = self.device_dir('object', post_fail_node)
        self.kill_drive(post_fail_path)
        # post over w/o x-delete-at
        client.post_object(self.url, self.token, self.container_name,
                           self.object_name, {'content-type': 'something-new'})
        # revive failed primary
        self.revive_drive(post_fail_path)
        # wait for the delete_at to pass, and check that it thinks the object
        # is expired
        timeout = time.time() + 5
        while time.time() < timeout:
            try:
                direct_client.direct_head_object(
                    post_fail_node, opart, self.account, self.container_name,
                    self.object_name, headers={
                        'X-Backend-Storage-Policy-Index': int(self.policy)})
            except direct_client.ClientException as err:
                if err.http_status != 404:
                    raise
                break
            else:
                time.sleep(0.1)
        else:
            self.fail('Failed to get a 404 from node with expired object')
        self.assertEqual(err.http_status, 404)
        self.assertIn('X-Backend-Timestamp', err.http_headers)

        # but from the proxy we've got the whole story
        headers, body = client.get_object(self.url, self.token,
                                          self.container_name,
                                          self.object_name)
        self.assertNotIn('X-Delete-At', headers)
        self.reconstructor.once()

        # ... and all the nodes have the final unexpired state
        for node in onodes:
            headers = direct_client.direct_head_object(
                node, opart, self.account, self.container_name,
                self.object_name, headers={
                    'X-Backend-Storage-Policy-Index': int(self.policy)})
            self.assertNotIn('X-Delete-At', headers)
Example #11
0
def set_object_expiry_time(request, container, objectname):
    """For the given object, set the x-delete-at. """
    storage_url = request.session.get('storage_url', '')
    auth_token = request.session.get('auth_token', '')
    form = TimeForm(request.POST)

    if form.is_valid():

        days_to_expiry = float(form.cleaned_data['days'])
        hours_to_expiry = float(form.cleaned_data['hours'])

        # When these values are zero, remove expiration
        if (days_to_expiry + hours_to_expiry == 0.0):
            try:
                client.post_object(
                    storage_url,
                    auth_token,
                    container,
                    objectname,
                    {})
                messages.add_message(
                    request,
                    messages.INFO,
                    _("Object expiry time removed!"))
            except Exception:
                messages.error(request, "Error updating object expiry time.")
        else:
            seconds_to_expiry = int(time.time()) + int(
                days_to_expiry * 24 * 3600
                + hours_to_expiry * 60 * 60)

            try:
                client.post_object(
                    storage_url,
                    auth_token,
                    container,
                    objectname,
                    {"x-delete-at": seconds_to_expiry})
                messages.add_message(
                    request,
                    messages.INFO,
                    _("Object expiry time updated!"))
            except Exception:
                messages.error(request, "Error updating object expiry time.")

        prefix = '/'.join(objectname.split('/')[:-1])
        if prefix:
            prefix += '/'

    else:
        messages.error(request, "Invalid form.")

    return redirect(swiftbrowser.views.objectview, container, prefix)
    def test_unicode_ok(self):
        conn = c.http_connection(u'http://www.test.com/')
        args = (u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                '\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91')
        headers = { #'X-Header1': u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                   'X-2': 1, 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr'}

        resp = MockHttpResponse()
        conn[1].getresponse = resp.fake_response
        conn[1].send = resp.fake_send
        c.post_object(*args, headers=headers, http_conn=conn)
        # Test for RFC-2616 encoded symbols
        self.assertTrue("a-b: .x:yz mn:kl:qr" in resp.buffer[0],
                        "[a-b: .x:yz mn:kl:qr] header is missing")
Example #13
0
    def test_unicode_ok(self):
        conn = c.http_connection(u'http://www.test.com/')
        args = (u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                '\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91')
        headers = {'X-Header1': u'\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91',
                   'X-2': '1', 'X-3': {'a': 'b'}, 'a-b': '.x:yz mn:kl:qr'}

        resp = MockHttpResponse()
        conn[1].getresponse = resp.fake_response
        conn[1].send = resp.fake_send
        c.post_object(*args, headers=headers, http_conn=conn)
        # Test for RFC-2616 encoded symbols
        self.assertTrue("a-b: .x:yz mn:kl:qr" in resp.buffer[0],
                        "[a-b: .x:yz mn:kl:qr] header is missing")
Example #14
0
    def test_main(self):
        # create EC container
        headers = {'X-Storage-Policy': self.policy.name}
        client.put_container(self.url,
                             self.token,
                             self.container_name,
                             headers=headers)

        # PUT object
        contents = Body()
        headers = {'x-object-meta-foo': 'meta-foo'}
        headers_post = {'x-object-meta-bar': 'meta-bar'}

        etag = client.put_object(self.url,
                                 self.token,
                                 self.container_name,
                                 self.object_name,
                                 contents=contents,
                                 headers=headers)
        client.post_object(self.url,
                           self.token,
                           self.container_name,
                           self.object_name,
                           headers=headers_post)
        del headers_post['X-Auth-Token']  # WTF, where did this come from?

        # built up a list of node lists to kill data from,
        # first try a single node
        # then adjacent nodes and then nodes >1 node apart
        opart, onodes = self.object_ring.get_nodes(self.account,
                                                   self.container_name,
                                                   self.object_name)
        single_node = [random.choice(onodes)]
        adj_nodes = [onodes[0], onodes[-1]]
        far_nodes = [onodes[0], onodes[-2]]
        test_list = [single_node, adj_nodes, far_nodes]

        for node_list in test_list:
            for onode in node_list:
                try:
                    self._check_node(onode, opart, etag, headers_post)
                except AssertionError as e:
                    self.fail(
                        str(e) + '\n... for node %r of scenario %r' %
                        (self._format_node(onode),
                         [self._format_node(n) for n in node_list]))
 def test_server_error(self):
     body = "c" * 60
     c.http_connection = self.fake_http_connection(500, body=body)
     args = ("http://www.test.com", "asdf", "asdf", "asdf", {})
     self.assertRaises(c.ClientException, c.post_object, *args)
     try:
         value = c.post_object(*args)
     except c.ClientException as e:
         self.assertEquals(e.http_response_content, body)
    def test_unicode_ok(self):
        conn = c.http_connection(u"http://www.test.com/")
        args = (
            u"\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91",
            "\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91",
            u"\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91",
            u"\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91",
        )
        text = u"\u5929\u7a7a\u4e2d\u7684\u4e4c\u4e91"
        headers = {"X-Header1": text, "X-2": "1", "X-3": {"a": "b"}, "a-b": ".x:yz mn:kl:qr"}

        resp = MockHttpResponse()
        conn[1].getresponse = resp.fake_response
        conn[1]._request = resp._fake_request
        c.post_object(*args, headers=headers, http_conn=conn)
        # Test for RFC-2616 encoded symbols
        self.assertTrue((b"a-b", b"a-b: .x:yz mn:kl:qr"), resp.buffer)
        # Test unicode header
        self.assertIn((b"x-header1", text.encode("utf8")), resp.buffer)
Example #17
0
def _set_headers(storage_url, auth_token, container, object_name, deleted, request):
    try:
        try:
            header = client.head_object(storage_url, auth_token, container, object_name)
        except swift_exception.ClientException as e:
            storage_url, auth_token = _reauthorize(request)
            header = client.head_object(storage_url, auth_token, container, object_name)

        new_header = {'X-Object-Meta-Deleted': deleted,
                      'X-Object-Meta-Format': header['x-object-meta-format'],
                      'X-Object-Meta-Resolution': header['x-object-meta-resolution'],
                      'X-Object-Meta-Name': header['x-object-meta-name'],
                      'X-Object-Meta-Type': header['x-object-meta-type']
                      }
        copy_of = None
        if (header['x-object-meta-format'] in video_types) and (header['x-object-meta-type'] == 'original'):
            new_header['X-Object-Meta-Mp4-Id'] = header['x-object-meta-mp4-id']

        if 'x-object-meta-status' in header:
            new_header['X-Object-Meta-Status'] = header['x-object-meta-status']

        if header['x-object-meta-type'] == 'thumbnail':
            new_header['X-Object-Meta-Original'] = header['x-object-meta-original']
            copy_of = header['x-object-meta-original']
        if header['x-object-meta-type'] == 'original':
            new_header['X-Object-Meta-Thumb'] = header['x-object-meta-thumb']
            if container == 'Video':
                copy_of = [header['x-object-meta-thumb'], header['x-object-meta-mp4-id']]
            else:
                copy_of = header['x-object-meta-thumb']
            if 'x-object-meta-preview-id' in header:
                new_header['X-Object-Meta-Preview-Id'] = header['x-object-meta-preview-id']
                copy_of = [header['x-object-meta-thumb'], header['x-object-meta-preview-id']]
        try:
            client.post_object(storage_url, auth_token, container, object_name, headers=new_header)
        except swift_exception.ClientException as e:
            storage_url, auth_token = _reauthorize(request)
            client.post_object(storage_url, auth_token, container, object_name, headers=new_header)
        return copy_of
    except swift_exception.ClientException as e:
        raise e
    except Exception as e:
        raise e
Example #18
0
def _set_headers(storage_url, auth_token, container, object_name, deleted):
    try:
        header = client.head_object(storage_url, auth_token, container, object_name)
        new_header = {'X-Object-Meta-Deleted': deleted,
                      'X-Object-Meta-Format': header['x-object-meta-format'],
                      'X-Object-Meta-Resolution': header['x-object-meta-resolution'],
                      'X-Object-Meta-Name': header['x-object-meta-name'],
                      'X-Object-Meta-Type': header['x-object-meta-type']
                      }
        copy_of = None
        if header['x-object-meta-type'] == 'thumbnail':
            new_header['X-Object-Meta-Original'] = header['x-object-meta-original']
            copy_of = header['x-object-meta-original']
        if header['x-object-meta-type'] == 'original':
            new_header['X-Object-Meta-Thumb'] = header['x-object-meta-thumb']
            copy_of = header['x-object-meta-thumb']
        client.post_object(storage_url, auth_token, container, object_name, headers=new_header)
        return copy_of
    except swift_exception.ClientException as e:
        raise e
    except Exception as e:
        raise e
    def test_main(self):
        # create EC container
        headers = {'X-Storage-Policy': self.policy.name}
        client.put_container(self.url, self.token, self.container_name,
                             headers=headers)

        # PUT object
        contents = Body()
        headers = {'x-object-meta-foo': 'meta-foo'}
        headers_post = {'x-object-meta-bar': 'meta-bar'}

        etag = client.put_object(self.url, self.token,
                                 self.container_name,
                                 self.object_name,
                                 contents=contents, headers=headers)
        client.post_object(self.url, self.token, self.container_name,
                           self.object_name, headers=headers_post)
        del headers_post['X-Auth-Token']  # WTF, where did this come from?

        # built up a list of node lists to kill data from,
        # first try a single node
        # then adjacent nodes and then nodes >1 node apart
        opart, onodes = self.object_ring.get_nodes(
            self.account, self.container_name, self.object_name)
        single_node = [random.choice(onodes)]
        adj_nodes = [onodes[0], onodes[-1]]
        far_nodes = [onodes[0], onodes[-2]]
        test_list = [single_node, adj_nodes, far_nodes]

        for node_list in test_list:
            for onode in node_list:
                try:
                    self._check_node(onode, opart, etag, headers_post)
                except AssertionError as e:
                    self.fail(
                        str(e) + '\n... for node %r of scenario %r' % (
                            self._format_node(onode),
                            [self._format_node(n) for n in node_list]))
Example #20
0
    def test_handoff_non_durable(self):
        # verify that reconstructor reverts non-durable frags from handoff to
        # primary (and also durable frag of same object on same handoff) and
        # cleans up non-durable data files on handoffs after revert
        headers = {'X-Storage-Policy': self.policy.name}
        client.put_container(self.url,
                             self.token,
                             self.container_name,
                             headers=headers)

        # get our node lists
        opart, onodes = self.object_ring.get_nodes(self.account,
                                                   self.container_name,
                                                   self.object_name)
        pdevs = [self.device_dir(onode) for onode in onodes]
        hnodes = list(
            itertools.islice(self.object_ring.get_more_nodes(opart), 2))

        # kill a primary nodes so we can force data onto a handoff
        self.kill_drive(pdevs[0])

        # PUT object at t1
        contents = Body(total=3.5 * 2**20)
        headers = {'x-object-meta-foo': 'meta-foo'}
        headers_post = {'x-object-meta-bar': 'meta-bar'}
        client.put_object(self.url,
                          self.token,
                          self.container_name,
                          self.object_name,
                          contents=contents,
                          headers=headers)
        client.post_object(self.url,
                           self.token,
                           self.container_name,
                           self.object_name,
                           headers=headers_post)
        # (Some versions of?) swiftclient will mutate the headers dict on post
        headers_post.pop('X-Auth-Token', None)

        # this primary can't serve the data; we expect 507 here and not 404
        # because we're using mount_check to kill nodes
        self.assert_direct_get_fails(onodes[0], opart, 507)
        # these primaries and first handoff do have the data
        for onode in (onodes[1:]):
            self.assert_direct_get_succeeds(onode, opart)
        _hdrs, older_frag_etag = self.assert_direct_get_succeeds(
            hnodes[0], opart)
        self.assert_direct_get_fails(hnodes[1], opart, 404)

        # make sure we can GET the object; there's 5 primaries and 1 handoff
        headers, older_obj_etag = self.proxy_get()
        self.assertEqual(contents.etag, older_obj_etag)
        self.assertEqual('meta-bar', headers.get('x-object-meta-bar'))

        # PUT object at t2; make all frags non-durable so that the previous
        # durable frags at t1 remain on object server; use InternalClient so
        # that x-backend-no-commit is passed through
        internal_client = self.make_internal_client()
        contents2 = Body(total=2.5 * 2**20)  # different content
        self.assertNotEqual(contents2.etag, older_obj_etag)  # sanity check
        headers = {
            'x-backend-no-commit': 'True',
            'x-object-meta-bar': 'meta-bar-new'
        }
        internal_client.upload_object(contents2, self.account,
                                      self.container_name.decode('utf8'),
                                      self.object_name.decode('utf8'), headers)
        # GET should still return the older durable object
        headers, obj_etag = self.proxy_get()
        self.assertEqual(older_obj_etag, obj_etag)
        self.assertEqual('meta-bar', headers.get('x-object-meta-bar'))
        # on handoff we have older durable and newer non-durable
        _hdrs, frag_etag = self.assert_direct_get_succeeds(hnodes[0], opart)
        self.assertEqual(older_frag_etag, frag_etag)
        _hdrs, newer_frag_etag = self.assert_direct_get_succeeds(
            hnodes[0], opart, require_durable=False)
        self.assertNotEqual(older_frag_etag, newer_frag_etag)

        # now make all the newer frags durable only on the 5 primaries
        self.assertEqual(5, self.make_durable(onodes[1:], opart))
        # now GET will return the newer object
        headers, newer_obj_etag = self.proxy_get()
        self.assertEqual(contents2.etag, newer_obj_etag)
        self.assertNotEqual(older_obj_etag, newer_obj_etag)
        self.assertEqual('meta-bar-new', headers.get('x-object-meta-bar'))

        # fix the 507'ing primary
        self.revive_drive(pdevs[0])

        # fire up reconstructor on handoff node only; commit_window is
        # set to zero to ensure the nondurable handoff frag is purged
        hnode_id = self.config_number(hnodes[0])
        self.run_custom_daemon(ObjectReconstructor, 'object-reconstructor',
                               hnode_id, {'commit_window': '0'})

        # primary now has only the newer non-durable frag
        self.assert_direct_get_fails(onodes[0], opart, 404)
        _hdrs, frag_etag = self.assert_direct_get_succeeds(
            onodes[0], opart, require_durable=False)
        self.assertEqual(newer_frag_etag, frag_etag)

        # handoff has only the older durable
        _hdrs, frag_etag = self.assert_direct_get_succeeds(hnodes[0], opart)
        self.assertEqual(older_frag_etag, frag_etag)
        headers, frag_etag = self.assert_direct_get_succeeds(
            hnodes[0], opart, require_durable=False)
        self.assertEqual(older_frag_etag, frag_etag)
        self.assertEqual('meta-bar', headers.get('x-object-meta-bar'))

        # fire up reconstructor on handoff node only, again
        self.reconstructor.once(number=hnode_id)

        # primary now has the newer non-durable frag and the older durable frag
        headers, frag_etag = self.assert_direct_get_succeeds(onodes[0], opart)
        self.assertEqual(older_frag_etag, frag_etag)
        self.assertEqual('meta-bar', headers.get('x-object-meta-bar'))
        headers, frag_etag = self.assert_direct_get_succeeds(
            onodes[0], opart, require_durable=False)
        self.assertEqual(newer_frag_etag, frag_etag)
        self.assertEqual('meta-bar-new', headers.get('x-object-meta-bar'))

        # handoff has nothing
        self.assert_direct_get_fails(hnodes[0],
                                     opart,
                                     404,
                                     require_durable=False)

        # kill all but first two primaries
        for pdev in pdevs[2:]:
            self.kill_drive(pdev)
        # fire up reconstructor on the remaining primary[1]; without the
        # other primaries, primary[1] cannot rebuild the frag but it can let
        # primary[0] know that its non-durable frag can be made durable
        self.reconstructor.once(number=self.config_number(onodes[1]))

        # first primary now has a *durable* *newer* frag - it *was* useful to
        # sync the non-durable!
        headers, frag_etag = self.assert_direct_get_succeeds(onodes[0], opart)
        self.assertEqual(newer_frag_etag, frag_etag)
        self.assertEqual('meta-bar-new', headers.get('x-object-meta-bar'))

        # revive primaries (in case we want to debug)
        for pdev in pdevs[2:]:
            self.revive_drive(pdev)
    def test_revert_object(self):
        # create EC container
        headers = {'X-Storage-Policy': self.policy.name}
        client.put_container(self.url,
                             self.token,
                             self.container_name,
                             headers=headers)

        # get our node lists
        opart, onodes = self.object_ring.get_nodes(self.account,
                                                   self.container_name,
                                                   self.object_name)
        hnodes = self.object_ring.get_more_nodes(opart)

        # kill 2 a parity count number of primary nodes so we can
        # force data onto handoffs, we do that by renaming dev dirs
        # to induce 507
        p_dev1 = self.device_dir(onodes[0])
        p_dev2 = self.device_dir(onodes[1])
        self.kill_drive(p_dev1)
        self.kill_drive(p_dev2)

        # PUT object
        contents = Body()
        headers = {'x-object-meta-foo': 'meta-foo'}
        headers_post = {'x-object-meta-bar': 'meta-bar'}
        client.put_object(self.url,
                          self.token,
                          self.container_name,
                          self.object_name,
                          contents=contents,
                          headers=headers)
        client.post_object(self.url,
                           self.token,
                           self.container_name,
                           self.object_name,
                           headers=headers_post)
        # (Some versions of?) swiftclient will mutate the headers dict on post
        headers_post.pop('X-Auth-Token', None)

        # these primaries can't serve the data any more, we expect 507
        # here and not 404 because we're using mount_check to kill nodes
        for onode in (onodes[0], onodes[1]):
            try:
                self.direct_get(onode, opart)
            except direct_client.DirectClientException as err:
                self.assertEqual(err.http_status, 507)
            else:
                self.fail('Node data on %r was not fully destroyed!' %
                          (onode, ))

        # now take out another primary
        p_dev3 = self.device_dir(onodes[2])
        self.kill_drive(p_dev3)

        # this node can't servce the data any more
        try:
            self.direct_get(onodes[2], opart)
        except direct_client.DirectClientException as err:
            self.assertEqual(err.http_status, 507)
        else:
            self.fail('Node data on %r was not fully destroyed!' % (onode, ))

        # make sure we can still GET the object and its correct
        # we're now pulling from handoffs and reconstructing
        etag = self.proxy_get()
        self.assertEqual(etag, contents.etag)

        # rename the dev dirs so they don't 507 anymore
        self.revive_drive(p_dev1)
        self.revive_drive(p_dev2)
        self.revive_drive(p_dev3)

        # fire up reconstructor on handoff nodes only
        for hnode in hnodes:
            hnode_id = (hnode['port'] - 6000) // 10
            self.reconstructor.once(number=hnode_id)

        # first three primaries have data again
        for onode in (onodes[0], onodes[2]):
            self.direct_get(onode, opart)

        # check meta
        meta = client.head_object(self.url, self.token, self.container_name,
                                  self.object_name)
        for key in headers_post:
            self.assertIn(key, meta)
            self.assertEqual(meta[key], headers_post[key])

        # handoffs are empty
        for hnode in hnodes:
            try:
                self.direct_get(hnode, opart)
            except direct_client.DirectClientException as err:
                self.assertEqual(err.http_status, 404)
            else:
                self.fail('Node data on %r was not fully destroyed!' %
                          (hnode, ))
Example #22
0
    def test_revert_object(self):
        # create EC container
        headers = {"X-Storage-Policy": self.policy.name}
        client.put_container(self.url, self.token, self.container_name, headers=headers)

        # get our node lists
        opart, onodes = self.object_ring.get_nodes(self.account, self.container_name, self.object_name)
        hnodes = self.object_ring.get_more_nodes(opart)

        # kill 2 a parity count number of primary nodes so we can
        # force data onto handoffs, we do that by renaming dev dirs
        # to induce 507
        p_dev1 = self.device_dir("object", onodes[0])
        p_dev2 = self.device_dir("object", onodes[1])
        self.kill_drive(p_dev1)
        self.kill_drive(p_dev2)

        # PUT object
        contents = Body()
        headers = {"x-object-meta-foo": "meta-foo"}
        headers_post = {"x-object-meta-bar": "meta-bar"}
        client.put_object(
            self.url, self.token, self.container_name, self.object_name, contents=contents, headers=headers
        )
        client.post_object(self.url, self.token, self.container_name, self.object_name, headers=headers_post)
        del headers_post["X-Auth-Token"]  # WTF, where did this come from?

        # these primaries can't servce the data any more, we expect 507
        # here and not 404 because we're using mount_check to kill nodes
        for onode in (onodes[0], onodes[1]):
            try:
                self.direct_get(onode, opart)
            except direct_client.DirectClientException as err:
                self.assertEqual(err.http_status, 507)
            else:
                self.fail("Node data on %r was not fully destoryed!" % (onode,))

        # now take out another primary
        p_dev3 = self.device_dir("object", onodes[2])
        self.kill_drive(p_dev3)

        # this node can't servce the data any more
        try:
            self.direct_get(onodes[2], opart)
        except direct_client.DirectClientException as err:
            self.assertEqual(err.http_status, 507)
        else:
            self.fail("Node data on %r was not fully destoryed!" % (onode,))

        # make sure we can still GET the object and its correct
        # we're now pulling from handoffs and reconstructing
        etag = self.proxy_get()
        self.assertEqual(etag, contents.etag)

        # rename the dev dirs so they don't 507 anymore
        self.revive_drive(p_dev1)
        self.revive_drive(p_dev2)
        self.revive_drive(p_dev3)

        # fire up reconstructor on handoff nodes only
        for hnode in hnodes:
            hnode_id = (hnode["port"] - 6000) / 10
            self.reconstructor.once(number=hnode_id)

        # first threee primaries have data again
        for onode in (onodes[0], onodes[2]):
            self.direct_get(onode, opart)

        # check meta
        meta = client.head_object(self.url, self.token, self.container_name, self.object_name)
        for key in headers_post:
            self.assertTrue(key in meta)
            self.assertEqual(meta[key], headers_post[key])

        # handoffs are empty
        for hnode in hnodes:
            try:
                self.direct_get(hnode, opart)
            except direct_client.DirectClientException as err:
                self.assertEqual(err.http_status, 404)
            else:
                self.fail("Node data on %r was not fully destoryed!" % (hnode,))
Example #23
0
    def test_sync_unexpired_object_metadata(self):
        # verify that metadata can be sync'd to a frag that has missed a POST
        # and consequently that frag appears to be expired, when in fact the
        # POST removed the x-delete-at header
        client.put_container(self.url,
                             self.token,
                             self.container_name,
                             headers={'x-storage-policy': self.policy.name})
        opart, onodes = self.object_ring.get_nodes(self.account,
                                                   self.container_name,
                                                   self.object_name)
        delete_at = int(time.time() + 3)
        contents = ('body-%s' % uuid.uuid4()).encode()
        headers = {'x-delete-at': delete_at}
        client.put_object(self.url,
                          self.token,
                          self.container_name,
                          self.object_name,
                          headers=headers,
                          contents=contents)
        # fail a primary
        post_fail_node = random.choice(onodes)
        post_fail_path = self.device_dir(post_fail_node)
        self.kill_drive(post_fail_path)
        # post over w/o x-delete-at
        client.post_object(self.url, self.token, self.container_name,
                           self.object_name, {'content-type': 'something-new'})
        # revive failed primary
        self.revive_drive(post_fail_path)
        # wait for the delete_at to pass, and check that it thinks the object
        # is expired
        timeout = time.time() + 5
        err = None
        while time.time() < timeout:
            try:
                direct_client.direct_head_object(
                    post_fail_node,
                    opart,
                    self.account,
                    self.container_name,
                    self.object_name,
                    headers={
                        'X-Backend-Storage-Policy-Index': int(self.policy)
                    })
            except direct_client.ClientException as client_err:
                if client_err.http_status != 404:
                    raise
                err = client_err
                break
            else:
                time.sleep(0.1)
        else:
            self.fail('Failed to get a 404 from node with expired object')
        self.assertEqual(err.http_status, 404)
        self.assertIn('X-Backend-Timestamp', err.http_headers)

        # but from the proxy we've got the whole story
        headers, body = client.get_object(self.url, self.token,
                                          self.container_name,
                                          self.object_name)
        self.assertNotIn('X-Delete-At', headers)
        self.reconstructor.once()

        # ... and all the nodes have the final unexpired state
        for node in onodes:
            headers = direct_client.direct_head_object(
                node,
                opart,
                self.account,
                self.container_name,
                self.object_name,
                headers={'X-Backend-Storage-Policy-Index': int(self.policy)})
            self.assertNotIn('X-Delete-At', headers)
 def test_ok(self):
     c.http_connection = self.fake_http_connection(200)
     args = ("http://www.test.com", "asdf", "asdf", "asdf", {})
     c.post_object(*args)
Example #25
0
 def post_object(self, account_id, token, s_type, container, name, headers):
     cnx = self.get_cnx(account_id, s_type)
     sclient.post_object("", token, container, name, headers, http_conn=cnx)
 def test_ok(self):
     c.http_connection = self.fake_http_connection(200)
     args = ('http://www.test.com', 'asdf', 'asdf', 'asdf', {})
     c.post_object(*args)
Example #27
0
 def post_object(self, account_id, token, s_type, container, name, headers):
     cnx = self.get_cnx(account_id, s_type)
     sclient.post_object("", token, container, name, headers, http_conn=cnx)
Example #28
0
 def test_ok(self):
     c.http_connection = self.fake_http_connection(200)
     args = ('http://www.test.com', 'asdf', 'asdf', 'asdf', {})
     value = c.post_object(*args)