diff --git a/AUTHORS b/AUTHORS index bf834db788..f6287945c8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -27,6 +27,7 @@ Stephen Milton Russ Nelson Colin Nicholson Andrew Clay Shafer +Scott Simpson Monty Taylor Caleb Tennis FUJITA Tomonori diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000000..97fe05d552 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,4 @@ +swift (x.x.x) + + * Renamed swift-stats-populate to swift-dispersion-populate and + swift-stats-report to swift-dispersion-report. diff --git a/bin/swauth-add-account b/bin/swauth-add-account index 2b91b6292d..b8591c3425 100755 --- a/bin/swauth-add-account +++ b/bin/swauth-add-account @@ -65,4 +65,4 @@ if __name__ == '__main__': ssl=(parsed.scheme == 'https')) resp = conn.getresponse() if resp.status // 100 != 2: - print 'Account creation failed: %s %s' % (resp.status, resp.reason) + exit('Account creation failed: %s %s' % (resp.status, resp.reason)) diff --git a/bin/swauth-add-user b/bin/swauth-add-user index 23144df41b..7b3dc129d3 100755 --- a/bin/swauth-add-user +++ b/bin/swauth-add-user @@ -90,4 +90,4 @@ if __name__ == '__main__': ssl=(parsed.scheme == 'https')) resp = conn.getresponse() if resp.status // 100 != 2: - print 'User creation failed: %s %s' % (resp.status, resp.reason) + exit('User creation failed: %s %s' % (resp.status, resp.reason)) diff --git a/bin/swauth-cleanup-tokens b/bin/swauth-cleanup-tokens index 3ca86cd990..3b09072f40 100755 --- a/bin/swauth-cleanup-tokens +++ b/bin/swauth-cleanup-tokens @@ -25,7 +25,7 @@ from optparse import OptionParser from sys import argv, exit from time import sleep, time -from swift.common.client import Connection +from swift.common.client import Connection, ClientException if __name__ == '__main__': @@ -65,7 +65,15 @@ if __name__ == '__main__': while True: if options.verbose: print 'GET %s?marker=%s' % (container, marker) - objs = conn.get_container(container, marker=marker)[1] + try: + objs = conn.get_container(container, marker=marker)[1] + except ClientException, e: + if e.http_status == 404: + exit('Container %s not found. swauth-prep needs to be ' + 'rerun' % (container)) + else: + exit('Object listing on container %s failed with status ' + 'code %d' % (container, e.http_status)) if objs: marker = objs[-1]['name'] else: @@ -90,7 +98,13 @@ if __name__ == '__main__': (container, obj['name'], time() - detail['expires']) print 'DELETE %s/%s' % (container, obj['name']) - conn.delete_object(container, obj['name']) + try: + conn.delete_object(container, obj['name']) + except ClientException, e: + if e.http_status != 404: + print 'DELETE of %s/%s failed with status ' \ + 'code %d' % (container, obj['name'], + e.http_status) elif options.verbose: print "%s/%s won't expire for %ds; skipping" % \ (container, obj['name'], diff --git a/bin/swauth-delete-account b/bin/swauth-delete-account index 66bdf2bbe1..45aba4c502 100755 --- a/bin/swauth-delete-account +++ b/bin/swauth-delete-account @@ -57,4 +57,4 @@ if __name__ == '__main__': ssl=(parsed.scheme == 'https')) resp = conn.getresponse() if resp.status // 100 != 2: - print 'Account deletion failed: %s %s' % (resp.status, resp.reason) + exit('Account deletion failed: %s %s' % (resp.status, resp.reason)) diff --git a/bin/swauth-delete-user b/bin/swauth-delete-user index de3ac3b12b..95025bc195 100755 --- a/bin/swauth-delete-user +++ b/bin/swauth-delete-user @@ -57,4 +57,4 @@ if __name__ == '__main__': ssl=(parsed.scheme == 'https')) resp = conn.getresponse() if resp.status // 100 != 2: - print 'User deletion failed: %s %s' % (resp.status, resp.reason) + exit('User deletion failed: %s %s' % (resp.status, resp.reason)) diff --git a/bin/swauth-list b/bin/swauth-list index 3f9ae5ea49..bbf5bfe9f1 100755 --- a/bin/swauth-list +++ b/bin/swauth-list @@ -75,9 +75,9 @@ If the [user] is '.groups', the active groups for the account will be listed. conn = http_connect(parsed.hostname, parsed.port, 'GET', path, headers, ssl=(parsed.scheme == 'https')) resp = conn.getresponse() - if resp.status // 100 != 2: - print 'List failed: %s %s' % (resp.status, resp.reason) body = resp.read() + if resp.status // 100 != 2: + exit('List failed: %s %s' % (resp.status, resp.reason)) if options.plain_text: info = json.loads(body) for group in info[['accounts', 'users', 'groups'][len(args)]]: diff --git a/bin/swauth-prep b/bin/swauth-prep index a7b912e60c..456cf3e4c8 100755 --- a/bin/swauth-prep +++ b/bin/swauth-prep @@ -56,4 +56,4 @@ if __name__ == '__main__': ssl=(parsed.scheme == 'https')) resp = conn.getresponse() if resp.status // 100 != 2: - print 'Auth subsystem prep failed: %s %s' % (resp.status, resp.reason) + exit('Auth subsystem prep failed: %s %s' % (resp.status, resp.reason)) diff --git a/bin/swauth-set-account-service b/bin/swauth-set-account-service index 0317546df5..acdba77962 100755 --- a/bin/swauth-set-account-service +++ b/bin/swauth-set-account-service @@ -70,4 +70,4 @@ Example: %prog -K swauthkey test storage local http://127.0.0.1:8080/v1/AUTH_018 conn.send(body) resp = conn.getresponse() if resp.status // 100 != 2: - print 'Service set failed: %s %s' % (resp.status, resp.reason) + exit('Service set failed: %s %s' % (resp.status, resp.reason)) diff --git a/doc/source/_theme/layout.html b/doc/source/_theme/layout.html index f0573a3b43..75d970baa8 100644 --- a/doc/source/_theme/layout.html +++ b/doc/source/_theme/layout.html @@ -58,7 +58,7 @@

