blob: 5670d6afa96f858d437f26885e862712bbf72b71 [file] [log] [blame]
#!/bin/bash
# Determine the Hadoop distribution to use.
if test -z "${1}"; then
distribution="0.20.205.0"
url="http://archive.apache.org/dist/hadoop/core/hadoop-0.20.205.0"
elif test "${1}" = "0.20.2-cdh3u3"; then
distribution="0.20.2-cdh3u3"
url="http://archive.cloudera.com/cdh/3"
fi
hadoop="hadoop-${distribution}"
# The potentially running JobTracker, that we need to kill.
jobtracker_pid=
# Trap Ctrl-C (signal 2).
trap 'test ! -z ${jobtracker_pid} && kill ${jobtracker_pid}; echo; exit 1' 2
# Utility function for failing the tutorial with a helpful message.
function fail() {
cat <<__EOF__
${RED}Oh no! We failed to run '${1}'. If you need help try emailing:
mesos-dev@incubator.apache.org
(Remember to include as much debug information as possible.)${NORMAL}
__EOF__
exit 1
}
# Make sure we start out in the right directory.
cd `dirname ${0}`
# Include wonderful colors for our tutorial!
test -f ../support/colors.sh && . ../support/colors.sh
# Make sure we have all the necessary files/directories we need.
resources="TUTORIAL.sh \
hadoop-gridmix.patch \
hadoop-7698-1.patch \
${hadoop}_hadoop-env.sh.patch \
${hadoop}_mesos.patch \
mapred-site.xml.patch \
mesos \
mesos-executor"
for resource in `echo ${resources}`; do
if test ! -e ${resource}; then
cat <<__EOF__
${RED}We seem to be missing ${resource} from the directory containing
this tutorial and we can't continue without it. If you haven't
made any modifications to this directory, please report this to:
mesos-dev@incubator.apache.org
(Remember to include as much debug information as possible.)${NORMAL}
__EOF__
exit 1
fi
done
# Start the tutorial!
cat <<__EOF__
Welcome to the tutorial on running Apache Hadoop on top of Mesos!
During this ${BRIGHT}interactive${NORMAL} guide we'll ask some yes/no
questions and you should enter your answer via 'Y' or 'y' for yes and
'N' or 'n' for no.
Let's begin!
__EOF__
# Check for JAVA_HOME.
if test -z ${JAVA_HOME}; then
cat <<__EOF__
${RED}You probably need to set JAVA_HOME in order to run this tutorial!${NORMAL}
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
fi
# Download Hadoop.
if test ! -e ${hadoop}.tar.gz; then
cat <<__EOF__
We'll try and grab ${hadoop} for you now via:
$ wget ${url}/${hadoop}.tar.gz
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
wget ${url}/${hadoop}.tar.gz || fail "wget ${url}/${hadoop}.tar.gz"
else
cat <<__EOF__
${RED}It looks like you've already downloaded ${hadoop}.tar.gz, so
we'll skip that step.${NORMAL}
__EOF__
fi
# Extract the archive.
if test ! -d ${hadoop}; then
cat <<__EOF__
Let's start by extracting ${hadoop}.tar.gz:
$ tar zxvf ${hadoop}.tar.gz
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
tar zxvf ${hadoop}.tar.gz || fail "tar zxvf ${hadoop}.tar.gz"
else
cat <<__EOF__
${RED}It looks like you've already extracted ${hadoop}.tar.gz, so
we'll skip that step.${NORMAL}
__EOF__
fi
# Change into Hadoop directory.
cat <<__EOF__
Okay, now let's change into the ${hadoop} directory in order to apply
some patches, copy in the Mesos specific code, and build everything.
$ cd ${hadoop}
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
cd ${hadoop} || fail "cd ${hadoop}"
# Apply the GridMix patch.
cat <<__EOF__
To run Hadoop on Mesos under Java 7 we need to apply a rather minor patch
to GridMix, a contribution in Hadoop. See 'NOTES' file for more info.
We'll apply the patch with:
$ patch -p1 <../hadoop-gridmix.patch
__EOF__
# Check and see if the patch has already been applied.
grep 'private String getEnumValues' \
src/contrib/gridmix/src/java/org/apache/hadoop/mapred/gridmix/Gridmix.java \
>/dev/null
if test ${?} == "0"; then
cat <<__EOF__
${RED}It looks like you've already applied the patch, so we'll skip
applying it now.${NORMAL}
__EOF__
else
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
patch -p1 <../hadoop-gridmix.patch || \
fail "patch -p1 <../hadoop-gridmix.patch"
fi
# Apply the 'jsvc' patch for hadoop-0.20.205.0.
if test ${distribution} = "0.20.205.0"; then
cat <<__EOF__
To build Mesos executor bundle, we need to apply a patch for
'jsvc' target that is broken in build.xml. We apply the patch with:
$ patch -p1 <../hadoop-7698-1.patch
__EOF__
# Check and see if the patch has already been applied.
grep 'os-name' build.xml >/dev/null
if test ${?} == "0"; then
cat <<__EOF__
${RED}It looks like you've already applied the patch, so we'll skip
applying it now.${NORMAL}
__EOF__
else
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
patch -p1 <../hadoop-7698-1.patch || \
fail "patch -p1 <../hadoop-7698-1.patch"
fi
fi
# Copy over the Mesos contrib component (and mesos-executor) and apply
# the patch to build the contrib.
cat <<__EOF__
Now we'll copy over the Mesos contrib components. In addition, we'll
need to edit ivy/libraries.properties and src/contrib/build.xml to
hook the Mesos contrib componenet into the build. We've included a
patch to do that for you:
$ cp -r ../mesos src/contrib
$ cp -p ../mesos-executor bin
$ patch -p1 <../${hadoop}_mesos.patch
__EOF__
cp -r ../mesos src/contrib || fail "cp -r ../mesos src/contrib"
cp -p ../mesos-executor bin || fail "cp -p ../mesos-executor bin"
# Check and see if the patch has already been applied.
grep mesos src/contrib/build.xml >/dev/null
if test ${?} == "0"; then
cat <<__EOF__
${RED}It looks like you've already applied the patch, so we'll skip
applying it now.${NORMAL}
__EOF__
else
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
patch -p1 <../${hadoop}_mesos.patch || \
fail "patch -p1 <../${hadoop}_mesos.patch"
fi
# Determine MESOS_BUILD_DIR.
cat <<__EOF__
Okay, now we're ready to build and then run Hadoop! There are a couple
important considerations. First, we need to locate the Mesos JAR and
native library (i.e., libmesos.so on Linux and libmesos.dylib on Mac
OS X). The Mesos JAR is used for both building and running, while the
native library is only used for running. In addition, we need to
locate the Protobuf JAR (if you don't already have one one your
default classpath).
This tutorial assumes you've built Mesos already. We'll use the
environment variable MESOS_BUILD_DIR to denote this directory.
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
MESOS_BUILD_DIR=`cd ../../ && pwd`
while test ! -f `echo ${MESOS_BUILD_DIR}/src/mesos-*.jar`; do
cat <<__EOF__
${RED}We couldn't automagically determine MESOS_BUILD_DIR. It doesn't
look like you used ${MESOS_BUILD_DIR} to build Mesos. Maybe you need
to go back and run 'make' in that directory before
continuing?${NORMAL}
__EOF__
DEFAULT=${MESOS_BUILD_DIR}
read -e -p "${BRIGHT}Where is the build directory?${NORMAL} [${DEFAULT}] "
echo
test -z ${REPLY} && REPLY=${DEFAULT}
MESOS_BUILD_DIR=`cd ${REPLY} && pwd`
done
cat <<__EOF__
Using ${BRIGHT}${MESOS_BUILD_DIR}${NORMAL} as the build directory.
__EOF__
LIBRARY=${MESOS_BUILD_DIR}/src/.libs/libmesos.so
if test ! -f ${LIBRARY}; then
LIBRARY=${MESOS_BUILD_DIR}/src/.libs/libmesos.dylib
fi
if test ! -f ${LIBRARY}; then
cat <<__EOF__
${RED}We seem to be having trouble locating the native library (it's
not at ${MESOS_BUILD_DIR}/src/.libs/libmesos.so or
${MESOS_BUILD_DIR}/src/.libs/libmesos.dylib).
Have you already built Mesos? If you have, please report this to:
mesos-dev@incubator.apache.org
(Remember to include as much debug information as possible.)${NORMAL}
__EOF__
exit 1
fi
# Determine the "platform name" to copy the native library.
cat <<__EOF__ >PlatformName.java
public class PlatformName {
public static void main(String[] args) {
System.out.println(System.getProperty("os.name") + "-" +
System.getProperty("os.arch") + "-" +
System.getProperty("sun.arch.data.model"));
System.exit(0);
}
}
__EOF__
${JAVA_HOME}/bin/javac PlatformName.java || \
fail "${JAVA_HOME}/bin/javac PlatformName.java"
PLATFORM=`${JAVA_HOME}/bin/java -Xmx32m PlatformName | sed -e "s/ /_/g"`
rm PlatformName.*
# Copy over libraries.
MESOS_JAR=`echo ${MESOS_BUILD_DIR}/src/mesos-*.jar`
PROTOBUF_JAR=`echo ${MESOS_BUILD_DIR}/protobuf-*.jar`
cat <<__EOF__
Now we'll copy over the necessary libraries we need from the build
directory.
$ cp ${PROTOBUF_JAR} lib
$ cp ${MESOS_JAR} lib
$ mkdir -p lib/native/${PLATFORM}
$ cp ${LIBRARY} lib/native/${PLATFORM}
__EOF__
cp ${PROTOBUF_JAR} lib || fail "cp ${PROTOBUF_JAR} lib"
cp ${MESOS_JAR} lib || fail "cp ${MESOS_JAR} lib"
mkdir -p lib/native/${PLATFORM} || fail "mkdir -p lib/native/${PLATFORM}"
cp ${LIBRARY} lib/native/${PLATFORM} || \
fail "cp ${LIBRARY} lib/native/${PLATFORM}"
if test ${distribution} = "0.20.205.0"; then
cat <<__EOF__
The Apache distribution requires that we also copy some libraries to
multiple places. :/
$ cp ${PROTOBUF_JAR} share/hadoop/lib
$ cp ${MESOS_JAR} share/hadoop/lib
$ cp ${LIBRARY} lib
__EOF__
cp ${PROTOBUF_JAR} share/hadoop/lib || \
fail "cp ${PROTOBUF_JAR} share/hadoop/lib"
cp ${MESOS_JAR} share/hadoop/lib || \
fail "cp ${MESOS_JAR} share/hadoop/lib"
cp ${LIBRARY} lib || fail "cp ${LIBRARY} lib"
fi
# Build with ant.
cat <<__EOF__
Okay, let's try building Hadoop and the Mesos contrib classes:
$ ant
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
ant || fail "ant"
# Apply conf/mapred-site.xml patch.
cat <<__EOF__
${GREEN}Build success!${NORMAL} Now let's run something!
First we need to configure Hadoop appropriately by modifying
conf/mapred-site.xml (as is always required when running Hadoop).
In order to run Hadoop on Mesos we need to set at least these four properties:
mapred.job.tracker
mapred.jobtracker.taskScheduler
mapred.mesos.master
mapred.mesos.executor
The 'mapred.job.tracker' property should be set to the host:port where
you want to launch the JobTracker (e.g., localhost:54321).
The 'mapred.jobtracker.taskScheduler' property must be set to
'org.apache.hadoop.mapred.MesosScheduler'.
If you've alredy got a Mesos master running you can use that for
'mapred.mesos.master', but for this tutorial well just use 'local' in
order to bring up a Mesos "cluster" within the process. To connect to
a remote master simply use the URL used to connect the slave to the
master (e.g., localhost:5050).
The 'mapred.mesos.executor' property must be set to the location
of Mesos executor bundle so that Mesos slaves can download
and run the executor.
NOTE: You need to MANUALLY upload the Mesos executor bundle to
the above location.
We've got a prepared patch for conf/mapred-site.xml that makes the
changes necessary to get everything running with a local Mesos cluster.
We can apply that patch like so:
$ patch -p1 <../mapred-site.xml.patch
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
patch --dry-run --silent --force -p1 \
<../mapred-site.xml.patch 1>/dev/null 2>&1
if test ${?} == "1"; then
cat <<__EOF__
${RED}It looks like conf/mapred-site.xml has been modified. You'll
need to copy that to something else and restore the file to it's
original contents before we'll be able to apply this patch.${NORMAL}
__EOF__
DEFAULT="N"
else
DEFAULT="Y"
fi
read -e -p "${BRIGHT}Patch conf/mapred-site.xml?${NORMAL} [${DEFAULT}] "
echo
test -z ${REPLY} && REPLY=${DEFAULT}
if test ${REPLY} == "Y" -o ${REPLY} == "y"; then
patch -p1 <../mapred-site.xml.patch || \
fail "patch -p1 <../mapred-site.xml.patch"
fi
# Apply conf/hadoop-env.sh patch.
cat <<__EOF__
Most users will need to set JAVA_HOME in conf/hadoop-env.sh, but we'll
also need to set MESOS_NATIVE_LIBRARY and update the HADOOP_CLASSPATH
to include the Mesos contrib classfiles. We've prepared a patch for
conf/hadoop-env.sh that makes the necessary changes. We can apply that
patch like so:
$ patch -p1 <../${hadoop}_hadoop-env.sh.patch
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
patch --dry-run --silent --force -p1 \
<../${hadoop}_hadoop-env.sh.patch 1>/dev/null 2>&1
if test ${?} == "1"; then
cat <<__EOF__
${RED}It looks like conf/hadoop-env.sh has been modified. You'll need
to copy that to something else and restore the file to it's original
contents before we'll be able to apply this patch.${NORMAL}
__EOF__
DEFAULT="N"
else
DEFAULT="Y"
fi
read -e -p "${BRIGHT}Patch conf/hadoop-env.sh?${NORMAL} [${DEFAULT}] "
echo
test -z ${REPLY} && REPLY=${DEFAULT}
if test ${REPLY} == "Y" -o ${REPLY} == "y"; then
patch -p1 <../${hadoop}_hadoop-env.sh.patch || \
fail "patch -p1 <../${hadoop}_hadoop-env.sh.patch"
fi
# Build Mesos executor package that Mesos slaves can download and execute.
# TODO(vinod): Create a new ant target in build.xml that does this for us.
# NOTE: We specifically set the version when calling ant, to ensure we know
# the resulting directory name.
cat <<__EOF__
Okay, let's try building Mesos executor package:
$ ant -Dversion=${distribution} bin-package
$ cd build/${hadoop}
$ cp ${LIBRARY} lib/native/${PLATFORM}
$ rm -rf cloudera # Only for cdh3
$ cd ..
$ mv ${hadoop} hadoop
$ tar -cjf hadoop.tar.gz hadoop
$ cd ..
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
ant -Dversion=${distribution} bin-package || \
fail "ant -Dversion=${distribution} bin-package"
cd build/${hadoop} || fail "cd build/${hadoop}"
# Copy the Mesos native library.
mkdir -p lib/native/${PLATFORM} || fail "mkdir -p lib/native/${PLATFORM}"
cp ${LIBRARY} lib/native/${PLATFORM} || \
fail "cp ${LIBRARY} lib/native/${PLATFORM}"
# Delete cloudera patches (only present in cdh3 versions of Hadoop)
# to save space (62MB).
rm -rf cloudera || fail "rm -rf cloudera"
cd .. || fail "cd .."
# We re-name the directory to 'hadoop' so that the Mesos executor
# can be agnostic to the Hadoop version.
mv ${hadoop} hadoop || fail "mv ${hadoop} hadoop"
# Create the bundle.
tar -cjf hadoop.tar.gz hadoop || fail "tar -cjf hadoop.tar.gz hadoop"
cd .. || fail "cd.."
# Start JobTracker.
cat <<__EOF__
Let's go ahead and try and start the JobTracker via:
$ ./bin/hadoop jobtracker
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
# Fake the resources for this local slave, because the default resources
# (esp. memory on MacOSX) offered by the slave might not be enough to
# launch TaskTrackers.
export MESOS_RESOURCES="cpus:16;mem:16384;disk:307200;ports:[31000-32000]"
./bin/hadoop jobtracker 1>/dev/null 2>&1 &
jobtracker_pid=${!}
cat <<__EOF__
JobTracker started at ${BRIGHT}${jobtracker_pid}${NORMAL}.
__EOF__
echo -n "Waiting 5 seconds for it to start."
for i in 1 2 3 4 5; do sleep 1 && echo -n " ."; done
# Now let's run an example.
cat <<__EOF__
Alright, now let's run the "wordcount" example via:
$ ./bin/hadoop jar hadoop-examples-${distribution}.jar wordcount \
src/contrib/mesos/src/java/org/apache/hadoop/mapred out
__EOF__
read -e -p "${BRIGHT}Hit enter to continue.${NORMAL} "
echo
rm -rf out # TODO(benh): Ask about removing this first.
./bin/hadoop jar hadoop-examples-${distribution}.jar wordcount \
src/contrib/mesos/src/java/org/apache/hadoop/mapred out
if test ${?} == "0"; then
cat <<__EOF__
${GREEN}Success!${NORMAL} We'll kill the JobTracker and exit.
Summary:
$ wget ${url}/${hadoop}.tar.gz
$ tar zxvf ${hadoop}.tar.gz
$ cd ${hadoop}
$ patch -p1 <../${hadoop}.patch
$ cp -r ../mesos src/contrib
$ cp -p ../mesos-executor bin
$ patch -p1 <../${hadoop}_mesos.patch
$ cp ${PROTOBUF_JAR} lib
$ cp ${MESOS_JAR} lib
$ mkdir -p lib/native/${PLATFORM}
$ cp ${LIBRARY} lib/native/${PLATFORM}
__EOF__
if test ${distribution} = "0.20.205.0"; then
cat <<__EOF__
$ cp ${PROTOBUF_JAR} share/hadoop/lib
$ cp ${MESOS_JAR} share/hadoop/lib
$ cp ${LIBRARY} lib
__EOF__
fi
cat <<__EOF__
$ ant
$ patch -p1 <../mapred-site.xml.patch
$ patch -p1 <../${hadoop}_hadoop-env.sh.patch
$ ant -Dversion=${distribution} bin-package
$ cd build/${hadoop}
$ cp ${LIBRARY} lib/native/${PLATFORM}
$ rm -rf cloudera
$ cd ..
$ mv ${hadoop} hadoop
$ tar -cjf hadoop.tar.gz hadoop
$ cd ..
Remember you'll need to make some changes to
${hadoop}/conf/mapred-site.xml to run Hadoop on a
real Mesos cluster:
We hope you found this was helpful!
__EOF__
kill ${jobtracker_pid}
else
cat <<__EOF__
${RED}Oh no, it failed! Try running the JobTracker and wordcount
example manually ... it might be an issue with your environment that
this tutorial didn't cover (if you find this to be the case, please
create a JIRA for us and/or send us a code review).${NORMAL}
__EOF__
kill ${jobtracker_pid}
exit 1
fi