[glusterfs] glusterfs-3.3.0-4, add UFO - Unified File and Object. UFO is openstack-swift (currently essex, 1.4.8
Kaleb S. KEITHLEY
kkeithle at fedoraproject.org
Fri Aug 10 15:12:17 UTC 2012
commit 4d2de6ced09ad1f23598a931e3acc84766d81d65
Author: Kaleb S. KEITHLEY <kkeithle at redhat.com>
Date: Fri Aug 10 11:02:39 2012 -0400
glusterfs-3.3.0-4, add UFO - Unified File and Object.
UFO is openstack-swift (currently essex, 1.4.8), patched to add hooks
for GlusterFS plug-ins.
N.B. Gluster's changes to swift have been submitted to upstream, and
when a new version of swift containing the hooks is released then
this patched version will be removed from the GlusterFS packaging.
.gitignore | 2 +
gluster-swift-account.init | 78 ++++
gluster-swift-container.init | 78 ++++
gluster-swift-functions | 64 ++++
gluster-swift-object.init | 79 ++++
gluster-swift-plugins.tar.gz | Bin 0 -> 18951 bytes
gluster-swift-proxy.init | 79 ++++
glusterfs.spec | 365 +++++++++++++++++++-
openstack-swift-docmod.patch | 14 +
openstack-swift-newdeps.patch | 36 ++
openstack-swift-nonet.patch | 11 +
sources | 1 +
swift.patch | 797 +++++++++++++++++++++++++++++++++++++++++
13 files changed, 1600 insertions(+), 4 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ac6c5fd..ce590a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,4 +11,6 @@ glusterfs-3.2.3.tar.gz
glusterfs-3.2.4.tar.gz
glusterfs-3.2.5.tar.gz
glusterfs-3.2.6.tar.gz
+glusterfs-3.2.7.tar.gz
glusterfs-3.3.0.tar.gz
+swift-1.4.8.tar.gz
diff --git a/gluster-swift-account.init b/gluster-swift-account.init
new file mode 100755
index 0000000..4f1dbfd
--- /dev/null
+++ b/gluster-swift-account.init
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+### BEGIN INIT INFO
+# Provides: gluster-swift-account
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Default-Stop: 0 1 6
+# Short-Description: Swift account server
+# Description: Account server for swift.
+### END INIT INFO
+
+# gluster-swift-account: swift account server
+#
+# chkconfig: - 20 80
+# description: Account server for swift.
+
+. /etc/rc.d/init.d/functions
+. /usr/share/gluster-swift/functions
+
+name="account"
+
+[ -e "/etc/sysconfig/gluster-swift-$name" ] && . "/etc/sysconfig/gluster-swift-$name"
+
+lockfile="/var/lock/subsys/gluster-swift-account"
+
+start() {
+ swift_action "$name" start
+ retval=$?
+ [ $retval -eq 0 ] && touch $lockfile
+ return $retval
+}
+
+stop() {
+ swift_action "$name" stop
+ retval=$?
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+rh_status() {
+ swift_action "$name" status
+}
+
+rh_status_q() {
+ rh_status &> /dev/null
+}
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ $1
+ ;;
+ stop)
+ rh_status_q || exit 0
+ $1
+ ;;
+ restart)
+ $1
+ ;;
+ reload)
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart}"
+ exit 2
+esac
+exit $?
diff --git a/gluster-swift-container.init b/gluster-swift-container.init
new file mode 100755
index 0000000..1d27989
--- /dev/null
+++ b/gluster-swift-container.init
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+### BEGIN INIT INFO
+# Provides: gluster-swift-container
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Default-Stop: 0 1 6
+# Short-Description: Swift container server
+# Description: Container server for swift.
+### END INIT INFO
+
+# gluster-swift-container: swift container server
+#
+# chkconfig: - 20 80
+# description: Container server for swift.
+
+. /etc/rc.d/init.d/functions
+. /usr/share/gluster-swift/functions
+
+name="container"
+
+[ -e "/etc/sysconfig/gluster-swift-$name" ] && . "/etc/sysconfig/gluster-swift-$name"
+
+lockfile="/var/lock/subsys/gluster-swift-container"
+
+start() {
+ swift_action "$name" start
+ retval=$?
+ [ $retval -eq 0 ] && touch $lockfile
+ return $retval
+}
+
+stop() {
+ swift_action "$name" stop
+ retval=$?
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+rh_status() {
+ swift_action "$name" status
+}
+
+rh_status_q() {
+ rh_status &> /dev/null
+}
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ $1
+ ;;
+ stop)
+ rh_status_q || exit 0
+ $1
+ ;;
+ restart)
+ $1
+ ;;
+ reload)
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart}"
+ exit 2
+esac
+exit $?
diff --git a/gluster-swift-functions b/gluster-swift-functions
new file mode 100644
index 0000000..4b69ed8
--- /dev/null
+++ b/gluster-swift-functions
@@ -0,0 +1,64 @@
+# vim: filetype=sh
+
+. /etc/rc.d/init.d/functions
+
+swift_action() {
+ retval=0
+ server="$1"
+ call="swift_$2"
+
+ if [[ -f "/etc/swift/$server-server.conf" ]]; then
+ $call "$server" \
+ "/etc/swift/$server-server.conf" \
+ "/var/run/swift/$server-server.pid"
+ [ $? -ne 0 ] && retval=1
+ elif [[ -d "/etc/swift/$server-server/" ]]; then
+ declare -i count=0
+ mkdir -p /var/run/swift/$server-server
+ for name in $( ls "/etc/swift/$server-server/" ); do
+ $call "$server" \
+ "/etc/swift/$server-server/$name" \
+ "/var/run/swift/$server-server/$count.pid"
+ [ $? -ne 0 ] && retval=1
+ count=$count+1
+ done
+ fi
+ return $retval
+}
+
+swift_start() {
+ name="$1"
+ long_name="$name-server"
+ conf_file="$2"
+ pid_file="$3"
+
+ ulimit -n ${SWIFT_MAX_FILES-32768}
+ echo -n "Starting swift-$long_name: "
+ daemon --pidfile $pid_file \
+ "/usr/bin/swift-$long_name $conf_file &>/var/log/swift-startup.log & echo \$! > $pid_file"
+ retval=$?
+ echo
+ return $retval
+}
+
+swift_stop() {
+ name="$1"
+ long_name="$name-server"
+ conf_name="$2"
+ pid_file="$3"
+
+ echo -n "Stopping swift-$long_name: "
+ killproc -p $pid_file -d ${SWIFT_STOP_DELAY-15} $long_name
+ retval=$?
+ echo
+ return $retval
+}
+
+swift_status() {
+ name="$1"
+ long_name="$name-server"
+ conf_name="$2"
+ pid_file="$3"
+
+ status -p $pid_file $long_name
+}
diff --git a/gluster-swift-object.init b/gluster-swift-object.init
new file mode 100755
index 0000000..f0fe540
--- /dev/null
+++ b/gluster-swift-object.init
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+### BEGIN INIT INFO
+# Provides: gluster-swift-object
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Default-Stop: 0 1 6
+# Short-Description: Swift object server
+# Description: Object server for swift.
+### END INIT INFO
+
+# gluster-swift-object: swift object server
+#
+# chkconfig: - 20 80
+# description: Object server for swift.
+
+. /etc/rc.d/init.d/functions
+. /usr/share/gluster-swift/functions
+
+name="object"
+
+[ -e "/etc/sysconfig/gluster-swift-$name" ] && . "/etc/sysconfig/gluster-swift-$name"
+
+lockfile="/var/lock/subsys/gluster-swift-object"
+
+start() {
+ swift_action "$name" start
+ retval=$?
+ [ $retval -eq 0 ] && touch $lockfile
+ return $retval
+}
+
+stop() {
+ swift_action "$name" stop
+ retval=$?
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+rh_status() {
+ swift_action "$name" status
+}
+
+rh_status_q() {
+ rh_status &> /dev/null
+}
+
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ $1
+ ;;
+ stop)
+ rh_status_q || exit 0
+ $1
+ ;;
+ restart)
+ $1
+ ;;
+ reload)
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart}"
+ exit 2
+esac
+exit $?
diff --git a/gluster-swift-plugins.tar.gz b/gluster-swift-plugins.tar.gz
new file mode 100644
index 0000000..d036bec
Binary files /dev/null and b/gluster-swift-plugins.tar.gz differ
diff --git a/gluster-swift-proxy.init b/gluster-swift-proxy.init
new file mode 100755
index 0000000..052e05f
--- /dev/null
+++ b/gluster-swift-proxy.init
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+### BEGIN INIT INFO
+# Provides: gluster-swift-proxy
+# Required-Start: $remote_fs
+# Required-Stop: $remote_fs
+# Default-Stop: 0 1 6
+# Short-Description: Swift proxy server
+# Description: Account server for swift.
+### END INIT INFO
+
+# gluster-swift-proxy: swift proxy server
+#
+# chkconfig: - 20 80
+# description: Proxy server for swift.
+
+. /etc/rc.d/init.d/functions
+. /usr/share/gluster-swift/functions
+
+name="proxy"
+
+[ -e "/etc/sysconfig/gluster-swift-$name" ] && . "/etc/sysconfig/gluster-swift-$name"
+
+lockfile="/var/lock/subsys/gluster-swift-proxy"
+
+start() {
+ swift_action "$name" start
+ retval=$?
+ [ $retval -eq 0 ] && touch $lockfile
+ return $retval
+}
+
+stop() {
+ swift_action "$name" stop
+ retval=$?
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+rh_status() {
+ swift_action "$name" status
+}
+
+rh_status_q() {
+ rh_status &> /dev/null
+}
+
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ $1
+ ;;
+ stop)
+ rh_status_q || exit 0
+ $1
+ ;;
+ restart)
+ $1
+ ;;
+ reload)
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart}"
+ exit 2
+esac
+exit $?
diff --git a/glusterfs.spec b/glusterfs.spec
index 43299b6..847be0c 100644
--- a/glusterfs.spec
+++ b/glusterfs.spec
@@ -21,11 +21,12 @@
# rpmbuild -ta @PACKAGE_NAME at -@PACKAGE_VERSION at .tar.gz --without georeplication
%{?_without_georeplication:%global _without_georeplication --disable-geo-replication}
+%global SWIFTVER 1.4.8
Summary: Cluster File System
Name: glusterfs
Version: 3.3.0
-Release: 3%{?dist}
+Release: 4%{?dist}
License: GPLv3+ and (GPLv2 or LGPLv3+)
Group: System Environment/Base
Vendor: Red Hat
@@ -196,11 +197,165 @@ is in user space and easily manageable.
This package provides the development libraries.
+%package swift
+
+Summary: GlusterFS OpenStack Object Storage
+License: ASL 2.0
+BuildArch: noarch
+
+Source10: http://launchpad.net/swift/essex/%{SWIFTVER}/+download/swift-%{SWIFTVER}.tar.gz
+Source11: gluster-swift-functions
+Source12: gluster-swift-account.init
+Source13: gluster-swift-container.init
+Source14: gluster-swift-object.init
+Source15: gluster-swift-proxy.init
+Patch3: openstack-swift-newdeps.patch
+Patch4: openstack-swift-docmod.patch
+Patch5: openstack-swift-nonet.patch
+Patch6: swift.patch
+#BuildRoot: %(mktemp -ud %{_tmppath}/swift-%{SWIFTVER}-%{release}-XXXXXX)
+
+BuildRequires: python-devel
+BuildRequires: python-setuptools
+BuildRequires: python-netifaces
+%if ( 0%{?rhel} && 0%{?rhel} < 7 )
+BuildRequires: python-webob1.0
+%else
+BuildRequires: python-webob
+%endif
+BuildRequires: python-paste-deploy
+BuildRequires: dos2unix
+Requires: python-configobj
+Requires: python-eventlet >= 0.9.8
+Requires: python-greenlet >= 0.3.1
+Requires: python-paste-deploy
+Requires: python-simplejson
+Requires: pyxattr
+Requires: python-setuptools
+Requires: python-netifaces
+Requires: python-netifaces
+
+Conflicts: openstack-swift
+
+
+%description swift
+
+OpenStack Object Storage (swift) aggregates commodity servers to work together
+in clusters for reliable, redundant, and large-scale storage of static objects.
+Objects are written to multiple hardware devices in the data center, with the
+OpenStack software responsible for ensuring data replication and integrity
+across the cluster. Storage clusters can scale horizontally by adding new nodes,
+which are automatically configured. Should a node fail, OpenStack works to
+replicate its content from other active nodes. Because OpenStack uses software
+logic to ensure data replication and distribution across different devices,
+inexpensive commodity hard drives and servers can be used in lieu of more
+expensive equipment.
+
+
+%package swift-account
+Summary: A swift account server
+Group: Applications/System
+License: ASL 2.0
+BuildArch: noarch
+Requires: %{name}-swift = %{version}-%{release}
+
+%description swift-account
+OpenStack Object Storage (swift) aggregates commodity servers to work together
+in clusters for reliable, redundant, and large-scale storage of static objects.
+
+This package contains the %{name}-swift account server.
+
+
+%package swift-container
+Summary: A swift container server
+Group: Applications/System
+License: ASL 2.0
+BuildArch: noarch
+Requires: %{name}-swift = %{version}-%{release}
+
+%description swift-container
+OpenStack Object Storage (swift) aggregates commodity servers to work together
+in clusters for reliable, redundant, and large-scale storage of static objects.
+
+This package contains the %{name}-swift container server.
+
+%package swift-object
+Summary: A swift object server
+Group: Applications/System
+License: ASL 2.0
+BuildArch: noarch
+Requires: %{name}-swift = %{version}-%{release}
+Requires: rsync >= 3.0
+
+%description swift-object
+OpenStack Object Storage (swift) aggregates commodity servers to work together
+in clusters for reliable, redundant, and large-scale storage of static objects.
+
+This package contains the %{name}-swift object server.
+
+%package swift-proxy
+Summary: A swift proxy server
+Group: Applications/System
+License: ASL 2.0
+BuildArch: noarch
+Requires: %{name}-swift = %{version}-%{release}
+
+%description swift-proxy
+OpenStack Object Storage (swift) aggregates commodity servers to work together
+in clusters for reliable, redundant, and large-scale storage of static objects.
+
+This package contains the %{name}-swift proxy server.
+
+
+%package swift-doc
+Summary: Documentation for %{name}
+Group: Documentation
+BuildArch: noarch
+# Required for generating docs
+BuildRequires: python-eventlet
+BuildRequires: python-simplejson
+BuildRequires: python-webob
+BuildRequires: python-sphinx
+BuildRequires: pyxattr
+
+%description swift-doc
+OpenStack Object Storage (swift) aggregates commodity servers to work together
+in clusters for reliable, redundant, and large-scale storage of static objects.
+
+This package contains documentation files for %{name}-swift.
+
+%package swift-plugin
+Summary: GlusterFS Unified File and Object Storage.
+Group: Applications/System
+License: ASL 2.0
+BuildArch: noarch
+Requires: %{name}-swift = %{version}-%{release}
+Requires: memcached
+Requires: openssl
+Requires: python
+Source20: gluster-swift-plugins.tar.gz
+
+%description swift-plugin
+Gluster Unified File and Object Storage unifies NAS and object storage
+technology. This provides a system for data storage that enables users to access
+the same data as an object and as a file, simplifying management and controlling
+storage costs.
+
+
+
%prep
%setup -q -n %{name}-%{version}
+%setup -q -T -D -n %{name}-%{version} -a 10
+%setup -q -T -D -n %{name}-%{version} -a 20
%patch0 -p0
%patch1 -p0
%patch2 -p0
+cd swift-%{SWIFTVER}
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+dos2unix LICENSE
%build
./autogen.sh
@@ -212,6 +367,12 @@ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
%{__make} %{?_smp_mflags}
+cd swift-%{SWIFTVER}
+%{__python} setup.py build
+%{__mkdir_p} doc/build
+%{__python} setup.py build_sphinx
+cd ..
+
%install
%{__rm} -rf %{buildroot}
%{__make} install DESTDIR=%{buildroot}
@@ -309,6 +470,44 @@ touch %{buildroot}%{_sharedstatedir}/glusterd/glusterd.info
%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/nfs
%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/peers
+cd swift-%{SWIFTVER}
+%{__python} setup.py install -O1 --skip-build --root %{buildroot}
+# Init helper functions
+%{__install} -p -D -m 644 %{SOURCE11} %{buildroot}%{_datarootdir}/gluster-swift/functions
+# Init scripts
+%{__install} -p -D -m 755 %{SOURCE12} %{buildroot}%{_initrddir}/gluster-swift-account
+%{__install} -p -D -m 755 %{SOURCE13} %{buildroot}%{_initrddir}/gluster-swift-container
+%{__install} -p -D -m 755 %{SOURCE14} %{buildroot}%{_initrddir}/gluster-swift-object
+%{__install} -p -D -m 755 %{SOURCE15} %{buildroot}%{_initrddir}/gluster-swift-proxy
+# Remove tests
+%{__rm} -rf %{buildroot}/%{python_sitelib}/test
+# Misc other
+%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift
+%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift/account-server
+%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift/container-server
+%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift/object-server
+%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift/proxy-server
+# Install pid directory
+%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift
+%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/account-server
+%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/container-server
+%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/object-server
+%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/proxy-server
+cd ..
+
+%{__mkdir -p} %{buildroot}%{python_sitelib}/swift/plugins
+#%{__mkdir -p} %{buildroot}%{_sysconfdir}/swift
+cd plugins
+%{__install} -p -D -m 755 constraints.py %{buildroot}%{python_sitelib}/swift/plugins
+%{__install} -p -D -m 755 DiskDir.py %{buildroot}%{python_sitelib}/swift/plugins
+%{__install} -p -D -m 755 DiskFile.py %{buildroot}%{python_sitelib}/swift/plugins
+%{__install} -p -D -m 755 Glusterfs.py %{buildroot}%{python_sitelib}/swift/plugins
+%{__install} -p -D -m 755 __init__.py %{buildroot}%{python_sitelib}/swift/plugins
+%{__install} -p -D -m 755 utils.py %{buildroot}%{python_sitelib}/swift/plugins
+cp -r conf/* %{buildroot}%{_sysconfdir}/swift
+cd ..
+
+
%clean
%{__rm} -rf %{buildroot}
@@ -428,15 +627,105 @@ touch %{buildroot}%{_sharedstatedir}/glusterd/glusterd.info
%exclude %{_includedir}/glusterfs/y.tab.h
%{_libdir}/*.so
+%files swift
+%defattr(-,root,root,-)
+%doc swift-%{SWIFTVER}/AUTHORS
+%doc swift-%{SWIFTVER}/LICENSE
+%doc swift-%{SWIFTVER}/README
+%doc swift-%{SWIFTVER}/etc/dispersion.conf-sample
+%doc swift-%{SWIFTVER}/etc/drive-audit.conf-sample
+%doc swift-%{SWIFTVER}/etc/object-expirer.conf-sample
+%doc swift-%{SWIFTVER}/etc/swift.conf-sample
+%dir %{_datarootdir}/gluster-swift/functions
+%dir %attr(0755, swift, swift) %{_localstatedir}/run/swift
+%dir %{_sysconfdir}/swift
+%dir %{python_sitelib}/swift
+%{_bindir}/swift
+%{_bindir}/swift-account-audit
+%{_bindir}/swift-bench
+%{_bindir}/swift-drive-audit
+%{_bindir}/swift-get-nodes
+%{_bindir}/swift-init
+%{_bindir}/swift-ring-builder
+%{_bindir}/swift-dispersion-populate
+%{_bindir}/swift-dispersion-report
+%{_bindir}/swift-recon*
+%{_bindir}/swift-object-expirer
+%{_bindir}/swift-oldies
+%{_bindir}/swift-orphans
+%{_bindir}/swift-form-signature
+%{_bindir}/swift-temp-url
+%{python_sitelib}/swift/*.py*
+%{python_sitelib}/swift/common
+%{python_sitelib}/swift-%{SWIFTVER}-*.egg-info
+
+%files swift-account
+%defattr(-,root,root,-)
+%doc swift-%{SWIFTVER}/etc/account-server.conf-sample
+%dir %{_initrddir}/gluster-swift-account
+%dir %attr(0755, swift, swift) %{_localstatedir}/run/swift/account-server
+%dir %{_sysconfdir}/swift/account-server
+%{_bindir}/swift-account-auditor
+%{_bindir}/swift-account-reaper
+%{_bindir}/swift-account-replicator
+%{_bindir}/swift-account-server
+%{python_sitelib}/swift/account
+
+%files swift-container
+%defattr(-,root,root,-)
+%doc swift-%{SWIFTVER}/etc/container-server.conf-sample
+%dir %{_initrddir}/gluster-swift-container
+%dir %attr(0755, swift, swift) %{_localstatedir}/run/swift/container-server
+%dir %{_sysconfdir}/swift/container-server
+%{_bindir}/swift-container-auditor
+%{_bindir}/swift-container-server
+%{_bindir}/swift-container-replicator
+%{_bindir}/swift-container-updater
+%{_bindir}/swift-container-sync
+%{python_sitelib}/swift/container
+
+%files swift-object
+%defattr(-,root,root,-)
+%doc swift-%{SWIFTVER}/etc/object-server.conf-sample
+%doc swift-%{SWIFTVER}/etc/rsyncd.conf-sample
+%dir %{_initrddir}/gluster-swift-object
+%dir %attr(0755, swift, swift) %{_localstatedir}/run/swift/object-server
+%dir %{_sysconfdir}/swift/object-server
+%{_bindir}/swift-object-auditor
+%{_bindir}/swift-object-info
+%{_bindir}/swift-object-replicator
+%{_bindir}/swift-object-server
+%{_bindir}/swift-object-updater
+%{python_sitelib}/swift/obj
+
+%files swift-proxy
+%defattr(-,root,root,-)
+%doc swift-%{SWIFTVER}/etc/proxy-server.conf-sample
+%dir %{_initrddir}/gluster-swift-proxy
+%dir %attr(0755, swift, swift) %{_localstatedir}/run/swift/proxy-server
+%dir %{_sysconfdir}/swift/proxy-server
+%{_bindir}/swift-proxy-server
+%{python_sitelib}/swift/proxy
+
+%files swift-doc
+%defattr(-,root,root,-)
+%doc swift-%{SWIFTVER}/LICENSE
+
+%files swift-plugin
+%defattr(-,root,root,-)
+%{python_sitelib}/swift/plugins
+%{_sysconfdir}/swift
+
+
%post server
# Legacy server
%_init_enable glusterd
%_init_enable glusterfsd
-# Genuine Fedora (and EPEL) builds never put gluster files in /etc; if
+# Genuine Fedora (and EPEL) builds never put gluster files in /etc; if
# there are any files in /etc from a prior gluster.org install, move them
# to /var/lib. (N.B. Starting with 3.3.0 all gluster files are in /var/lib
-# in gluster.org RPMs.) Be careful to copy them on the off chance that
+# in gluster.org RPMs.) Be careful to copy them on the off chance that
# /etc and /var/lib are on separate file systems
if [ -d /etc/glusterd ]; then
%{__mkdir_p} /var/lib
@@ -459,7 +748,7 @@ fi
# but first make certain that there are no old libs around to bite us
# BZ 834847
if [ -e /etc/ld.so.conf.d/glusterfs.conf ]; then
- rm -f /etc/ld.so.conf.d/glusterfs.conf
+ rm -f /etc/ld.so.conf.d/glusterfs.conf
/sbin/ldconfig
fi
pidof -c -o %PPID -x glusterd &> /dev/null
@@ -472,6 +761,70 @@ else
glusterd --xlator-option *.upgrade=on -N
fi
+%pre swift
+getent group swift >/dev/null || groupadd -r swift -g 160
+getent passwd swift >/dev/null || \
+useradd -r -g swift -u 160 -d %{_sharedstatedir}/swift -s /sbin/nologin \
+-c "OpenStack Swift Daemons" swift
+exit 0
+
+%post swift-account
+/sbin/chkconfig --add gluster-swift-account
+
+%preun swift-account
+if [ $1 = 0 ] ; then
+ /sbin/service gluster-swift-account stop >/dev/null 2>&1
+ /sbin/chkconfig --del gluster-swift-account
+fi
+
+%postun swift-account
+if [ "$1" -ge "1" ] ; then
+ /sbin/service gluster-swift-account condrestart >/dev/null 2>&1 || :
+fi
+
+%post swift-container
+/sbin/chkconfig --add gluster-swift-container
+
+%preun swift-container
+if [ $1 = 0 ] ; then
+ /sbin/service gluster-swift-container stop >/dev/null 2>&1
+ /sbin/chkconfig --del gluster-swift-container
+fi
+
+%postun swift-container
+if [ "$1" -ge "1" ] ; then
+ /sbin/service gluster-swift-container condrestart >/dev/null 2>&1 || :
+fi
+
+%post swift-object
+/sbin/chkconfig --add gluster-swift-object
+
+%preun swift-object
+if [ $1 = 0 ] ; then
+ /sbin/service gluster-swift-object stop >/dev/null 2>&1
+ /sbin/chkconfig --del gluster-swift-object
+fi
+
+%postun swift-object
+if [ "$1" -ge "1" ] ; then
+ /sbin/service gluster-swift-object condrestart >/dev/null 2>&1 || :
+fi
+
+%post swift-proxy
+/sbin/chkconfig --add gluster-swift-proxy
+
+%preun swift-proxy
+if [ $1 = 0 ] ; then
+ /sbin/service gluster-swift-proxy stop >/dev/null 2>&1
+ /sbin/chkconfig --del gluster-swift-proxy
+fi
+
+%postun swift-proxy
+if [ "$1" -ge "1" ] ; then
+ /sbin/service gluster-swift-proxy condrestart >/dev/null 2>&1 || :
+fi
+
+
%preun server
if [ $1 -eq 0 ]; then
%_init_stop glusterfsd
@@ -484,7 +837,11 @@ if [ $1 -ge 1 ]; then
%_init_restart glusterfsd
fi
+
%changelog
+* Fri Aug 10 2012 Kaleb S. KEITHLEY <kkeithle[at]redhat.com> - 3.3.0-4
+- now with UFO (openstack-swift)
+
* Wed Jul 18 2012 Kaleb S. KEITHLEY <kkeithle[at]redhat.com> - 3.3.0-3
- fix segv in cmd_heal_volume_brick_out (RHEL seems particularly
sensitive to this bug.)
diff --git a/openstack-swift-docmod.patch b/openstack-swift-docmod.patch
new file mode 100644
index 0000000..03f193c
--- /dev/null
+++ b/openstack-swift-docmod.patch
@@ -0,0 +1,14 @@
+--- swift-1.4.4/doc/source/conf.py.orig 2011-11-24 08:59:50.000000000 -0500
++++ swift-1.4.4/doc/source/conf.py 2012-01-04 22:35:55.571492761 -0500
+@@ -31,7 +31,10 @@
+ # If extensions (or modules to document with autodoc) are in another directory,
+ # add these directories to sys.path here. If the directory is relative to the
+ # documentation root, use os.path.abspath to make it absolute, like shown here.
+-sys.path.append([os.path.abspath('../swift'), os.path.abspath('..'), os.path.abspath('../bin')])
++sys.path = [os.path.abspath('../../swift'),
++ os.path.abspath('../..'),
++ os.path.abspath('../../bin')
++ ] + sys.path
+
+ # -- General configuration -----------------------------------------------------
+
diff --git a/openstack-swift-newdeps.patch b/openstack-swift-newdeps.patch
new file mode 100644
index 0000000..3b4222a
--- /dev/null
+++ b/openstack-swift-newdeps.patch
@@ -0,0 +1,36 @@
+diff -ru swift-1.4.4-ORIG/swift/__init__.py swift-1.4.4/swift/__init__.py
+--- swift-1.4.4-ORIG/swift/__init__.py 2011-11-24 14:59:50.000000000 +0100
++++ swift-1.4.4/swift/__init__.py 2012-01-04 00:09:10.122030579 +0100
+@@ -1,3 +1,32 @@
++import sys
++import pkg_resources
++
++# If there is a conflicting non egg module,
++# i.e. an older standard system module installed,
++# then replace it with this requirement
++def replace_dist(requirement):
++ try:
++ return pkg_resources.require(requirement)
++ except pkg_resources.VersionConflict:
++ e = sys.exc_info()[1]
++ dist=e.args[0]
++ req=e.args[1]
++ if dist.key == req.key and not dist.location.endswith('.egg'):
++ del pkg_resources.working_set.by_key[dist.key]
++ # We assume there is no need to adjust sys.path
++ # and the associated pkg_resources.working_set.entries
++ return pkg_resources.require(requirement)
++
++replace_dist("WebOb >= 1.0")
++
++replace_dist("PasteDeploy >= 1.5.0")
++# This hack is needed because replace_dist() results in
++# the standard paste module path being at the start of __path__.
++# TODO: See can we get pkg_resources to do the right thing directly
++import paste
++paste.__path__.insert(0, paste.__path__.pop(-1))
++
++
+ import gettext
+
+
diff --git a/openstack-swift-nonet.patch b/openstack-swift-nonet.patch
new file mode 100644
index 0000000..af8cad4
--- /dev/null
+++ b/openstack-swift-nonet.patch
@@ -0,0 +1,11 @@
+--- swift-1.4.4/doc/source/conf.py.orig 2012-01-04 22:40:43.190300958 -0500
++++ swift-1.4.4/doc/source/conf.py 2012-01-04 22:41:26.980492712 -0500
+@@ -40,7 +40,7 @@
+
+ # Add any Sphinx extension module names here, as strings. They can be extensions
+ # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig']
++extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig']
+ todo_include_todos = True
+
+ # Add any paths that contain templates here, relative to this directory.
diff --git a/sources b/sources
index 88da1ce..0e24a6b 100644
--- a/sources
+++ b/sources
@@ -1 +1,2 @@
3ddf782421f54c60b9da9607b0c32ec1 glusterfs-3.3.0.tar.gz
+785ae9ba4e1f6fc256cd6a697bb2861f swift-1.4.8.tar.gz
diff --git a/swift.patch b/swift.patch
new file mode 100644
index 0000000..8ed5070
--- /dev/null
+++ b/swift.patch
@@ -0,0 +1,797 @@
+diff --git a/setup.py b/setup.py
+index d195d34..b5b5ca2 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1,5 +1,6 @@
+ #!/usr/bin/python
+ # Copyright (c) 2010-2012 OpenStack, LLC.
++# Copyright (c) 2011 Red Hat, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+@@ -94,6 +95,7 @@ setup(
+ 'tempurl=swift.common.middleware.tempurl:filter_factory',
+ 'formpost=swift.common.middleware.formpost:filter_factory',
+ 'name_check=swift.common.middleware.name_check:filter_factory',
++ 'gluster=swift.common.middleware.gluster:filter_factory',
+ ],
+ },
+ )
+diff --git a/swift/account/server.py b/swift/account/server.py
+index 800b3c0..cb17970 100644
+--- a/swift/account/server.py
++++ b/swift/account/server.py
+@@ -1,4 +1,5 @@
+ # Copyright (c) 2010-2012 OpenStack, LLC.
++# Copyright (c) 2011 Red Hat, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+@@ -31,7 +32,7 @@ import simplejson
+
+ from swift.common.db import AccountBroker
+ from swift.common.utils import get_logger, get_param, hash_path, \
+- normalize_timestamp, split_path, storage_directory
++ normalize_timestamp, split_path, storage_directory, plugin_enabled
+ from swift.common.constraints import ACCOUNT_LISTING_LIMIT, \
+ check_mount, check_float, check_utf8
+ from swift.common.db_replicator import ReplicatorRpc
+@@ -39,6 +40,8 @@ from swift.common.db_replicator import ReplicatorRpc
+
+ DATADIR = 'accounts'
+
++if plugin_enabled():
++ from swift.plugins.DiskDir import DiskAccount
+
+ class AccountController(object):
+ """WSGI controller for the account server."""
+@@ -52,8 +55,12 @@ class AccountController(object):
+ self.mount_check, logger=self.logger)
+ self.auto_create_account_prefix = \
+ conf.get('auto_create_account_prefix') or '.'
++ self.fs_object = None
+
+ def _get_account_broker(self, drive, part, account):
++ if self.fs_object:
++ return DiskAccount(self.root, account, self.fs_object);
++
+ hsh = hash_path(account)
+ db_dir = storage_directory(DATADIR, part, hsh)
+ db_path = os.path.join(self.root, drive, db_dir, hsh + '.db')
+@@ -121,9 +128,15 @@ class AccountController(object):
+ if broker.is_deleted():
+ return HTTPConflict(request=req)
+ metadata = {}
+- metadata.update((key, (value, timestamp))
+- for key, value in req.headers.iteritems()
+- if key.lower().startswith('x-account-meta-'))
++ if not self.fs_object:
++ metadata.update((key, (value, timestamp))
++ for key, value in req.headers.iteritems()
++ if key.lower().startswith('x-account-meta-'))
++ else:
++ metadata.update((key, value)
++ for key, value in req.headers.iteritems()
++ if key.lower().startswith('x-account-meta-'))
++
+ if metadata:
+ broker.update_metadata(metadata)
+ if created:
+@@ -153,6 +166,9 @@ class AccountController(object):
+ broker.stale_reads_ok = True
+ if broker.is_deleted():
+ return HTTPNotFound(request=req)
++ if self.fs_object and not self.fs_object.object_only:
++ broker.list_containers_iter(None, None,None,
++ None, None)
+ info = broker.get_info()
+ headers = {
+ 'X-Account-Container-Count': info['container_count'],
+@@ -164,9 +180,16 @@ class AccountController(object):
+ container_ts = broker.get_container_timestamp(container)
+ if container_ts is not None:
+ headers['X-Container-Timestamp'] = container_ts
+- headers.update((key, value)
+- for key, (value, timestamp) in broker.metadata.iteritems()
+- if value != '')
++ if not self.fs_object:
++ headers.update((key, value)
++ for key, (value, timestamp) in broker.metadata.iteritems()
++ if value != '')
++ else:
++ headers.update((key, value)
++ for key, value in broker.metadata.iteritems()
++ if value != '')
++
++
+ return HTTPNoContent(request=req, headers=headers)
+
+ def GET(self, req):
+@@ -190,9 +213,15 @@ class AccountController(object):
+ 'X-Account-Bytes-Used': info['bytes_used'],
+ 'X-Timestamp': info['created_at'],
+ 'X-PUT-Timestamp': info['put_timestamp']}
+- resp_headers.update((key, value)
+- for key, (value, timestamp) in broker.metadata.iteritems()
+- if value != '')
++ if not self.fs_object:
++ resp_headers.update((key, value)
++ for key, (value, timestamp) in broker.metadata.iteritems()
++ if value != '')
++ else:
++ resp_headers.update((key, value)
++ for key, value in broker.metadata.iteritems()
++ if value != '')
++
+ try:
+ prefix = get_param(req, 'prefix')
+ delimiter = get_param(req, 'delimiter')
+@@ -224,6 +253,7 @@ class AccountController(object):
+ content_type='text/plain', request=req)
+ account_list = broker.list_containers_iter(limit, marker, end_marker,
+ prefix, delimiter)
++
+ if out_content_type == 'application/json':
+ json_pattern = ['"name":%s', '"count":%s', '"bytes":%s']
+ json_pattern = '{' + ','.join(json_pattern) + '}'
+@@ -298,15 +328,29 @@ class AccountController(object):
+ return HTTPNotFound(request=req)
+ timestamp = normalize_timestamp(req.headers['x-timestamp'])
+ metadata = {}
+- metadata.update((key, (value, timestamp))
+- for key, value in req.headers.iteritems()
+- if key.lower().startswith('x-account-meta-'))
++ if not self.fs_object:
++ metadata.update((key, (value, timestamp))
++ for key, value in req.headers.iteritems()
++ if key.lower().startswith('x-account-meta-'))
++ else:
++ metadata.update((key, value)
++ for key, value in req.headers.iteritems()
++ if key.lower().startswith('x-account-meta-'))
+ if metadata:
+ broker.update_metadata(metadata)
+ return HTTPNoContent(request=req)
+
++ def plugin(self, env):
++ if env.get('Gluster_enabled', False):
++ self.fs_object = env.get('fs_object')
++ self.root = env.get('root')
++ self.mount_check = False
++ else:
++ self.fs_object = None
++
+ def __call__(self, env, start_response):
+ start_time = time.time()
++ self.plugin(env)
+ req = Request(env)
+ self.logger.txn_id = req.headers.get('x-trans-id', None)
+ if not check_utf8(req.path_info):
+diff --git a/swift/common/middleware/gluster.py b/swift/common/middleware/gluster.py
+new file mode 100644
+index 0000000..341285d
+--- /dev/null
++++ b/swift/common/middleware/gluster.py
+@@ -0,0 +1,55 @@
++# Copyright (c) 2011 Red Hat, Inc.
++#
++# Licensed under the Apache License, Version 2.0 (the "License");
++# you may not use this file except in compliance with the License.
++# You may obtain a copy of the License at
++#
++# http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS,
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
++# implied.
++# See the License for the specific language governing permissions and
++# limitations under the License.
++
++from swift.common.utils import get_logger, plugin_enabled
++from swift import plugins
++from ConfigParser import ConfigParser
++
++class Gluster_plugin(object):
++ """
++ Update the environment with keys that reflect Gluster_plugin enabled
++ """
++
++ def __init__(self, app, conf):
++ self.app = app
++ self.conf = conf
++ self.fs_name = 'Glusterfs'
++ self.logger = get_logger(conf, log_route='gluster')
++
++ def __call__(self, env, start_response):
++ if not plugin_enabled():
++ return self.app(env, start_response)
++ env['Gluster_enabled'] =True
++ fs_object = getattr(plugins, self.fs_name, False)
++ if not fs_object:
++ raise Exception('%s plugin not found', self.fs_name)
++
++ env['fs_object'] = fs_object()
++ fs_conf = ConfigParser()
++ if fs_conf.read('/etc/swift/fs.conf'):
++ try:
++ env['root'] = fs_conf.get ('DEFAULT', 'mount_path')
++ except NoSectionError, NoOptionError:
++ self.logger.exception(_('ERROR mount_path not present'))
++ return self.app(env, start_response)
++
++def filter_factory(global_conf, **local_conf):
++ """Returns a WSGI filter app for use with paste.deploy."""
++ conf = global_conf.copy()
++ conf.update(local_conf)
++
++ def gluster_filter(app):
++ return Gluster_plugin(app, conf)
++ return gluster_filter
+diff --git a/swift/common/utils.py b/swift/common/utils.py
+index 47edce8..03701ce 100644
+--- a/swift/common/utils.py
++++ b/swift/common/utils.py
+@@ -1,4 +1,5 @@
+ # Copyright (c) 2010-2012 OpenStack, LLC.
++# Copyright (c) 2011 Red Hat, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+@@ -1138,3 +1139,11 @@ def streq_const_time(s1, s2):
+ for (a, b) in zip(s1, s2):
+ result |= ord(a) ^ ord(b)
+ return result == 0
++
++def plugin_enabled():
++ swift_conf = ConfigParser()
++ swift_conf.read(os.path.join('/etc/swift', 'swift.conf'))
++ try:
++ return swift_conf.get('DEFAULT', 'Enable_plugin', 'no') in TRUE_VALUES
++ except NoOptionError, NoSectionError:
++ return False
+diff --git a/swift/container/server.py b/swift/container/server.py
+index 8a18cfd..93943a3 100644
+--- a/swift/container/server.py
++++ b/swift/container/server.py
+@@ -1,4 +1,5 @@
+ # Copyright (c) 2010-2012 OpenStack, LLC.
++# Copyright (c) 2011 Red Hat, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+@@ -31,7 +32,8 @@ from webob.exc import HTTPAccepted, HTTPBadRequest, HTTPConflict, \
+
+ from swift.common.db import ContainerBroker
+ from swift.common.utils import get_logger, get_param, hash_path, \
+- normalize_timestamp, storage_directory, split_path, validate_sync_to
++ normalize_timestamp, storage_directory, split_path, validate_sync_to, \
++ plugin_enabled
+ from swift.common.constraints import CONTAINER_LISTING_LIMIT, \
+ check_mount, check_float, check_utf8
+ from swift.common.bufferedhttp import http_connect
+@@ -40,6 +42,9 @@ from swift.common.db_replicator import ReplicatorRpc
+
+ DATADIR = 'containers'
+
++if plugin_enabled():
++ from swift.plugins.DiskDir import DiskDir
++
+
+ class ContainerController(object):
+ """WSGI Controller for the container server."""
+@@ -62,6 +67,7 @@ class ContainerController(object):
+ ContainerBroker, self.mount_check, logger=self.logger)
+ self.auto_create_account_prefix = \
+ conf.get('auto_create_account_prefix') or '.'
++ self.fs_object = None
+
+ def _get_container_broker(self, drive, part, account, container):
+ """
+@@ -73,6 +79,11 @@ class ContainerController(object):
+ :param container: container name
+ :returns: ContainerBroker object
+ """
++ if self.fs_object:
++ return DiskDir(self.root, drive, part, account,
++ container, self.logger,
++ fs_object = self.fs_object)
++
+ hsh = hash_path(account, container)
+ db_dir = storage_directory(DATADIR, part, hsh)
+ db_path = os.path.join(self.root, drive, db_dir, hsh + '.db')
+@@ -211,10 +222,18 @@ class ContainerController(object):
+ if broker.is_deleted():
+ return HTTPConflict(request=req)
+ metadata = {}
+- metadata.update((key, (value, timestamp))
+- for key, value in req.headers.iteritems()
+- if key.lower() in self.save_headers or
+- key.lower().startswith('x-container-meta-'))
++ #Note: check the structure of req.headers
++ if not self.fs_object:
++ metadata.update((key, (value, timestamp))
++ for key, value in req.headers.iteritems()
++ if key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-'))
++ else:
++ metadata.update((key, value)
++ for key, value in req.headers.iteritems()
++ if key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-'))
++
+ if metadata:
+ if 'X-Container-Sync-To' in metadata:
+ if 'X-Container-Sync-To' not in broker.metadata or \
+@@ -222,6 +241,7 @@ class ContainerController(object):
+ broker.metadata['X-Container-Sync-To'][0]:
+ broker.set_x_container_sync_points(-1, -1)
+ broker.update_metadata(metadata)
++
+ resp = self.account_update(req, account, container, broker)
+ if resp:
+ return resp
+@@ -245,6 +265,11 @@ class ContainerController(object):
+ broker.stale_reads_ok = True
+ if broker.is_deleted():
+ return HTTPNotFound(request=req)
++
++ if self.fs_object and not self.fs_object.object_only:
++ broker.list_objects_iter(None, None, None, None,
++ None, None)
++
+ info = broker.get_info()
+ headers = {
+ 'X-Container-Object-Count': info['object_count'],
+@@ -252,10 +277,17 @@ class ContainerController(object):
+ 'X-Timestamp': info['created_at'],
+ 'X-PUT-Timestamp': info['put_timestamp'],
+ }
+- headers.update((key, value)
+- for key, (value, timestamp) in broker.metadata.iteritems()
+- if value != '' and (key.lower() in self.save_headers or
+- key.lower().startswith('x-container-meta-')))
++ if not self.fs_object:
++ headers.update((key, value)
++ for key, (value, timestamp) in broker.metadata.iteritems()
++ if value != '' and (key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-')))
++ else:
++ headers.update((key, value)
++ for key, value in broker.metadata.iteritems()
++ if value != '' and (key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-')))
++
+ return HTTPNoContent(request=req, headers=headers)
+
+ def GET(self, req):
+@@ -268,6 +300,7 @@ class ContainerController(object):
+ request=req)
+ if self.mount_check and not check_mount(self.root, drive):
+ return Response(status='507 %s is not mounted' % drive)
++
+ broker = self._get_container_broker(drive, part, account, container)
+ broker.pending_timeout = 0.1
+ broker.stale_reads_ok = True
+@@ -280,10 +313,17 @@ class ContainerController(object):
+ 'X-Timestamp': info['created_at'],
+ 'X-PUT-Timestamp': info['put_timestamp'],
+ }
+- resp_headers.update((key, value)
+- for key, (value, timestamp) in broker.metadata.iteritems()
+- if value != '' and (key.lower() in self.save_headers or
+- key.lower().startswith('x-container-meta-')))
++ if not self.fs_object:
++ resp_headers.update((key, value)
++ for key, (value, timestamp) in broker.metadata.iteritems()
++ if value != '' and (key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-')))
++ else:
++ resp_headers.update((key, value)
++ for key, value in broker.metadata.iteritems()
++ if value != '' and (key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-')))
++
+ try:
+ path = get_param(req, 'path')
+ prefix = get_param(req, 'prefix')
+@@ -414,10 +454,17 @@ class ContainerController(object):
+ return HTTPNotFound(request=req)
+ timestamp = normalize_timestamp(req.headers['x-timestamp'])
+ metadata = {}
+- metadata.update((key, (value, timestamp))
+- for key, value in req.headers.iteritems()
+- if key.lower() in self.save_headers or
+- key.lower().startswith('x-container-meta-'))
++ if not self.fs_object:
++ metadata.update((key, (value, timestamp))
++ for key, value in req.headers.iteritems()
++ if key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-'))
++ else:
++ metadata.update((key, value)
++ for key, value in req.headers.iteritems()
++ if key.lower() in self.save_headers or
++ key.lower().startswith('x-container-meta-'))
++
+ if metadata:
+ if 'X-Container-Sync-To' in metadata:
+ if 'X-Container-Sync-To' not in broker.metadata or \
+@@ -427,8 +474,19 @@ class ContainerController(object):
+ broker.update_metadata(metadata)
+ return HTTPNoContent(request=req)
+
++ def plugin(self, env):
++ if env.get('Gluster_enabled', False):
++ self.fs_object = env.get('fs_object')
++ if not self.fs_object:
++ raise NoneTypeError
++ self.root = env.get('root')
++ self.mount_check = False
++ else:
++ self.fs_object = None
++
+ def __call__(self, env, start_response):
+ start_time = time.time()
++ self.plugin(env)
+ req = Request(env)
+ self.logger.txn_id = req.headers.get('x-trans-id', None)
+ if not check_utf8(req.path_info):
+diff --git a/swift/obj/server.py b/swift/obj/server.py
+index 9cca16b..a45daff 100644
+--- a/swift/obj/server.py
++++ b/swift/obj/server.py
+@@ -1,4 +1,5 @@
+ # Copyright (c) 2010-2012 OpenStack, LLC.
++# Copyright (c) 2011 Red Hat, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+@@ -26,6 +27,7 @@ from hashlib import md5
+ from tempfile import mkstemp
+ from urllib import unquote
+ from contextlib import contextmanager
++from ConfigParser import ConfigParser
+
+ from webob import Request, Response, UTC
+ from webob.exc import HTTPAccepted, HTTPBadRequest, HTTPCreated, \
+@@ -37,16 +39,23 @@ from eventlet import sleep, Timeout, tpool
+
+ from swift.common.utils import mkdirs, normalize_timestamp, \
+ storage_directory, hash_path, renamer, fallocate, \
+- split_path, drop_buffer_cache, get_logger, write_pickle
++ split_path, drop_buffer_cache, get_logger, write_pickle, \
++ plugin_enabled
+ from swift.common.bufferedhttp import http_connect
+-from swift.common.constraints import check_object_creation, check_mount, \
+- check_float, check_utf8
++if plugin_enabled():
++ from swift.plugins.constraints import check_object_creation
++ from swift.plugins.utils import X_TYPE, X_OBJECT_TYPE, FILE, DIR, MARKER_DIR, \
++ OBJECT, DIR_TYPE, FILE_TYPE
++else:
++ from swift.common.constraints import check_object_creation
++
++from swift.common.constraints import check_mount, check_float, check_utf8
++
+ from swift.common.exceptions import ConnectionTimeout, DiskFileError, \
+ DiskFileNotExist
+ from swift.obj.replicator import tpooled_get_hashes, invalidate_hash, \
+ quarantine_renamer
+
+-
+ DATADIR = 'objects'
+ ASYNCDIR = 'async_pending'
+ PICKLE_PROTOCOL = 2
+@@ -339,6 +348,9 @@ class DiskFile(object):
+ raise
+ raise DiskFileNotExist('Data File does not exist.')
+
++if plugin_enabled():
++ from swift.plugins.DiskFile import Gluster_DiskFile
++
+
+ class ObjectController(object):
+ """Implements the WSGI application for the Swift Object Server."""
+@@ -377,6 +389,17 @@ class ObjectController(object):
+ 'expiring_objects'
+ self.expiring_objects_container_divisor = \
+ int(conf.get('expiring_objects_container_divisor') or 86400)
++ self.fs_object = None
++
++ def get_DiskFile_obj(self, path, device, partition, account, container, obj,
++ logger, keep_data_fp=False, disk_chunk_size=65536):
++ if self.fs_object:
++ return Gluster_DiskFile(path, device, partition, account, container,
++ obj, logger, keep_data_fp,
++ disk_chunk_size, fs_object = self.fs_object);
++ else:
++ return DiskFile(path, device, partition, account, container,
++ obj, logger, keep_data_fp, disk_chunk_size)
+
+ def async_update(self, op, account, container, obj, host, partition,
+ contdevice, headers_out, objdevice):
+@@ -493,7 +516,7 @@ class ObjectController(object):
+ content_type='text/plain')
+ if self.mount_check and not check_mount(self.devices, device):
+ return Response(status='507 %s is not mounted' % device)
+- file = DiskFile(self.devices, device, partition, account, container,
++ file = self.get_DiskFile_obj(self.devices, device, partition, account, container,
+ obj, self.logger, disk_chunk_size=self.disk_chunk_size)
+
+ if 'X-Delete-At' in file.metadata and \
+@@ -548,7 +571,7 @@ class ObjectController(object):
+ if new_delete_at and new_delete_at < time.time():
+ return HTTPBadRequest(body='X-Delete-At in past', request=request,
+ content_type='text/plain')
+- file = DiskFile(self.devices, device, partition, account, container,
++ file = self.get_DiskFile_obj(self.devices, device, partition, account, container,
+ obj, self.logger, disk_chunk_size=self.disk_chunk_size)
+ orig_timestamp = file.metadata.get('X-Timestamp')
+ upload_expiration = time.time() + self.max_upload_time
+@@ -580,12 +603,29 @@ class ObjectController(object):
+ if 'etag' in request.headers and \
+ request.headers['etag'].lower() != etag:
+ return HTTPUnprocessableEntity(request=request)
+- metadata = {
+- 'X-Timestamp': request.headers['x-timestamp'],
+- 'Content-Type': request.headers['content-type'],
+- 'ETag': etag,
+- 'Content-Length': str(os.fstat(fd).st_size),
+- }
++ content_type = request.headers['content-type']
++ if self.fs_object and not content_type:
++ content_type = FILE_TYPE
++ if not self.fs_object:
++ metadata = {
++ 'X-Timestamp': request.headers['x-timestamp'],
++ 'Content-Type': request.headers['content-type'],
++ 'ETag': etag,
++ 'Content-Length': str(os.fstat(fd).st_size),
++ }
++ else:
++ metadata = {
++ 'X-Timestamp': request.headers['x-timestamp'],
++ 'Content-Type': request.headers['content-type'],
++ 'ETag': etag,
++ 'Content-Length': str(os.fstat(fd).st_size),
++ X_TYPE: OBJECT,
++ X_OBJECT_TYPE: FILE,
++ }
++
++ if self.fs_object and \
++ request.headers['content-type'].lower() == DIR_TYPE:
++ metadata.update({X_OBJECT_TYPE: MARKER_DIR})
+ metadata.update(val for val in request.headers.iteritems()
+ if val[0].lower().startswith('x-object-meta-') and
+ len(val[0]) > 14)
+@@ -612,7 +652,7 @@ class ObjectController(object):
+ 'x-timestamp': file.metadata['X-Timestamp'],
+ 'x-etag': file.metadata['ETag'],
+ 'x-trans-id': request.headers.get('x-trans-id', '-')},
+- device)
++ (self.fs_object and account) or device)
+ resp = HTTPCreated(request=request, etag=etag)
+ return resp
+
+@@ -626,9 +666,9 @@ class ObjectController(object):
+ content_type='text/plain')
+ if self.mount_check and not check_mount(self.devices, device):
+ return Response(status='507 %s is not mounted' % device)
+- file = DiskFile(self.devices, device, partition, account, container,
+- obj, self.logger, keep_data_fp=True,
+- disk_chunk_size=self.disk_chunk_size)
++ file = self.get_DiskFile_obj(self.devices, device, partition, account, container,
++ obj, self.logger, keep_data_fp=True,
++ disk_chunk_size=self.disk_chunk_size)
+ if file.is_deleted() or ('X-Delete-At' in file.metadata and
+ int(file.metadata['X-Delete-At']) <= time.time()):
+ if request.headers.get('if-match') == '*':
+@@ -702,7 +742,7 @@ class ObjectController(object):
+ return resp
+ if self.mount_check and not check_mount(self.devices, device):
+ return Response(status='507 %s is not mounted' % device)
+- file = DiskFile(self.devices, device, partition, account, container,
++ file = self.get_DiskFile_obj(self.devices, device, partition, account, container,
+ obj, self.logger, disk_chunk_size=self.disk_chunk_size)
+ if file.is_deleted() or ('X-Delete-At' in file.metadata and
+ int(file.metadata['X-Delete-At']) <= time.time()):
+@@ -744,7 +784,7 @@ class ObjectController(object):
+ if self.mount_check and not check_mount(self.devices, device):
+ return Response(status='507 %s is not mounted' % device)
+ response_class = HTTPNoContent
+- file = DiskFile(self.devices, device, partition, account, container,
++ file = self.get_DiskFile_obj(self.devices, device, partition, account, container,
+ obj, self.logger, disk_chunk_size=self.disk_chunk_size)
+ if 'x-if-delete-at' in request.headers and \
+ int(request.headers['x-if-delete-at']) != \
+@@ -797,9 +837,18 @@ class ObjectController(object):
+ raise hashes
+ return Response(body=pickle.dumps(hashes))
+
++ def plugin(self, env):
++ if env.get('Gluster_enabled', False):
++ self.fs_object = env.get('fs_object')
++ self.devices = env.get('root')
++ self.mount_check = False
++ else:
++ self.fs_object = None
++
+ def __call__(self, env, start_response):
+ """WSGI Application entry point for the Swift Object Server."""
+ start_time = time.time()
++ self.plugin(env)
+ req = Request(env)
+ self.logger.txn_id = req.headers.get('x-trans-id', None)
+ if not check_utf8(req.path_info):
+diff --git a/swift/proxy/server.py b/swift/proxy/server.py
+index 17613b8..d277d28 100644
+--- a/swift/proxy/server.py
++++ b/swift/proxy/server.py
+@@ -1,4 +1,5 @@
+ # Copyright (c) 2010-2012 OpenStack, LLC.
++# Copyright (c) 2011 Red Hat, Inc.
+ #
+ # Licensed under the Apache License, Version 2.0 (the "License");
+ # you may not use this file except in compliance with the License.
+@@ -53,11 +54,20 @@ from webob import Request, Response
+
+ from swift.common.ring import Ring
+ from swift.common.utils import cache_from_env, ContextPool, get_logger, \
+- get_remote_client, normalize_timestamp, split_path, TRUE_VALUES
++ get_remote_client, normalize_timestamp, split_path, TRUE_VALUES, \
++ plugin_enabled
+ from swift.common.bufferedhttp import http_connect
+-from swift.common.constraints import check_metadata, check_object_creation, \
+- check_utf8, CONTAINER_LISTING_LIMIT, MAX_ACCOUNT_NAME_LENGTH, \
+- MAX_CONTAINER_NAME_LENGTH, MAX_FILE_SIZE
++
++if plugin_enabled():
++ from swift.plugins.constraints import check_object_creation, \
++ MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH, MAX_FILE_SIZE
++else:
++ from swift.common.constraints import check_object_creation, \
++ MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH, MAX_FILE_SIZE
++
++from swift.common.constraints import check_metadata, check_utf8, \
++ CONTAINER_LISTING_LIMIT
++
+ from swift.common.exceptions import ChunkReadTimeout, \
+ ChunkWriteTimeout, ConnectionTimeout
+
+diff --git a/test/__init__.py b/test/__init__.py
+index ef2ce31..363a051 100644
+--- a/test/__init__.py
++++ b/test/__init__.py
+@@ -6,8 +6,16 @@ import sys
+ import os
+ from ConfigParser import MissingSectionHeaderError
+ from StringIO import StringIO
+-
+ from swift.common.utils import readconf
++from swift.common.utils import plugin_enabled
++if plugin_enabled():
++ from swift.plugins.constraints import MAX_OBJECT_NAME_LENGTH, \
++ MAX_CONTAINER_NAME_LENGTH, MAX_ACCOUNT_NAME_LENGTH, \
++ MAX_FILE_SIZE
++else:
++ from swift.common.constraints import MAX_OBJECT_NAME_LENGTH, \
++ MAX_CONTAINER_NAME_LENGTH, MAX_ACCOUNT_NAME_LENGTH, \
++ MAX_FILE_SIZE
+
+ setattr(__builtin__, '_', lambda x: x)
+
+diff --git a/test/functional/tests.py b/test/functional/tests.py
+index b25b4fd..8d12f58 100644
+--- a/test/functional/tests.py
++++ b/test/functional/tests.py
+@@ -31,6 +31,16 @@ import urllib
+ from test import get_config
+ from swift import Account, AuthenticationFailed, Connection, Container, \
+ File, ResponseError
++from test import plugin_enabled
++if plugin_enabled():
++ from test import MAX_OBJECT_NAME_LENGTH, \
++ MAX_CONTAINER_NAME_LENGTH, MAX_ACCOUNT_NAME_LENGTH, \
++ MAX_FILE_SIZE
++else:
++ from test import MAX_OBJECT_NAME_LENGTH, \
++ MAX_CONTAINER_NAME_LENGTH, MAX_ACCOUNT_NAME_LENGTH, \
++ MAX_FILE_SIZE
++
+
+ config = get_config()
+
+@@ -361,7 +371,7 @@ class TestContainer(Base):
+ set_up = False
+
+ def testContainerNameLimit(self):
+- limit = 256
++ limit = MAX_CONTAINER_NAME_LENGTH
+
+ for l in (limit-100, limit-10, limit-1, limit,
+ limit+1, limit+10, limit+100):
+@@ -949,7 +959,7 @@ class TestFile(Base):
+ self.assert_status(404)
+
+ def testNameLimit(self):
+- limit = 1024
++ limit = MAX_OBJECT_NAME_LENGTH
+
+ for l in (1, 10, limit/2, limit-1, limit, limit+1, limit*2):
+ file = self.env.container.file('a'*l)
+@@ -1093,7 +1103,7 @@ class TestFile(Base):
+ self.assert_(file.read(hdrs={'Range': r}) == data[0:1000])
+
+ def testFileSizeLimit(self):
+- limit = 5*2**30 + 2
++ limit = MAX_FILE_SIZE
+ tsecs = 3
+
+ for i in (limit-100, limit-10, limit-1, limit, limit+1, limit+10,
+diff --git a/test/unit/obj/test_server.py b/test/unit/obj/test_server.py
+index 075700e..5b6f32d 100644
+--- a/test/unit/obj/test_server.py
++++ b/test/unit/obj/test_server.py
+@@ -1355,7 +1355,7 @@ class TestObjectController(unittest.TestCase):
+
+ def test_max_object_name_length(self):
+ timestamp = normalize_timestamp(time())
+- req = Request.blank('/sda1/p/a/c/' + ('1' * 1024),
++ req = Request.blank('/sda1/p/a/c/' + ('1' * MAX_OBJECT_NAME_LENGTH),
+ environ={'REQUEST_METHOD': 'PUT'},
+ headers={'X-Timestamp': timestamp,
+ 'Content-Length': '4',
+diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py
+index 364370e..c17fe59 100644
+--- a/test/unit/proxy/test_server.py
++++ b/test/unit/proxy/test_server.py
+@@ -21,7 +21,6 @@ import os
+ import sys
+ import unittest
+ from nose import SkipTest
+-from ConfigParser import ConfigParser
+ from contextlib import contextmanager
+ from cStringIO import StringIO
+ from gzip import GzipFile
+@@ -44,8 +43,18 @@ from swift.account import server as account_server
+ from swift.container import server as container_server
+ from swift.obj import server as object_server
+ from swift.common import ring
+-from swift.common.constraints import MAX_META_NAME_LENGTH, \
+- MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, MAX_FILE_SIZE
++from swift.common.utils import plugin_enabled
++if plugin_enabled():
++ from swift.plugins.constraints import MAX_META_NAME_LENGTH, \
++ MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \
++ MAX_FILE_SIZE, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH, \
++ MAX_OBJECT_NAME_LENGTH
++else:
++ from swift.plugins.constraints import MAX_META_NAME_LENGTH, \
++ MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \
++ MAX_FILE_SIZE, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH, \
++ MAX_OBJECT_NAME_LENGTH
++
+ from swift.common.utils import mkdirs, normalize_timestamp, NullLogger
+ from swift.common.wsgi import monkey_patch_mimetools
+
+@@ -3207,7 +3216,8 @@ class TestContainerController(unittest.TestCase):
+ def test_PUT_max_container_name_length(self):
+ with save_globals():
+ controller = proxy_server.ContainerController(self.app, 'account',
+- '1' * 256)
++ '1' *
++ MAX_CONTAINER_NAME_LENGTH,)
+ self.assert_status_map(controller.PUT,
+ (200, 200, 200, 201, 201, 201), 201,
+ missing_container=True)
+@@ -3813,7 +3823,8 @@ class TestAccountController(unittest.TestCase):
+ def test_PUT_max_account_name_length(self):
+ with save_globals():
+ self.app.allow_account_management = True
+- controller = proxy_server.AccountController(self.app, '1' * 256)
++ controller = proxy_server.AccountController(self.app, '1' *
++ MAX_ACCOUNT_NAME_LENGTH)
+ self.assert_status_map(controller.PUT, (201, 201, 201), 201)
+ controller = proxy_server.AccountController(self.app, '2' * 257)
+ self.assert_status_map(controller.PUT, (201, 201, 201), 400)
More information about the scm-commits
mailing list