[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