- Psst... hey. Did you know you can read Swift 1.2 docs or Swift 1.1 docs also? + Psst... hey. Did you know you can read Swift 1.3 docs or Swift 1.2 docs also?

{%- endif %} diff --git a/doc/source/debian_package_guide.rst b/doc/source/debian_package_guide.rst index e8086adc16..eef9180a90 100644 --- a/doc/source/debian_package_guide.rst +++ b/doc/source/debian_package_guide.rst @@ -58,7 +58,7 @@ Instructions for Building Debian Packages for Swift apt-get install python-software-properties add-apt-repository ppa:swift-core/ppa apt-get update - apt-get install curl gcc bzr python-configobj python-coverage python-dev python-nose python-setuptools python-simplejson python-xattr python-webob python-eventlet python-greenlet debhelper python-sphinx python-all python-openssl python-pastedeploy bzr-builddeb + apt-get install curl gcc bzr python-configobj python-coverage python-dev python-nose python-setuptools python-simplejson python-xattr python-webob python-eventlet python-greenlet debhelper python-sphinx python-all python-openssl python-pastedeploy python-netifaces bzr-builddeb * As you diff --git a/doc/source/development_saio.rst b/doc/source/development_saio.rst index 9d0bce0a19..ce2a09e270 100644 --- a/doc/source/development_saio.rst +++ b/doc/source/development_saio.rst @@ -11,8 +11,8 @@ virtual machine will emulate running a four node Swift cluster. * Get the *Ubuntu 10.04 LTS (Lucid Lynx)* server image: - - Ubuntu Server ISO: http://releases.ubuntu.com/10.04/ubuntu-10.04.1-server-amd64.iso (682 MB) - - Ubuntu Live/Install: http://cdimage.ubuntu.com/releases/10.04/release/ubuntu-10.04-dvd-amd64.iso (4.1 GB) + - Ubuntu Server ISO: http://releases.ubuntu.com/lucid/ubuntu-10.04.2-server-amd64.iso (717 MB) + - Ubuntu Live/Install: http://cdimage.ubuntu.com/releases/lucid/release/ubuntu-10.04.2-dvd-amd64.iso (4.2 GB) - Ubuntu Mirrors: https://launchpad.net/ubuntu/+cdmirrors * Create guest virtual machine from the Ubuntu image. @@ -70,6 +70,7 @@ Using a loopback device for storage If you want to use a loopback device instead of another partition, follow these instructions. + #. `mkdir /srv` #. `dd if=/dev/zero of=/srv/swift-disk bs=1024 count=0 seek=1000000` (modify seek to make a larger or smaller partition) #. `mkfs.xfs -i size=1024 /srv/swift-disk` @@ -79,7 +80,6 @@ If you want to use a loopback device instead of another partition, follow these #. `mount /mnt/sdb1` #. `mkdir /mnt/sdb1/1 /mnt/sdb1/2 /mnt/sdb1/3 /mnt/sdb1/4` #. `chown : /mnt/sdb1/*` - #. `mkdir /srv` #. `for x in {1..4}; do ln -s /mnt/sdb1/$x /srv/$x; done` #. `mkdir -p /etc/swift/object-server /etc/swift/container-server /etc/swift/account-server /srv/1/node/sdb1 /srv/2/node/sdb2 /srv/3/node/sdb3 /srv/4/node/sdb4 /var/run/swift` #. `chown -R : /etc/swift /srv/[1-4]/ /var/run/swift` -- **Make sure to include the trailing slash after /srv/[1-4]/** @@ -555,7 +555,9 @@ Sample configuration files are provided with all defaults in line-by-line commen Setting up scripts for running Swift ------------------------------------ - #. Create `~/bin/resetswift.` If you are using a loopback device substitute `/dev/sdb1` with `/srv/swift-disk`:: + #. Create `~/bin/resetswift.` + If you are using a loopback device substitute `/dev/sdb1` with `/srv/swift-disk`. + If you did not set up rsyslog for individual logging, remove the `find /var/log/swift...` line:: #!/bin/bash diff --git a/swift/__init__.py b/swift/__init__.py index 25a1c6b8c7..441e13d5e8 100644 --- a/swift/__init__.py +++ b/swift/__init__.py @@ -1,5 +1,5 @@ import gettext -__version__ = '1.3-dev' +__version__ = '1.4-dev' gettext.install('swift') diff --git a/swift/common/bench.py b/swift/common/bench.py index 482c2d77aa..c500493187 100644 --- a/swift/common/bench.py +++ b/swift/common/bench.py @@ -147,6 +147,16 @@ class BenchDELETE(Bench): self.total = len(names) self.msg = 'DEL' + def run(self): + Bench.run(self) + for container in self.containers: + try: + client.delete_container(self.url, self.token, container) + except client.ClientException, e: + if e.http_status != 409: + self._log_status("Unable to delete container '%s'. " \ + "Got http status '%d'." % (container, e.http_status)) + def _run(self, thread): if time.time() - self.heartbeat >= 15: self.heartbeat = time.time() diff --git a/swift/common/db_replicator.py b/swift/common/db_replicator.py index 25bb8c810d..838cfc21df 100644 --- a/swift/common/db_replicator.py +++ b/swift/common/db_replicator.py @@ -20,6 +20,8 @@ import random import math import time import shutil +import uuid +import errno from eventlet import GreenPool, sleep, Timeout, TimeoutError from eventlet.green import subprocess @@ -49,7 +51,13 @@ def quarantine_db(object_file, server_type): quarantine_dir = os.path.abspath(os.path.join(object_dir, '..', '..', '..', '..', 'quarantined', server_type + 's', os.path.basename(object_dir))) - renamer(object_dir, quarantine_dir) + try: + renamer(object_dir, quarantine_dir) + except OSError, e: + if e.errno not in (errno.EEXIST, errno.ENOTEMPTY): + raise + quarantine_dir = "%s-%s" % (quarantine_dir, uuid.uuid4().hex) + renamer(object_dir, quarantine_dir) class ReplConnection(BufferedHTTPConnection): diff --git a/swift/common/middleware/swauth.py b/swift/common/middleware/swauth.py index 76ad4495f4..328799a19a 100644 --- a/swift/common/middleware/swauth.py +++ b/swift/common/middleware/swauth.py @@ -468,7 +468,7 @@ class Swauth(object): {"account_id": "AUTH_018c3946-23f8-4efb-a8fb-b67aae8e4162", "services": {"storage": {"default": "local", - "local": "http://127.0.0.1:8080/v1/AUTH_018c3946-23f8-4efb-a8fb-b67aae8e4162"}}, + "local": "http://127.0.0.1:8080/v1/AUTH_018c3946"}}, "users": [{"name": "tester"}, {"name": "tester3"}]} :param req: The webob.Request to process. @@ -522,7 +522,7 @@ class Swauth(object): this:: "services": {"storage": {"default": "local", - "local": "http://127.0.0.1:8080/v1/AUTH_018c3946-23f8-4efb-a8fb-b67aae8e4162"}} + "local": "http://127.0.0.1:8080/v1/AUTH_018c3946"}} Making use of this section is described in :func:`handle_get_token`. @@ -849,6 +849,12 @@ class Swauth(object): raise Exception('Could not retrieve user object: %s %s' % (path, resp.status)) body = resp.body + display_groups = [g['name'] for g in json.loads(body)['groups']] + if ('.admin' in display_groups and + not self.is_reseller_admin(req)) or \ + ('.reseller_admin' in display_groups and + not self.is_super_admin(req)): + return HTTPForbidden(request=req) return Response(body=body) def handle_put_user(self, req): diff --git a/swift/common/middleware/swift3.py b/swift/common/middleware/swift3.py index a41c8cb695..df1ca3f755 100644 --- a/swift/common/middleware/swift3.py +++ b/swift/common/middleware/swift3.py @@ -16,9 +16,6 @@ """ The swift3 middleware will emulate the S3 REST api on top of swift. -The boto python library is necessary to use this middleware (install -the python-boto package if you use Ubuntu). - The following opperations are currently supported: * GET Service @@ -239,7 +236,7 @@ class BucketController(Controller): if 'acl' in args: return get_acl(self.account_name) - + objects = loads(''.join(list(body_iter))) body = ('' '