diff --git a/nova/objectstore/s3server.py b/nova/objectstore/s3server.py index a74d76392985..1dc6a264bea5 100644 --- a/nova/objectstore/s3server.py +++ b/nova/objectstore/s3server.py @@ -308,6 +308,16 @@ class BucketHandler(BaseRequestHandler): self.set_status(204) self.finish() + def head(self, bucket_name): + path = os.path.abspath(os.path.join(self.application.directory, + bucket_name)) + if (not path.startswith(self.application.directory) or + not os.path.isdir(path)): + self.set_404() + return + self.set_status(200) + self.finish() + class ObjectHandler(BaseRequestHandler): def get(self, bucket, object_name): diff --git a/nova/tests/test_objectstore.py b/nova/tests/test_objectstore.py index e66bd9fad9f0..3f10cab282ee 100644 --- a/nova/tests/test_objectstore.py +++ b/nova/tests/test_objectstore.py @@ -127,10 +127,27 @@ class S3APITestCase(test.NoDBTestCase): self._ensure_no_buckets(bucket.get_all_keys()) def test_unknown_bucket(self): + # NOTE(unicell): Since Boto v2.25.0, the underlying implementation + # of get_bucket method changed from GET to HEAD. + # + # Prior to v2.25.0, default validate=True fetched a list of keys in the + # bucket and raises S3ResponseError. As a side effect of switching to + # HEAD request, get_bucket call now generates less error message. + # + # To keep original semantics, additional get_all_keys call is + # suggestted per Boto document. This case tests both validate=False and + # validate=True case for completeness. + # + # http://docs.pythonboto.org/en/latest/releasenotes/v2.25.0.html + # http://docs.pythonboto.org/en/latest/s3_tut.html#accessing-a-bucket bucket_name = 'falalala' self.assertRaises(boto_exception.S3ResponseError, self.conn.get_bucket, bucket_name) + bucket = self.conn.get_bucket(bucket_name, validate=False) + self.assertRaises(boto_exception.S3ResponseError, + bucket.get_all_keys, + maxkeys=0) def tearDown(self): """Tear down test server."""