summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoren Hansen <soren.hansen@rackspace.com>2010-07-26 16:03:23 +0200
committerSoren Hansen <soren.hansen@rackspace.com>2010-07-26 16:03:23 +0200
commitd5051bf90909f693a74ea0f2bdc3db341460a5a3 (patch)
tree091d7a97bb7193e673611cee008c8b69f6ead54d
parentdd17c810029d142abaa8f0c97e30a8ae1dc13b5c (diff)
downloadnova-d5051bf90909f693a74ea0f2bdc3db341460a5a3.tar.gz
nova-d5051bf90909f693a74ea0f2bdc3db341460a5a3.tar.xz
nova-d5051bf90909f693a74ea0f2bdc3db341460a5a3.zip
Add a simple set of tests for S3 API (using boto).
-rw-r--r--nova/objectstore/handler.py14
-rw-r--r--nova/tests/objectstore_unittest.py131
2 files changed, 105 insertions, 40 deletions
diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py
index 1a54f8a98..45eeef163 100644
--- a/nova/objectstore/handler.py
+++ b/nova/objectstore/handler.py
@@ -108,8 +108,6 @@ def get_context(request):
raise exception.NotAuthorized
access, sep, secret = authorization_header.split(' ')[1].rpartition(':')
um = users.UserManager.instance()
- print 'um %s' % um
-
(user, project) = um.authenticate(access, secret, {}, request.method, request.getRequestHostname(), request.uri, headers=request.getAllHeaders(), check_type='s3')
return api.APIRequestContext(None, user, project)
except exception.Error as ex:
@@ -169,10 +167,6 @@ class BucketResource(Resource):
def render_PUT(self, request):
logging.debug("Creating bucket %s" % (self.name))
- try:
- print 'user is %s' % request.context
- except Exception as e:
- logging.exception(e)
logging.debug("calling bucket.Bucket.create(%r, %r)" % (self.name, request.context))
bucket.Bucket.create(self.name, request.context)
request.finish()
@@ -300,9 +294,13 @@ class ImageResource(Resource):
request.setResponseCode(204)
return ''
-def get_application():
+def get_site():
root = S3()
- factory = server.Site(root)
+ site = server.Site(root)
+ return site
+
+def get_application():
+ factory = get_site()
application = service.Application("objectstore")
objectStoreService = internet.TCPServer(FLAGS.s3_port, factory)
objectStoreService.setServiceParent(application)
diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py
index f47ca7f00..ef1a477ff 100644
--- a/nova/tests/objectstore_unittest.py
+++ b/nova/tests/objectstore_unittest.py
@@ -16,6 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import boto
import glob
import hashlib
import logging
@@ -27,7 +28,11 @@ from nova import flags
from nova import objectstore
from nova import test
from nova.auth import users
+from nova.objectstore.handler import S3
+from boto.s3.connection import S3Connection, OrdinaryCallingFormat
+from twisted.internet import reactor, threads, defer
+from twisted.web import http, server
FLAGS = flags.FLAGS
@@ -169,35 +174,97 @@ class ObjectStoreTestCase(test.BaseTestCase):
self.context.project = self.um.get_project('proj2')
self.assert_(my_img.is_authorized(self.context) == False)
-# class ApiObjectStoreTestCase(test.BaseTestCase):
-# def setUp(self):
-# super(ApiObjectStoreTestCase, self).setUp()
-# FLAGS.fake_users = True
-# FLAGS.buckets_path = os.path.join(tempdir, 'buckets')
-# FLAGS.images_path = os.path.join(tempdir, 'images')
-# FLAGS.ca_path = os.path.join(os.path.dirname(__file__), 'CA')
-#
-# self.users = users.UserManager.instance()
-# self.app = handler.Application(self.users)
-#
-# self.host = '127.0.0.1'
-#
-# self.conn = boto.s3.connection.S3Connection(
-# aws_access_key_id=user.access,
-# aws_secret_access_key=user.secret,
-# is_secure=False,
-# calling_format=boto.s3.connection.OrdinaryCallingFormat(),
-# port=FLAGS.s3_port,
-# host=FLAGS.s3_host)
-#
-# self.mox.StubOutWithMock(self.ec2, 'new_http_connection')
-#
-# def tearDown(self):
-# FLAGS.Reset()
-# super(ApiObjectStoreTestCase, self).tearDown()
-#
-# def test_describe_instances(self):
-# self.expect_http()
-# self.mox.ReplayAll()
-#
-# self.assertEqual(self.ec2.get_all_instances(), [])
+
+class TestHTTPChannel(http.HTTPChannel):
+ # Otherwise we end up with an unclean reactor
+ def checkPersistence(self, _, __):
+ return False
+
+
+class TestSite(server.Site):
+ protocol = TestHTTPChannel
+
+
+class S3APITestCase(test.TrialTestCase):
+ def setUp(self):
+ super(S3APITestCase, self).setUp()
+ FLAGS.fake_users = True
+ FLAGS.buckets_path = os.path.join(oss_tempdir, 'buckets')
+
+ shutil.rmtree(FLAGS.buckets_path)
+ os.mkdir(FLAGS.buckets_path)
+
+ root = S3()
+ self.site = TestSite(root)
+ self.listening_port = reactor.listenTCP(0, self.site, interface='127.0.0.1')
+ self.tcp_port = self.listening_port.getHost().port
+
+
+ boto.config.set('Boto', 'num_retries', '0')
+ self.conn = S3Connection(aws_access_key_id='admin',
+ aws_secret_access_key='admin',
+ host='127.0.0.1',
+ port=self.tcp_port,
+ is_secure=False,
+ calling_format=OrdinaryCallingFormat())
+
+ # Don't attempt to reuse connections
+ def get_http_connection(host, is_secure):
+ return self.conn.new_http_connection(host, is_secure)
+ self.conn.get_http_connection = get_http_connection
+
+ def _ensure_empty_list(self, l):
+ self.assertEquals(len(l), 0, "List was not empty")
+ return True
+
+ def _ensure_only_bucket(self, l, name):
+ self.assertEquals(len(l), 1, "List didn't have exactly one element in it")
+ self.assertEquals(l[0].name, name, "Wrong name")
+
+ def test_000_list_buckets(self):
+ d = threads.deferToThread(self.conn.get_all_buckets)
+ d.addCallback(self._ensure_empty_list)
+ return d
+
+ def test_001_create_and_delete_bucket(self):
+ bucket_name = 'testbucket'
+
+ d = threads.deferToThread(self.conn.create_bucket, bucket_name)
+ d.addCallback(lambda _:threads.deferToThread(self.conn.get_all_buckets))
+
+ def ensure_only_bucket(l, name):
+ self.assertEquals(len(l), 1, "List didn't have exactly one element in it")
+ self.assertEquals(l[0].name, name, "Wrong name")
+ d.addCallback(ensure_only_bucket, bucket_name)
+
+ d.addCallback(lambda _:threads.deferToThread(self.conn.delete_bucket, bucket_name))
+ d.addCallback(lambda _:threads.deferToThread(self.conn.get_all_buckets))
+ d.addCallback(self._ensure_empty_list)
+ return d
+
+ def test_002_create_bucket_and_key_and_delete_key_again(self):
+ bucket_name = 'testbucket'
+ key_name = 'somekey'
+ key_contents = 'somekey'
+
+ d = threads.deferToThread(self.conn.create_bucket, bucket_name)
+ d.addCallback(lambda b:threads.deferToThread(b.new_key, key_name))
+ d.addCallback(lambda k:threads.deferToThread(k.set_contents_from_string, key_contents))
+ def ensure_key_contents(bucket_name, key_name, contents):
+ bucket = self.conn.get_bucket(bucket_name)
+ key = bucket.get_key(key_name)
+ self.assertEquals(key.get_contents_as_string(), contents, "Bad contents")
+ d.addCallback(lambda _:threads.deferToThread(ensure_key_contents, bucket_name, key_name, key_contents))
+ def delete_key(bucket_name, key_name):
+ bucket = self.conn.get_bucket(bucket_name)
+ key = bucket.get_key(key_name)
+ key.delete()
+ d.addCallback(lambda _:threads.deferToThread(delete_key, bucket_name, key_name))
+ d.addCallback(lambda _:threads.deferToThread(self.conn.get_bucket, bucket_name))
+ d.addCallback(lambda b:threads.deferToThread(b.get_all_keys))
+ d.addCallback(self._ensure_empty_list)
+ return d
+
+ def tearDown(self):
+ super(S3APITestCase, self).tearDown()
+ return defer.DeferredList([defer.maybeDeferred(self.listening_port.stopListening)])