diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82a535e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/r3.6.3.tar.gz diff --git a/.rh-mongodb36-mongodb.metadata b/.rh-mongodb36-mongodb.metadata new file mode 100644 index 0000000..7403a6f --- /dev/null +++ b/.rh-mongodb36-mongodb.metadata @@ -0,0 +1 @@ +ab89cb884f752e664b810df9fe1d99c5bb096e2e SOURCES/r3.6.3.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 98f42b4..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/README b/SOURCES/README new file mode 100644 index 0000000..6ad77fc --- /dev/null +++ b/SOURCES/README @@ -0,0 +1,57 @@ +This directory contains a test suite for the mongoDB daemon. To run the +core JavaScripts tests, execute "./resmoke.py --suites core" in this +directory. + +For use in Red Hat distributions, you should run the script as user +mongodb, who is created with nologin shell however, so the best bet is +something like: + $ su - + # cd /usr/share/mongodb-test + # su -s /bin/bash mongodb -c "./resmoke.py --suites core" + +This will use the installed mongodb executables, but will run a private +copy of the server process (using data files within +/usr/share/mongodb-test/var/), so you need not start the mongod service +beforehand. + +To clean up afterwards, remove the created "var/*" subdirectories, eg + # su -s /bin/bash - mongodb -c "rm -rf /usr/share/mongodb-test/var/*" + +If one or more tests fail on your system, please read the following +manual section for instructions on how to report the problem: + +http://www.mongodb.org/about/contributors/tutorial/submit-bug-reports/ + +MongoDB offers several test suites. To get list of provided test suites +run "./resmoke.py -l". + +If you want to run a specific test, simply add path to JavaSctipt file +from /usr/share/mongodb-test/jstests/ you want to run to the option to +resmoke.py. It is also possible to specify more files. For example to +run jstests/disk/*.js files execute "./resmoke.py jstests/disk/*.js" + +If you want to use some specific storage engine for mongod server you +have to specify --storageEngine option. Actualy there are two stable +storage engines: mmapv1 and wiredTiger (x86_64 only). + +For more options run "./resmoke.py --help". + + +In Red Hat distributions use this syntax: + $ su - + # cd /usr/share/mongodb-test + # su -s /bin/bash mongodb -c "./resmoke.py OPTIONS" + +More info about mongoDB testing: +http://www.mongodb.org/about/contributors/tutorial/test-the-mongodb-server/ + + + +Notes: + +- ARM architecture is not fully supported - + https://jira.mongodb.org/browse/SERVER-1811 + +- This subpackage does not contain dbtest binary (it is going to be + deprecated). + diff --git a/SOURCES/daemon-scl-helper.sh b/SOURCES/daemon-scl-helper.sh new file mode 100644 index 0000000..da8a3f3 --- /dev/null +++ b/SOURCES/daemon-scl-helper.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# This helper script is necessary for having proper SELinux context of daemon +# process run in SCL environment via systemd unit file. +# Without this script the process looses SELinux type because /usr/bin/scl +# has context bin_t and unit_t -> bin_t results in unconfined process running. +# If this helper script has the same SELinux context as the original binary, +# the process will have proper SELinux context. +# +# This script was designed to be usable the same as the scl command is used, +# including the collections given as more arguments, separated from binary +# itself by -- separator. +# So it is possible to use the list of collections to be enabled via +# environment file. +# Thus, instead of: +# /usr/bin/scl enable scl1 scl2 -- /path/to/bin arg1 arg2 +# you can use: +# /usr/bin/this-script enable scl1 scl2 -- /path/to/bin arg1 arg2 +# +# Notice: do not forget to set proper SELinux context for this file. +# The context should be the same as the binary running has. + +action="$1" +shift + +while [ -n "$1" ] && [ "$1" != "--" ] ; do + source scl_source "$action" "$1" + shift +done + +if [ $# -le 2 ] ; then + echo "Usage `basename $0` enable sclname [sclname ...] -- /path/to/bin [arg ...]" >&2 + exit 1 +fi + +shift + +exec "$@" + + + diff --git a/SOURCES/mongod.conf b/SOURCES/mongod.conf new file mode 100644 index 0000000..46beac3 --- /dev/null +++ b/SOURCES/mongod.conf @@ -0,0 +1,119 @@ +## +## For list of options visit: +## https://docs.mongodb.org/manual/reference/configuration-options/ +## + +# systemLog Options - How to do logging +systemLog: + # The default log message verbosity level for components (0-5) + verbosity: 0 + + # The destination to which MongoDB sends all log output (file|syslog, if not specifed to STDOUT) + destination: file + + # Log file to send write to instead of stdout - has to be a file, not directory + path: /var/log/mongodb/mongod.log + + # Append to logpath instead of over-writing (false by default) + logAppend: true + + # Set the log rotation behavior (rename|reopen, rename by default) + logRotate: reopen + + +# processManagement Options - How the process runs +processManagement: + # Fork server process (false by default) + fork: true + + # Full path to pidfile (if not set, no pidfile is created) + pidFilePath: /var/run/mongodb/mongod.pid + + +# net Options - Network interfaces settings +net: + # Specify port number (27017 by default) + port: 27017 + + # Comma separated list of ip addresses to listen on (all local ips by default) + bindIp: 127.0.0.1,::1 + + # Enable IPv6 support (disabled by default) + ipv6: true + + unixDomainSocket: + # Enable/disable listening on the UNIX domain socket (true by default) + enabled: true + + # Alternative directory for UNIX domain sockets (defaults to /tmp) + pathPrefix: /var/run/mongodb + + #ssl: + # Set the SSL operation mode (disabled|allowSSL|preferSSL|requireSSL) + #mode: + + # PEM file for ssl + #PEMKeyFile: + + # Certificate Authority file for SSL + #CAFile: + + +# storage Options - How and Where to store data +storage: + # Directory for datafiles (defaults to /data/db/) + dbPath: /var/lib/mongodb + + #journal: + # Enable/Disable journaling (journaling is on by default for 64 bit) + #enabled: true + + # The storage engine for the mongod database (mmapv1|wiredTiger, wiredTiger by default + # - works for 64 bit only) + # Also possible to use unstable engines: devnull|ephemeralForTest + engine: mmapv1 + + #mmapv1: + # Enable or disable the preallocation of data files (true by default) + #preallocDataFiles: + + # Use a smaller default file size (false by default) + #smallFiles: + + #wiredTiger: + #engineConfig: + # The maximum size of the cache that WiredTiger will use for all data + # (max(60% of RAM - 1GB, 1GB) by default) + #cacheSizeGB: 5 + + # The type of compression to use to compress WiredTiger journal data + # (none|snappy|zlib, snappy by default) + #journalCompressor: + + #collectionConfig: + # The default type of compression to use to compress collection data + # (none|snappy|zlib, snappy by default) + #blockCompressor: + + +# secutiry Options - Authorization and other security settings +#security: + # Private key for cluster authentication + #keyFile: + + # Run with/without security (enabled|disabled, disabled by default) + #authorization + + +# setParameter Options - Set MongoDB server parameters +# setParameter: + +# opratrionProfiling Options - Profiling settings +#operationProfiling: + +# replication Options - ReplSet settings +#replication: + +# sharding Options - Shard settings +#sharding: + diff --git a/SOURCES/mongod.init b/SOURCES/mongod.init new file mode 100644 index 0000000..2de7fde --- /dev/null +++ b/SOURCES/mongod.init @@ -0,0 +1,172 @@ +#!/bin/sh +# +# mongod init file for starting up the MongoDB server +# +# chkconfig: - 90 10 +# description: Starts and stops the MongDB daemon that handles all \ +# database requests. + +# Source function library. +. /etc/rc.d/init.d/functions + +prog="mongod" +exec="/usr/bin/$prog" +logfile="/var/log/mongodb/$prog.log" + +[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog + +pidfile=${PIDFILE-/var/run/mongodb/$prog.pid} +options="$MONGODB_OPTIONS $OPTIONS" +lockfile="/var/lock/subsys/$prog" + +# Nicer version of killproc that does not kill mongodb when it takes +# a long time to shut down and does not hang for a long time when mongo +# shuts down quickly +killproc_nice() { + local RC base pid pid_file= delay i + + RC=0; delay=3 + # Test syntax. + if [ "$#" -eq 0 ]; then + echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]" + return 1 + fi + if [ "$1" = "-p" ]; then + pid_file=$2 + shift 2 + fi + if [ "$1" = "-d" ]; then + delay=$2 + shift 2 + fi + + # Save basename. + base=${1##*/} + + # Find pid. + __pids_var_run "$1" "$pid_file" + RC=$? + if [ -z "$pid" ]; then + if [ -z "$pid_file" ]; then + pid="$(__pids_pidof "$1")" + else + [ "$RC" = "4" ] && { failure $"$base shutdown" ; return $RC ;} + fi + fi + + # Kill it. + if [ -n "$pid" ] ; then + [ "$BOOTUP" = "verbose" -a -z "${LSB:-}" ] && echo -n "$base " + if checkpid $pid 2>&1; then + # TERM first, then KILL if not dead + kill -TERM $pid >/dev/null 2>&1 + usleep 100000 + + # Check every one second if the program is stopped. + # Do so for a maximum of $delay seconds + for ((i = 0 ; i < $delay; i++)) + do + if checkpid $pid; then + sleep 1 + else + break + fi + done + + # If the program is not stopped, kill it + if checkpid $pid ; then + kill -KILL $pid >/dev/null 2>&1 + usleep 100000 + fi + fi + checkpid $pid + RC=$? + [ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown" + RC=$((! $RC)) + else + failure $"$base shutdown" + RC=0 + fi + + # Remove pid file if any. + rm -f "${pid_file:-/var/run/$base.pid}" + return $RC +} + +start() { + [ -x $exec ] || exit 5 + [ "$(id -u)" -eq 0 ] || exit 4 + echo -n $"Starting $prog: " + daemon --pidfile=${pidfile} --user mongodb "$exec $options run >> $logfile 2>&1" + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + [ "$(id -u)" -eq 0 ] || exit 4 + echo -n $"Stopping $prog: " + killproc_nice -p ${pidfile} -d 300 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p ${pidfile} $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + +. __SCL_SCRIPTS__/service-environment +. scl_source enable __list of scls__ + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/SOURCES/mongod.service b/SOURCES/mongod.service new file mode 100644 index 0000000..beb9c28 --- /dev/null +++ b/SOURCES/mongod.service @@ -0,0 +1,17 @@ +[Unit] +Description=High-performance, schema-free document-oriented database +After=syslog.target network.target + +[Service] +Type=forking +User=mongodb +PIDFile=/var/run/mongodb/mongod.pid +EnvironmentFile=__SCL_SCRIPTS__/service-environment +EnvironmentFile=/etc/sysconfig/mongod +ExecStart=/bin/sh -c "exec @libexecdir@/mongodb-scl-helper enable __list of scls__ -- $NUMACTL /usr/bin/mongod $OPTIONS run" +PrivateTmp=true +LimitNOFILE=64000 +TimeoutStartSec=180 + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/mongod.sysconf b/SOURCES/mongod.sysconf new file mode 100644 index 0000000..e2e3587 --- /dev/null +++ b/SOURCES/mongod.sysconf @@ -0,0 +1,5 @@ +OPTIONS="-f /etc/mongod.conf" + +# To run numactl before starting mongodb server +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +#NUMACTL="/usr/bin/numactl --interleave=all" diff --git a/SOURCES/mongodb-tmpfile b/SOURCES/mongodb-tmpfile new file mode 100644 index 0000000..634b44e --- /dev/null +++ b/SOURCES/mongodb-tmpfile @@ -0,0 +1,3 @@ +# make sure the mongodb dir is owned by mongodb so the process running as +# mongodb can write the pid there +d /run/mongodb 0755 mongodb root - diff --git a/SOURCES/mongodb.logrotate b/SOURCES/mongodb.logrotate new file mode 100644 index 0000000..8df6558 --- /dev/null +++ b/SOURCES/mongodb.logrotate @@ -0,0 +1,12 @@ +/var/log/mongodb/*.log { + weekly + rotate 10 + copytruncate + delaycompress + compress + notifempty + missingok + postrotate + /bin/kill -USR1 `cat /var/run/mongodb/mongod.pid 2>/dev/null` 2> /dev/null|| true + endscript +} diff --git a/SOURCES/mongos.conf b/SOURCES/mongos.conf new file mode 100644 index 0000000..b460fe8 --- /dev/null +++ b/SOURCES/mongos.conf @@ -0,0 +1,86 @@ +## +## For list of options visit: +## https://docs.mongodb.org/manual/reference/configuration-options/ +## + +# systemLog Options - How to do logging +systemLog: + # The default log message verbosity level for components (0-5) + verbosity: 0 + + # The destination to which MongoDB sends all log output (file|syslog, if not specifed to STDOUT) + destination: file + + # Log file to send write to instead of stdout - has to be a file, not directory + path: /var/log/mongodb/mongod.log + + # Append to logpath instead of over-writing (false by default) + logAppend: true + + # Set the log rotation behavior (rename|reopen, rename by default) + logRotate: reopen + + +# processManagement Options - How the process runs +processManagement: + # Fork server process (false by default) + fork: true + + # Full path to pidfile (if not set, no pidfile is created) + pidFilePath: /var/run/mongodb/mongod.pid + + +# net Options - Network interfaces settings +net: + # Specify port number (27017 by default) + port: 27017 + + # Comma separated list of ip addresses to listen on (all local ips by default) + bindIp: 127.0.0.1,::1 + + # Enable IPv6 support (disabled by default) + ipv6: true + + unixDomainSocket: + # Enable/disable listening on the UNIX domain socket (true by default) + enabled: true + + # Alternative directory for UNIX domain sockets (defaults to /tmp) + pathPrefix: /var/run/mongodb + + #ssl: + # Set the SSL operation mode (disabled|allowSSL|preferSSL|requireSSL) + #mode: + + # PEM file for ssl + #PEMKeyFile: + + # Certificate Authority file for SSL + #CAFile: + + +# secutiry Options - Authorization and other security settings +#security: + # Private key for cluster authentication + #keyFile: + + +# sharding Options - Shard settings +#sharding: + # The configuration servers for the sharded cluster + # Acceptable form: /,,[...] + #configDB: + + +# storage Options - How and Where to store data +#storage: + +# setParameter Options - Set MongoDB server parameters +# setParameter: + +# opratrionProfiling Options - Profiling settings +#operationProfiling: + +# replication Options - ReplSet settings +#replication: + diff --git a/SOURCES/mongos.init b/SOURCES/mongos.init new file mode 100644 index 0000000..ec10e60 --- /dev/null +++ b/SOURCES/mongos.init @@ -0,0 +1,177 @@ +#!/bin/sh +# +# mongos init file for starting up the MongoDB shard server +# +# chkconfig: - 90 10 +# description: Starts and stops the MongoDB shard daemon that handles all \ +# database requests. + +# Source function library. +. /etc/rc.d/init.d/functions + +prog="mongos" +exec="/usr/bin/$prog" +logfile="/var/log/mongodb/$prog.log" + +[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog + +pidfile=${PIDFILE-/var/run/mongodb/$prog.pid} +options="$MONGODB_OPTIONS $OPTIONS" +lockfile="/var/lock/subsys/$prog" + +# Nicer version of killproc that does not kill mongodb when it takes +# a long time to shut down and does not hang for a long time when mongo +# shuts down quickly +killproc_nice() { + local RC base pid pid_file= delay i + + RC=0; delay=3 + # Test syntax. + if [ "$#" -eq 0 ]; then + echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]" + return 1 + fi + if [ "$1" = "-p" ]; then + pid_file=$2 + shift 2 + fi + if [ "$1" = "-d" ]; then + delay=$2 + shift 2 + fi + + # Save basename. + base=${1##*/} + + # Find pid. + __pids_var_run "$1" "$pid_file" + RC=$? + if [ -z "$pid" ]; then + if [ -z "$pid_file" ]; then + pid="$(__pids_pidof "$1")" + else + [ "$RC" = "4" ] && { failure $"$base shutdown" ; return $RC ;} + fi + fi + + # Kill it. + if [ -n "$pid" ] ; then + [ "$BOOTUP" = "verbose" -a -z "${LSB:-}" ] && echo -n "$base " + if checkpid $pid 2>&1; then + # TERM first, then KILL if not dead + kill -TERM $pid >/dev/null 2>&1 + usleep 100000 + + # Check every one second if the program is stopped. + # Do so for a maximum of $delay seconds + for ((i = 0 ; i < $delay; i++)) + do + if checkpid $pid; then + sleep 1 + else + break + fi + done + + # If the program is not stopped, kill it + if checkpid $pid ; then + kill -KILL $pid >/dev/null 2>&1 + usleep 100000 + fi + fi + checkpid $pid + RC=$? + [ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown" + RC=$((! $RC)) + else + failure $"$base shutdown" + RC=0 + fi + + # Remove pid file if any. + rm -f "${pid_file:-/var/run/$base.pid}" + return $RC +} + +start() { + [ -x $exec ] || exit 5 + [ "$(id -u)" -eq 0 ] || exit 4 + printf '%s' $"Starting $prog: " + # why the hell is this not checked in /etc/rc.d/init.d/functions ? + [ "$(id -u)" -eq 0 ] || exit 4 + # FIXME check mongod source - if parent waits after forking for childs + # message about proper initialization + daemon --pidfile="$pidfile" --user mongodb \ + "$exec $options >> $logfile 2>&1" + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + [ "$(id -u)" -eq 0 ] || exit 4 + printf '%s' $"Stopping $prog: " + killproc_nice -p ${pidfile} -d 300 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p ${pidfile} $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + +. __SCL_SCRIPTS__/service-environment +. scl_source enable __list of scls__ + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/SOURCES/mongos.service b/SOURCES/mongos.service new file mode 100644 index 0000000..55cca32 --- /dev/null +++ b/SOURCES/mongos.service @@ -0,0 +1,17 @@ +[Unit] +Description=High-performance, schema-free document-oriented database +After=syslog.target network.target + +[Service] +Type=forking +User=mongodb +PIDFile=/var/run/mongodb/mongos.pid +EnvironmentFile=__SCL_SCRIPTS__/service-environment +EnvironmentFile=/etc/sysconfig/mongos +ExecStart=/bin/sh -c "exec @libexecdir@/mongodb-scl-helper enable __list of scls__ -- $NUMACTL /usr/bin/mongos $OPTIONS" +PrivateTmp=true +LimitNOFILE=64000 +TimeoutStartSec=180 + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/mongos.sysconf b/SOURCES/mongos.sysconf new file mode 100644 index 0000000..8741ddd --- /dev/null +++ b/SOURCES/mongos.sysconf @@ -0,0 +1,5 @@ +OPTIONS="-f /etc/mongos.conf" + +# To run numactl before starting mongodb server +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +#NUMACTL="/usr/bin/numactl --interleave=all" diff --git a/SOURCES/ppc64le-disable-altivec.patch b/SOURCES/ppc64le-disable-altivec.patch new file mode 100644 index 0000000..85f7d5c --- /dev/null +++ b/SOURCES/ppc64le-disable-altivec.patch @@ -0,0 +1,13 @@ +diff --git a/src/mongo/db/fts/unicode/byte_vector.h b/src/mongo/db/fts/unicode/byte_vector.h +index 2404e15dfd..d361a857ff 100644 +--- a/src/mongo/db/fts/unicode/byte_vector.h ++++ b/src/mongo/db/fts/unicode/byte_vector.h +@@ -33,8 +33,6 @@ + // TODO replace this with #if BOOST_HW_SIMD_X86 >= BOOST_HW_SIMD_X86_SSE2_VERSION in boost 1.60 + #if defined(_M_AMD64) || defined(__amd64__) + #include "mongo/db/fts/unicode/byte_vector_sse2.h" +-#elif defined(__powerpc64__) +-#include "mongo/db/fts/unicode/byte_vector_altivec.h" + #else // Other platforms go above here. + #undef MONGO_HAVE_FAST_BYTE_VECTOR + #endif diff --git a/SOURCES/python3-buildscripts-tests.patch b/SOURCES/python3-buildscripts-tests.patch new file mode 100644 index 0000000..3a75241 --- /dev/null +++ b/SOURCES/python3-buildscripts-tests.patch @@ -0,0 +1,1727 @@ +diff --git a/SConstruct b/SConstruct +index f949f65475..78eab698b9 100644 +--- a/SConstruct ++++ b/SConstruct +@@ -383,7 +383,7 @@ win_version_min_choices = { + } + + add_option('win-version-min', +- choices=win_version_min_choices.keys(), ++ choices=list(win_version_min_choices.keys()), + default=None, + help='minimum Windows version to support', + type='choice', +@@ -492,7 +492,7 @@ except ValueError as e: + def variable_shlex_converter(val): + # If the argument is something other than a string, propogate + # it literally. +- if not isinstance(val, basestring): ++ if not isinstance(val, str): + return val + parse_mode = get_option('variable-parse-mode') + if parse_mode == 'auto': +@@ -820,7 +820,7 @@ SConsignFile(str(sconsDataDir.File('sconsign'))) + def printLocalInfo(): + import sys, SCons + print( "scons version: " + SCons.__version__ ) +- print( "python version: " + " ".join( [ `i` for i in sys.version_info ] ) ) ++ print( "python version: " + " ".join( [ str(i) for i in sys.version_info ] ) ) + + printLocalInfo() + +@@ -1930,7 +1930,7 @@ def doConfigure(myenv): + # to make them real errors. + cloned.Append(CCFLAGS=['-Werror']) + conf = Configure(cloned, help=False, custom_tests = { +- 'CheckFlag' : lambda(ctx) : CheckFlagTest(ctx, tool, extension, flag) ++ 'CheckFlag' : lambda ctx : CheckFlagTest(ctx, tool, extension, flag) + }) + available = conf.CheckFlag() + conf.Finish() +@@ -2402,7 +2402,7 @@ def doConfigure(myenv): + "undefined" : myenv.File("#etc/ubsan.blacklist"), + } + +- blackfiles = set([v for (k, v) in blackfiles_map.iteritems() if k in sanitizer_list]) ++ blackfiles = set([v for (k, v) in blackfiles_map.items() if k in sanitizer_list]) + blacklist_options=["-fsanitize-blacklist=%s" % blackfile + for blackfile in blackfiles + if os.stat(blackfile.path).st_size != 0] +diff --git a/buildscripts/clang_format.py b/buildscripts/clang_format.py +index cf9884d8b1..c0f4140e59 100755 +--- a/buildscripts/clang_format.py ++++ b/buildscripts/clang_format.py +@@ -20,7 +20,7 @@ import sys + import tarfile + import tempfile + import threading +-import urllib2 ++import urllib.request, urllib.error, urllib.parse + from distutils import spawn + from optparse import OptionParser + from multiprocessing import cpu_count +@@ -96,11 +96,11 @@ def get_clang_format_from_cache_and_extract(url, tarball_ext): + num_tries = 5 + for attempt in range(num_tries): + try: +- resp = urllib2.urlopen(url) ++ resp = urllib.request.urlopen(url) + with open(temp_tar_file, 'wb') as f: + f.write(resp.read()) + break +- except urllib2.URLError: ++ except urllib.error.URLError: + if attempt == num_tries - 1: + raise + continue +@@ -436,7 +436,7 @@ def reformat_branch(clang_format, commit_prior_to_reformat, commit_after_reforma + + # Check if anything needed reformatting, and if so amend the commit + if not repo.is_working_tree_dirty(): +- print ("Commit %s needed no reformatting" % commit_hash) ++ print("Commit %s needed no reformatting" % commit_hash) + else: + repo.commit(["--all", "--amend", "--no-edit"]) + +diff --git a/buildscripts/cpplint.py b/buildscripts/cpplint.py +index c6aa51b7b9..ed9cdb311e 100755 +--- a/buildscripts/cpplint.py ++++ b/buildscripts/cpplint.py +@@ -835,7 +835,7 @@ class _CppLintState(object): + + def PrintErrorCounts(self): + """Print a summary of errors by category, and the total.""" +- for category, count in self.errors_by_category.iteritems(): ++ for category, count in self.errors_by_category.items(): + sys.stderr.write('Category \'%s\' errors found: %d\n' % + (category, count)) + sys.stderr.write('Total errors found: %d\n' % self.error_count) +@@ -1388,7 +1388,7 @@ def FindEndOfExpressionInLine(line, startpos, stack): + On finding an unclosed expression: (-1, None) + Otherwise: (-1, new stack at end of this line) + """ +- for i in xrange(startpos, len(line)): ++ for i in range(startpos, len(line)): + char = line[i] + if char in '([{': + # Found start of parenthesized expression, push to expression stack +@@ -1687,7 +1687,7 @@ def CheckForCopyright(filename, lines, error): + + # We'll say it should occur by line 10. Don't forget there's a + # dummy line at the front. +- for line in xrange(1, min(len(lines), 11)): ++ for line in range(1, min(len(lines), 11)): + if re.search(r'Copyright', lines[line], re.I): break + else: # means no copyright line was found + error(filename, 0, 'legal/copyright', 5, +@@ -1838,7 +1838,7 @@ def CheckForBadCharacters(filename, lines, error): + error: The function to call with any errors found. + """ + for linenum, line in enumerate(lines): +- if u'\ufffd' in line: ++ if '\ufffd' in line: + error(filename, linenum, 'readability/utf8', 5, + 'Line contains invalid UTF-8 (or Unicode replacement character).') + if '\0' in line: +@@ -2884,7 +2884,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum, + + if starting_func: + body_found = False +- for start_linenum in xrange(linenum, clean_lines.NumLines()): ++ for start_linenum in range(linenum, clean_lines.NumLines()): + start_line = lines[start_linenum] + joined_line += ' ' + start_line.lstrip() + if Search(r'(;|})', start_line): # Declarations and trivial functions +@@ -3361,7 +3361,7 @@ def CheckBracesSpacing(filename, clean_lines, linenum, error): + trailing_text = '' + if endpos > -1: + trailing_text = endline[endpos:] +- for offset in xrange(endlinenum + 1, ++ for offset in range(endlinenum + 1, + min(endlinenum + 3, clean_lines.NumLines() - 1)): + trailing_text += clean_lines.elided[offset] + if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text): +@@ -3530,7 +3530,7 @@ def IsRValueType(clean_lines, nesting_state, linenum, column): + + # Look for the previous 'for(' in the previous lines. + before_text = match_symbol.group(1) +- for i in xrange(start - 1, max(start - 6, 0), -1): ++ for i in range(start - 1, max(start - 6, 0), -1): + before_text = clean_lines.elided[i] + before_text + if Search(r'for\s*\([^{};]*$', before_text): + # This is the condition inside a for-loop +@@ -3657,12 +3657,12 @@ def IsRValueAllowed(clean_lines, linenum): + True if line is within the region where RValue references are allowed. + """ + # Allow region marked by PUSH/POP macros +- for i in xrange(linenum, 0, -1): ++ for i in range(linenum, 0, -1): + line = clean_lines.elided[i] + if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): + if not line.endswith('PUSH'): + return False +- for j in xrange(linenum, clean_lines.NumLines(), 1): ++ for j in range(linenum, clean_lines.NumLines(), 1): + line = clean_lines.elided[j] + if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): + return line.endswith('POP') +@@ -4142,7 +4142,7 @@ def CheckCheck(filename, clean_lines, linenum, error): + expression = lines[linenum][start_pos + 1:end_pos - 1] + else: + expression = lines[linenum][start_pos + 1:] +- for i in xrange(linenum + 1, end_line): ++ for i in range(linenum + 1, end_line): + expression += lines[i] + expression += last_line[0:end_pos - 1] + +@@ -4270,7 +4270,7 @@ def GetLineWidth(line): + The width of the line in column positions, accounting for Unicode + combining characters and wide characters. + """ +- if isinstance(line, unicode): ++ if isinstance(line, str): + width = 0 + for uc in unicodedata.normalize('NFC', line): + if unicodedata.east_asian_width(uc) in ('W', 'F'): +@@ -4623,7 +4623,7 @@ def _GetTextInside(text, start_pattern): + + # Give opening punctuations to get the matching close-punctuations. + matching_punctuation = {'(': ')', '{': '}', '[': ']'} +- closing_punctuation = set(matching_punctuation.itervalues()) ++ closing_punctuation = set(matching_punctuation.values()) + + # Find the position to start extracting text. + match = re.search(start_pattern, text, re.M) +@@ -4949,7 +4949,7 @@ def IsDerivedFunction(clean_lines, linenum): + virt-specifier. + """ + # Scan back a few lines for start of current function +- for i in xrange(linenum, max(-1, linenum - 10), -1): ++ for i in range(linenum, max(-1, linenum - 10), -1): + match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i]) + if match: + # Look for "override" after the matching closing parenthesis +@@ -4970,7 +4970,7 @@ def IsInitializerList(clean_lines, linenum): + True if current line appears to be inside constructor initializer + list, False otherwise. + """ +- for i in xrange(linenum, 1, -1): ++ for i in range(linenum, 1, -1): + line = clean_lines.elided[i] + if i == linenum: + remove_function_body = Match(r'^(.*)\{\s*$', line) +@@ -5066,7 +5066,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum, + # Found the matching < on an earlier line, collect all + # pieces up to current line. + line = '' +- for i in xrange(startline, linenum + 1): ++ for i in range(startline, linenum + 1): + line += clean_lines.elided[i].strip() + + # Check for non-const references in function parameters. A single '&' may +@@ -5090,7 +5090,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum, + # appear inside the second set of parentheses on the current line as + # opposed to the first set. + if linenum > 0: +- for i in xrange(linenum - 1, max(0, linenum - 10), -1): ++ for i in range(linenum - 1, max(0, linenum - 10), -1): + previous_line = clean_lines.elided[i] + if not Search(r'[),]\s*$', previous_line): + break +@@ -5121,7 +5121,7 @@ def CheckForNonConstReference(filename, clean_lines, linenum, + # Don't see a whitelisted function on this line. Actually we + # didn't see any function name on this line, so this is likely a + # multi-line parameter list. Try a bit harder to catch this case. +- for i in xrange(2): ++ for i in range(2): + if (linenum > i and + Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): + return +@@ -5283,7 +5283,7 @@ def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error): + # Try expanding current context to see if we one level of + # parentheses inside a macro. + if linenum > 0: +- for i in xrange(linenum - 1, max(0, linenum - 5), -1): ++ for i in range(linenum - 1, max(0, linenum - 5), -1): + context = clean_lines.elided[i] + context + if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context): + return False +@@ -5540,7 +5540,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, + required = {} # A map of header name to linenumber and the template entity. + # Example of required: { '': (1219, 'less<>') } + +- for linenum in xrange(clean_lines.NumLines()): ++ for linenum in range(clean_lines.NumLines()): + line = clean_lines.elided[linenum] + if not line or line[0] == '#': + continue +@@ -5589,7 +5589,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, + + # include_dict is modified during iteration, so we iterate over a copy of + # the keys. +- header_keys = include_dict.keys() ++ header_keys = list(include_dict.keys()) + for header in header_keys: + (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) + fullpath = common_path + header +@@ -5684,7 +5684,7 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error): + end_col = -1 + end_line = -1 + start_col = len(virtual.group(1)) +- for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())): ++ for start_line in range(linenum, min(linenum + 3, clean_lines.NumLines())): + line = clean_lines.elided[start_line][start_col:] + parameter_list = Match(r'^([^(]*)\(', line) + if parameter_list: +@@ -5699,7 +5699,7 @@ def CheckRedundantVirtual(filename, clean_lines, linenum, error): + + # Look for "override" or "final" after the parameter list + # (possibly on the next few lines). +- for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())): ++ for i in range(end_line, min(end_line + 3, clean_lines.NumLines())): + line = clean_lines.elided[i][end_col:] + match = Search(r'\b(override|final)\b', line) + if match: +@@ -5926,7 +5926,7 @@ def ProcessFileData(filename, file_extension, lines, error, + + RemoveMultiLineComments(filename, lines, error) + clean_lines = CleansedLines(lines) +- for line in xrange(clean_lines.NumLines()): ++ for line in range(clean_lines.NumLines()): + ProcessLine(filename, file_extension, clean_lines, line, + include_state, function_state, nesting_state, error, + extra_check_functions) +diff --git a/buildscripts/errorcodes.py b/buildscripts/errorcodes.py +index cc46789907..7351e6a12e 100755 +--- a/buildscripts/errorcodes.py ++++ b/buildscripts/errorcodes.py +@@ -5,13 +5,16 @@ + Parses .cpp files for assertions and verifies assertion codes are distinct. + Optionally replaces zero codes in source code with new distinct values. + """ ++from __future__ import unicode_literals ++import io + + import bisect + import os + import sys +-import utils ++from . import utils + from collections import defaultdict, namedtuple + from optparse import OptionParser ++from functools import reduce + + try: + import regex as re +@@ -66,9 +69,9 @@ def parseSourceFiles( callback ): + + for sourceFile in utils.getAllSourceFiles(prefix='src/mongo/'): + if list_files: +- print 'scanning file: ' + sourceFile ++ print('scanning file: ' + sourceFile) + +- with open(sourceFile) as f: ++ with io.open(sourceFile, encoding="utf-8") as f: + text = f.read() + + if not any([zz in text for zz in quick]): +@@ -159,7 +162,7 @@ def readErrorCodes(): + + parseSourceFiles( checkDups ) + +- if seen.has_key("0"): ++ if "0" in seen: + code = "0" + bad = seen[code] + errors.append( bad ) +@@ -167,7 +170,7 @@ def readErrorCodes(): + print( "ZERO_CODE:" ) + print( " %s:%d:%d:%s" % (bad.sourceFile, line, col, bad.lines) ) + +- for code, locations in dups.items(): ++ for code, locations in list(dups.items()): + print( "DUPLICATE IDS: %s" % code ) + for loc in locations: + line, col = getLineAndColumnForPosition(loc) +@@ -189,19 +192,19 @@ def replaceBadCodes( errors, nextCode ): + + for loc in skip_errors: + line, col = getLineAndColumnForPosition(loc) +- print ("SKIPPING NONZERO code=%s: %s:%d:%d" ++ print("SKIPPING NONZERO code=%s: %s:%d:%d" + % (loc.code, loc.sourceFile, line, col)) + + # Dedupe, sort, and reverse so we don't have to update offsets as we go. + for assertLoc in reversed(sorted(set(zero_errors))): + (sourceFile, byteOffset, lines, code) = assertLoc + lineNum, _ = getLineAndColumnForPosition(assertLoc) +- print "UPDATING_FILE: %s:%s" % (sourceFile, lineNum) ++ print("UPDATING_FILE: %s:%s" % (sourceFile, lineNum)) + + ln = lineNum - 1 + + with open(sourceFile, 'r+') as f: +- print "LINE_%d_BEFORE:%s" % (lineNum, f.readlines()[ln].rstrip()) ++ print("LINE_%d_BEFORE:%s" % (lineNum, f.readlines()[ln].rstrip())) + + f.seek(0) + text = f.read() +@@ -212,7 +215,7 @@ def replaceBadCodes( errors, nextCode ): + f.write(text[byteOffset+1:]) + f.seek(0) + +- print "LINE_%d_AFTER :%s" % (lineNum, f.readlines()[ln].rstrip()) ++ print("LINE_%d_AFTER :%s" % (lineNum, f.readlines()[ln].rstrip())) + nextCode += 1 + + +@@ -281,7 +284,7 @@ def main(): + elif options.replace: + replaceBadCodes(errors, next) + else: +- print ERROR_HELP ++ print(ERROR_HELP) + sys.exit(1) + + +diff --git a/buildscripts/eslint.py b/buildscripts/eslint.py +index c1ab04fbab..d5c6aef4fc 100755 +--- a/buildscripts/eslint.py ++++ b/buildscripts/eslint.py +@@ -18,7 +18,7 @@ import sys + import tarfile + import tempfile + import threading +-import urllib ++import urllib.request, urllib.parse, urllib.error + from distutils import spawn + from optparse import OptionParser + +@@ -81,7 +81,7 @@ def get_eslint_from_cache(dest_file, platform, arch): + # Download the file + print("Downloading ESLint %s from %s, saving to %s" % (ESLINT_VERSION, + url, temp_tar_file)) +- urllib.urlretrieve(url, temp_tar_file) ++ urllib.request.urlretrieve(url, temp_tar_file) + + eslint_distfile = ESLINT_SOURCE_TAR_BASE.substitute(platform=platform, arch=arch) + extract_eslint(temp_tar_file, eslint_distfile) +diff --git a/buildscripts/idl/idl/binder.py b/buildscripts/idl/idl/binder.py +index 354acca974..9612e39305 100644 +--- a/buildscripts/idl/idl/binder.py ++++ b/buildscripts/idl/idl/binder.py +@@ -608,7 +608,7 @@ def _validate_enum_int(ctxt, idl_enum): + min_value = min(int_values_set) + max_value = max(int_values_set) + +- valid_int = {x for x in xrange(min_value, max_value + 1)} ++ valid_int = {x for x in range(min_value, max_value + 1)} + + if valid_int != int_values_set: + ctxt.add_enum_non_continuous_range_error(idl_enum, idl_enum.name) +diff --git a/buildscripts/idl/idl/bson.py b/buildscripts/idl/idl/bson.py +index 214b67a7bf..b84421d657 100644 +--- a/buildscripts/idl/idl/bson.py ++++ b/buildscripts/idl/idl/bson.py +@@ -141,7 +141,7 @@ def cpp_bson_type_name(name): + def list_valid_types(): + # type: () -> List[unicode] + """Return a list of supported bson types.""" +- return [a for a in _BSON_TYPE_INFORMATION.iterkeys()] ++ return [a for a in _BSON_TYPE_INFORMATION.keys()] + + + def is_valid_bindata_subtype(name): +diff --git a/buildscripts/idl/idl/cpp_types.py b/buildscripts/idl/idl/cpp_types.py +index aafcf87224..e989664eee 100644 +--- a/buildscripts/idl/idl/cpp_types.py ++++ b/buildscripts/idl/idl/cpp_types.py +@@ -28,6 +28,7 @@ from . import writer + + _STD_ARRAY_UINT8_16 = 'std::array' + ++ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()}) + + def is_primitive_scalar_type(cpp_type): + # type: (unicode) -> bool +@@ -75,11 +76,9 @@ def _qualify_array_type(cpp_type): + return "std::vector<%s>" % (cpp_type) + + +-class CppTypeBase(object): ++class CppTypeBase(ABC): + """Base type for C++ Type information.""" + +- __metaclass__ = ABCMeta +- + def __init__(self, field): + # type: (ast.Field) -> None + """Construct a CppTypeBase.""" +@@ -537,11 +536,9 @@ def get_cpp_type(field): + return cpp_type_info + + +-class BsonCppTypeBase(object): ++class BsonCppTypeBase(ABC): + """Base type for custom C++ support for BSON Types information.""" + +- __metaclass__ = ABCMeta +- + def __init__(self, field): + # type: (ast.Field) -> None + """Construct a BsonCppTypeBase.""" +diff --git a/buildscripts/idl/idl/enum_types.py b/buildscripts/idl/idl/enum_types.py +index 3caed6f67d..f17c926748 100644 +--- a/buildscripts/idl/idl/enum_types.py ++++ b/buildscripts/idl/idl/enum_types.py +@@ -29,11 +29,11 @@ from . import common + from . import syntax + from . import writer + ++ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()}) + +-class EnumTypeInfoBase(object): +- """Base type for enumeration type information.""" + +- __metaclass__ = ABCMeta ++class EnumTypeInfoBase(ABC): ++ """Base type for enumeration type information.""" + + def __init__(self, idl_enum): + # type: (Union[syntax.Enum,ast.Enum]) -> None +@@ -108,8 +108,6 @@ class EnumTypeInfoBase(object): + class _EnumTypeInt(EnumTypeInfoBase): + """Type information for integer enumerations.""" + +- __metaclass__ = ABCMeta +- + def __init__(self, idl_enum): + # type: (Union[syntax.Enum,ast.Enum]) -> None + super(_EnumTypeInt, self).__init__(idl_enum) +@@ -189,8 +187,6 @@ def _get_constant_enum_name(idl_enum, enum_value): + class _EnumTypeString(EnumTypeInfoBase): + """Type information for string enumerations.""" + +- __metaclass__ = ABCMeta +- + def __init__(self, idl_enum): + # type: (Union[syntax.Enum,ast.Enum]) -> None + super(_EnumTypeString, self).__init__(idl_enum) +diff --git a/buildscripts/idl/idl/generator.py b/buildscripts/idl/idl/generator.py +index 9f591eccc4..8f97abf28c 100644 +--- a/buildscripts/idl/idl/generator.py ++++ b/buildscripts/idl/idl/generator.py +@@ -33,6 +33,7 @@ from . import enum_types + from . import struct_types + from . import writer + ++ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()}) + + def _get_field_member_name(field): + # type: (ast.Field) -> unicode +@@ -105,11 +106,9 @@ def _get_bson_type_check(bson_element, ctxt_name, field): + return '%s.checkAndAssertTypes(%s, %s)' % (ctxt_name, bson_element, type_list) + + +-class _FieldUsageCheckerBase(object): ++class _FieldUsageCheckerBase(ABC): + """Check for duplicate fields, and required fields as needed.""" + +- __metaclass__ = ABCMeta +- + def __init__(self, indented_writer): + # type: (writer.IndentedTextWriter) -> None + """Create a field usage checker.""" +@@ -1470,8 +1469,8 @@ def _generate_header(spec, file_name): + header.generate(spec) + + # Generate structs +- with io.open(file_name, mode='wb') as file_handle: +- file_handle.write(stream.getvalue().encode()) ++ with io.open(file_name, mode='w') as file_handle: ++ file_handle.write(stream.getvalue()) + + + def _generate_source(spec, file_name, header_file_name): +@@ -1485,8 +1484,8 @@ def _generate_source(spec, file_name, header_file_name): + source.generate(spec, header_file_name) + + # Generate structs +- with io.open(file_name, mode='wb') as file_handle: +- file_handle.write(stream.getvalue().encode()) ++ with io.open(file_name, mode='w') as file_handle: ++ file_handle.write(stream.getvalue()) + + + def generate_code(spec, output_base_dir, header_file_name, source_file_name): +diff --git a/buildscripts/idl/idl/parser.py b/buildscripts/idl/idl/parser.py +index fd0af9b144..ac36a3a280 100644 +--- a/buildscripts/idl/idl/parser.py ++++ b/buildscripts/idl/idl/parser.py +@@ -30,6 +30,7 @@ from . import common + from . import errors + from . import syntax + ++ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()}) + + class _RuleDesc(object): + """ +@@ -486,11 +487,9 @@ def _parse(stream, error_file_name): + return syntax.IDLParsedSpec(spec, None) + + +-class ImportResolverBase(object): ++class ImportResolverBase(ABC): + """Base class for resolving imported files.""" + +- __metaclass__ = ABCMeta +- + def __init__(self): + # type: () -> None + """Construct a ImportResolver.""" +diff --git a/buildscripts/idl/idl/struct_types.py b/buildscripts/idl/idl/struct_types.py +index 9e2a9504ac..cd46e7c0ff 100644 +--- a/buildscripts/idl/idl/struct_types.py ++++ b/buildscripts/idl/idl/struct_types.py +@@ -23,6 +23,7 @@ from . import ast + from . import common + from . import writer + ++ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()}) + + class ArgumentInfo(object): + """Class that encapsulates information about an argument to a method.""" +@@ -125,11 +126,9 @@ class MethodInfo(object): + "${method_name}(${args});", method_name=self.method_name, args=args) + + +-class StructTypeInfoBase(object): ++class StructTypeInfoBase(ABC): + """Base class for struct and command code generation.""" + +- __metaclass__ = ABCMeta +- + @abstractmethod + def get_constructor_method(self): + # type: () -> MethodInfo +diff --git a/buildscripts/idl/idl/syntax.py b/buildscripts/idl/idl/syntax.py +index 056d2e9dc3..ff9a3953db 100644 +--- a/buildscripts/idl/idl/syntax.py ++++ b/buildscripts/idl/idl/syntax.py +@@ -82,7 +82,7 @@ def _item_and_type(dic): + # type: (Dict[Any, List[Any]]) -> Iterator[Tuple[Any, Any]] + """Return an Iterator of (key, value) pairs from a dictionary.""" + return itertools.chain.from_iterable((_zip_scalar(value, key) +- for (key, value) in dic.viewitems())) ++ for (key, value) in dic.items())) + + + class SymbolTable(object): +diff --git a/buildscripts/idl/tests/test_binder.py b/buildscripts/idl/tests/test_binder.py +index 5502b69d36..b0f4ba4269 100644 +--- a/buildscripts/idl/tests/test_binder.py ++++ b/buildscripts/idl/tests/test_binder.py +@@ -72,7 +72,7 @@ class TestBinder(testcase.IDLTestcase): + cpp_includes: + - 'bar' + - 'foo'""")) +- self.assertEquals(spec.globals.cpp_namespace, "something") ++ self.assertEqual(spec.globals.cpp_namespace, "something") + self.assertListEqual(spec.globals.cpp_includes, ['bar', 'foo']) + + def test_type_positive(self): +diff --git a/buildscripts/lint.py b/buildscripts/lint.py +index d4061a9b04..b1ca5b6169 100644 +--- a/buildscripts/lint.py ++++ b/buildscripts/lint.py +@@ -2,8 +2,8 @@ + import sys + import codecs + +-import cpplint +-import utils ++from . import cpplint ++from . import utils + + class CheckForConfigH: + def __init__(self): +diff --git a/buildscripts/linter/base.py b/buildscripts/linter/base.py +index ae78d52066..7988876c98 100644 +--- a/buildscripts/linter/base.py ++++ b/buildscripts/linter/base.py +@@ -5,12 +5,11 @@ from __future__ import print_function + from abc import ABCMeta, abstractmethod + from typing import Dict, List, Optional + ++ABC = ABCMeta(str('ABC'), (object,), {'__slots__': ()}) + +-class LinterBase(object): ++class LinterBase(ABC): + """Base Class for all linters.""" + +- __metaclass__ = ABCMeta +- + def __init__(self, cmd_name, required_version): + # type: (str, str) -> None + """ +diff --git a/buildscripts/linter/git.py b/buildscripts/linter/git.py +index edde6d0a49..4680e2f5fd 100644 +--- a/buildscripts/linter/git.py ++++ b/buildscripts/linter/git.py +@@ -175,7 +175,7 @@ def get_files_to_check_from_patch(patches, filter_function): + + lines = [] # type: List[str] + for patch in patches: +- with open(patch, "rb") as infile: ++ with open(patch, "r") as infile: + lines += infile.readlines() + + candidates = [check.match(line).group(1) for line in lines if check.match(line)] +diff --git a/buildscripts/linter/parallel.py b/buildscripts/linter/parallel.py +index 0648bfb16e..361da0c559 100644 +--- a/buildscripts/linter/parallel.py ++++ b/buildscripts/linter/parallel.py +@@ -2,7 +2,12 @@ + from __future__ import absolute_import + from __future__ import print_function + +-import Queue ++try: ++ import queue ++except ImportError: ++ #Python 2 ++ import Queue as queue ++ + import threading + import time + from multiprocessing import cpu_count +@@ -17,7 +22,7 @@ def parallel_process(items, func): + except NotImplementedError: + cpus = 1 + +- task_queue = Queue.Queue() # type: Queue.Queue ++ task_queue = queue.Queue() # type: queue.Queue + + # Use a list so that worker function will capture this variable + pp_event = threading.Event() +@@ -30,7 +35,7 @@ def parallel_process(items, func): + while not pp_event.is_set(): + try: + item = task_queue.get_nowait() +- except Queue.Empty: ++ except queue.Empty: + # if the queue is empty, exit the worker thread + pp_event.set() + return +diff --git a/buildscripts/resmokeconfig/loggers/__init__.py b/buildscripts/resmokeconfig/loggers/__init__.py +index 6511d49636..454f675ca2 100644 +--- a/buildscripts/resmokeconfig/loggers/__init__.py ++++ b/buildscripts/resmokeconfig/loggers/__init__.py +@@ -21,7 +21,7 @@ def _get_named_loggers(): + named_loggers = {} + + try: +- (root, _dirs, files) = os.walk(dirname).next() ++ (root, _dirs, files) = next(os.walk(dirname)) + for filename in files: + (short_name, ext) = os.path.splitext(filename) + if ext in (".yml", ".yaml"): +diff --git a/buildscripts/resmokeconfig/suites/__init__.py b/buildscripts/resmokeconfig/suites/__init__.py +index e075dd22e0..2ca2187e6e 100644 +--- a/buildscripts/resmokeconfig/suites/__init__.py ++++ b/buildscripts/resmokeconfig/suites/__init__.py +@@ -21,7 +21,7 @@ def _get_named_suites(): + named_suites = {} + + try: +- (root, _dirs, files) = os.walk(dirname).next() ++ (root, _dirs, files) = next(os.walk(dirname)) + for filename in files: + (short_name, ext) = os.path.splitext(filename) + if ext in (".yml", ".yaml"): +diff --git a/buildscripts/resmokelib/config.py b/buildscripts/resmokelib/config.py +index 1dcd7d7793..8a15651b4a 100644 +--- a/buildscripts/resmokelib/config.py ++++ b/buildscripts/resmokelib/config.py +@@ -58,7 +58,7 @@ DEFAULTS = { + "repeat": 1, + "reportFailureStatus": "fail", + "reportFile": None, +- "seed": long(time.time() * 256), # Taken from random.py code in Python 2.7. ++ "seed": int(time.time() * 256), # Taken from random.py code in Python 2.7. + "serviceExecutor": None, + "shellReadMode": None, + "shellWriteMode": None, +diff --git a/buildscripts/resmokelib/core/process.py b/buildscripts/resmokelib/core/process.py +index 03fb849616..e70f90abb4 100644 +--- a/buildscripts/resmokelib/core/process.py ++++ b/buildscripts/resmokelib/core/process.py +@@ -196,8 +196,8 @@ class Process(object): + finally: + win32api.CloseHandle(mongo_signal_handle) + +- print "Failed to cleanly exit the program, calling TerminateProcess() on PID: " +\ +- str(self._process.pid) ++ print("Failed to cleanly exit the program, calling TerminateProcess() on PID: " +\ ++ str(self._process.pid)) + + # Adapted from implementation of Popen.terminate() in subprocess.py of Python 2.7 + # because earlier versions do not catch exceptions. +diff --git a/buildscripts/resmokelib/logging/buildlogger.py b/buildscripts/resmokelib/logging/buildlogger.py +index a577d64e3f..d5405bd15c 100644 +--- a/buildscripts/resmokelib/logging/buildlogger.py ++++ b/buildscripts/resmokelib/logging/buildlogger.py +@@ -205,7 +205,7 @@ class BuildloggerServer(object): + def __init__(self): + tmp_globals = {} + self.config = {} +- execfile(_BUILDLOGGER_CONFIG, tmp_globals, self.config) ++ exec(compile(open(_BUILDLOGGER_CONFIG).read(), _BUILDLOGGER_CONFIG, 'exec'), tmp_globals, self.config) + + # Rename "slavename" to "username" if present. + if "slavename" in self.config and "username" not in self.config: +diff --git a/buildscripts/resmokelib/selector.py b/buildscripts/resmokelib/selector.py +index 3fff181c18..4395c3b2cf 100644 +--- a/buildscripts/resmokelib/selector.py ++++ b/buildscripts/resmokelib/selector.py +@@ -66,7 +66,7 @@ class TestFileExplorer(object): + A list of paths as a list(str). + """ + tests = [] +- with open(root_file_path, "rb") as filep: ++ with open(root_file_path, "r") as filep: + for test_path in filep: + test_path = test_path.strip() + tests.append(test_path) +@@ -294,7 +294,7 @@ def make_expression(conf): + elif isinstance(conf, dict): + if len(conf) != 1: + raise ValueError("Tag matching expressions should only contain one key") +- key = conf.keys()[0] ++ key = next(iter(conf.keys())) + value = conf[key] + if key == "$allOf": + return _AllOfExpression(_make_expression_list(value)) +diff --git a/buildscripts/resmokelib/testing/executor.py b/buildscripts/resmokelib/testing/executor.py +index cc665568f0..db8d385826 100644 +--- a/buildscripts/resmokelib/testing/executor.py ++++ b/buildscripts/resmokelib/testing/executor.py +@@ -64,7 +64,7 @@ class TestSuiteExecutor(object): + jobs_to_start = num_tests + + # Must be done after getting buildlogger configuration. +- self._jobs = [self._make_job(job_num) for job_num in xrange(jobs_to_start)] ++ self._jobs = [self._make_job(job_num) for job_num in range(jobs_to_start)] + + def run(self): + """ +@@ -290,7 +290,7 @@ class TestSuiteExecutor(object): + queue.put(test_case) + + # Add sentinel value for each job to indicate when there are no more items to process. +- for _ in xrange(len(self._jobs)): ++ for _ in range(len(self._jobs)): + queue.put(None) + + return queue +diff --git a/buildscripts/resmokelib/testing/fixtures/interface.py b/buildscripts/resmokelib/testing/fixtures/interface.py +index 6dffa24e43..dfeeb1326d 100644 +--- a/buildscripts/resmokelib/testing/fixtures/interface.py ++++ b/buildscripts/resmokelib/testing/fixtures/interface.py +@@ -4,6 +4,7 @@ Interface of the different fixtures for executing JSTests against. + + from __future__ import absolute_import + ++import six + import time + + import pymongo +@@ -27,13 +28,11 @@ def make_fixture(class_name, *args, **kwargs): + return _FIXTURES[class_name](*args, **kwargs) + + +-class Fixture(object): ++class Fixture(six.with_metaclass(registry.make_registry_metaclass(_FIXTURES), object)): + """ + Base class for all fixtures. + """ + +- __metaclass__ = registry.make_registry_metaclass(_FIXTURES) +- + # We explicitly set the 'REGISTERED_NAME' attribute so that PyLint realizes that the attribute + # is defined for all subclasses of Fixture. + REGISTERED_NAME = "Fixture" +diff --git a/buildscripts/resmokelib/testing/fixtures/replicaset.py b/buildscripts/resmokelib/testing/fixtures/replicaset.py +index 025ce257a7..678ef45930 100644 +--- a/buildscripts/resmokelib/testing/fixtures/replicaset.py ++++ b/buildscripts/resmokelib/testing/fixtures/replicaset.py +@@ -75,7 +75,7 @@ class ReplicaSetFixture(interface.ReplFixture): + self.replset_name = self.mongod_options.get("replSet", "rs") + + if not self.nodes: +- for i in xrange(self.num_nodes): ++ for i in range(self.num_nodes): + node = self._new_mongod(i, self.replset_name) + self.nodes.append(node) + +diff --git a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py +index 4f90d16f51..eb96b8be38 100644 +--- a/buildscripts/resmokelib/testing/fixtures/shardedcluster.py ++++ b/buildscripts/resmokelib/testing/fixtures/shardedcluster.py +@@ -85,7 +85,7 @@ class ShardedClusterFixture(interface.Fixture): + self.configsvr.setup() + + if not self.shards: +- for i in xrange(self.num_shards): ++ for i in range(self.num_shards): + if self.num_rs_nodes_per_shard is None: + shard = self._new_standalone_shard(i) + elif isinstance(self.num_rs_nodes_per_shard, int): +diff --git a/buildscripts/resmokelib/testing/hooks/interface.py b/buildscripts/resmokelib/testing/hooks/interface.py +index 6ca4ae79a7..a225a1b8e9 100644 +--- a/buildscripts/resmokelib/testing/hooks/interface.py ++++ b/buildscripts/resmokelib/testing/hooks/interface.py +@@ -7,6 +7,7 @@ from __future__ import absolute_import + from ... import logging + from ...utils import registry + ++import six + + _HOOKS = {} + +@@ -22,13 +23,11 @@ def make_custom_behavior(class_name, *args, **kwargs): + return _HOOKS[class_name](*args, **kwargs) + + +-class CustomBehavior(object): ++class CustomBehavior(six.with_metaclass(registry.make_registry_metaclass(_HOOKS), object)): + """ + The common interface all CustomBehaviors will inherit from. + """ + +- __metaclass__ = registry.make_registry_metaclass(_HOOKS) +- + REGISTERED_NAME = registry.LEAVE_UNREGISTERED + + @staticmethod +diff --git a/buildscripts/resmokelib/testing/suite.py b/buildscripts/resmokelib/testing/suite.py +index 132a2d70d9..07262d194a 100644 +--- a/buildscripts/resmokelib/testing/suite.py ++++ b/buildscripts/resmokelib/testing/suite.py +@@ -262,7 +262,7 @@ class Suite(object): + sb.append("Executed %d times in %0.2f seconds:" % (num_iterations, total_time_taken)) + + combined_summary = _summary.Summary(0, 0.0, 0, 0, 0, 0) +- for iteration in xrange(num_iterations): ++ for iteration in range(num_iterations): + # Summarize each execution as a bulleted list of results. + bulleter_sb = [] + summary = self._summarize_report( +diff --git a/buildscripts/resmokelib/testing/summary.py b/buildscripts/resmokelib/testing/summary.py +index bb44472caa..54da2181d5 100644 +--- a/buildscripts/resmokelib/testing/summary.py ++++ b/buildscripts/resmokelib/testing/summary.py +@@ -17,6 +17,6 @@ def combine(summary1, summary2): + Returns a summary representing the sum of 'summary1' and 'summary2'. + """ + args = [] +- for i in xrange(len(Summary._fields)): ++ for i in range(len(Summary._fields)): + args.append(summary1[i] + summary2[i]) + return Summary._make(args) +diff --git a/buildscripts/resmokelib/testing/testcases/interface.py b/buildscripts/resmokelib/testing/testcases/interface.py +index be7f14afd5..f736bd5c36 100644 +--- a/buildscripts/resmokelib/testing/testcases/interface.py ++++ b/buildscripts/resmokelib/testing/testcases/interface.py +@@ -7,6 +7,7 @@ from __future__ import absolute_import + + import os + import os.path ++import six + import unittest + + from ... import config +@@ -27,13 +28,11 @@ def make_test_case(test_kind, *args, **kwargs): + return _TEST_CASES[test_kind](*args, **kwargs) + + +-class TestCase(unittest.TestCase): ++class TestCase(six.with_metaclass(registry.make_registry_metaclass(_TEST_CASES), unittest.TestCase)): + """ + A test case to execute. + """ + +- __metaclass__ = registry.make_registry_metaclass(_TEST_CASES) +- + REGISTERED_NAME = registry.LEAVE_UNREGISTERED + + def __init__(self, logger, test_kind, test_name): +@@ -46,10 +45,10 @@ class TestCase(unittest.TestCase): + if not isinstance(logger, logging.Logger): + raise TypeError("logger must be a Logger instance") + +- if not isinstance(test_kind, basestring): ++ if not isinstance(test_kind, str): + raise TypeError("test_kind must be a string") + +- if not isinstance(test_name, basestring): ++ if not isinstance(test_name, str): + raise TypeError("test_name must be a string") + + # When the TestCase is created by the TestSuiteExecutor (through a call to make_test_case()) +diff --git a/buildscripts/resmokelib/testing/testcases/jstest.py b/buildscripts/resmokelib/testing/testcases/jstest.py +index adb28285f0..528a9747a9 100644 +--- a/buildscripts/resmokelib/testing/testcases/jstest.py ++++ b/buildscripts/resmokelib/testing/testcases/jstest.py +@@ -235,7 +235,7 @@ class JSTestCase(interface.TestCase): + test_cases = [] + try: + # If there are multiple clients, make a new thread for each client. +- for thread_id in xrange(self.num_clients): ++ for thread_id in range(self.num_clients): + logger = self.logger.new_test_thread_logger(self.test_kind, str(thread_id)) + test_case = self._create_test_case_for_thread(logger, thread_id) + test_cases.append(test_case) +diff --git a/buildscripts/resmokelib/utils/__init__.py b/buildscripts/resmokelib/utils/__init__.py +index fa782f3430..3ce73c9b64 100644 +--- a/buildscripts/resmokelib/utils/__init__.py ++++ b/buildscripts/resmokelib/utils/__init__.py +@@ -43,14 +43,14 @@ def is_string_list(lst): + """ + Returns true if 'lst' is a list of strings, and false otherwise. + """ +- return isinstance(lst, list) and all(isinstance(x, basestring) for x in lst) ++ return isinstance(lst, list) and all(isinstance(x, str) for x in lst) + + + def is_string_set(value): + """ + Returns true if 'value' is a set of strings, and false otherwise. + """ +- return isinstance(value, set) and all(isinstance(x, basestring) for x in value) ++ return isinstance(value, set) and all(isinstance(x, str) for x in value) + + + def is_js_file(filename): +diff --git a/buildscripts/resmokelib/utils/globstar.py b/buildscripts/resmokelib/utils/globstar.py +index 644ebfe3e3..52100d7d9d 100644 +--- a/buildscripts/resmokelib/utils/globstar.py ++++ b/buildscripts/resmokelib/utils/globstar.py +@@ -145,7 +145,7 @@ def _list_dir(pathname): + """ + + try: +- (_root, dirs, files) = os.walk(pathname).next() ++ (_root, dirs, files) = next(os.walk(pathname)) + return (dirs, files) + except StopIteration: + return None # 'pathname' directory does not exist +diff --git a/buildscripts/resmokelib/utils/jscomment.py b/buildscripts/resmokelib/utils/jscomment.py +index 18da788582..a393c43723 100644 +--- a/buildscripts/resmokelib/utils/jscomment.py ++++ b/buildscripts/resmokelib/utils/jscomment.py +@@ -39,7 +39,7 @@ def get_tags(pathname): + # TODO: it might be worth supporting the block (indented) style of YAML lists in + # addition to the flow (bracketed) style + tags = yaml.safe_load(_strip_jscomments(match.group(1))) +- if not isinstance(tags, list) and all(isinstance(tag, basestring) for tag in tags): ++ if not isinstance(tags, list) and all(isinstance(tag, str) for tag in tags): + raise TypeError("Expected a list of string tags, but got '%s'" % (tags)) + return tags + except yaml.YAMLError as err: +diff --git a/buildscripts/resmokelib/utils/queue.py b/buildscripts/resmokelib/utils/queue.py +index 80da5e2cc6..41d23d54bf 100644 +--- a/buildscripts/resmokelib/utils/queue.py ++++ b/buildscripts/resmokelib/utils/queue.py +@@ -9,15 +9,20 @@ See https://bugs.python.org/issue1167930 for more details. + + from __future__ import absolute_import + +-import Queue ++try: ++ import queue ++except ImportError: ++ #Python 2 ++ import Queue as queue ++ + import time + + + # Exception that is raised when get_nowait() is called on an empty Queue. +-Empty = Queue.Empty ++Empty = queue.Empty + + +-class Queue(Queue.Queue): ++class Queue(queue.Queue): + """ + A multi-producer, multi-consumer queue. + """ +diff --git a/buildscripts/utils.py b/buildscripts/utils.py +index 69a78921ca..93c697adca 100644 +--- a/buildscripts/utils.py ++++ b/buildscripts/utils.py +@@ -122,7 +122,7 @@ def getprocesslist(): + raw = "" + try: + raw = execsys( "/bin/ps axww" )[0] +- except Exception,e: ++ except Exception as e: + print( "can't get processlist: " + str( e ) ) + + r = re.compile( "[\r\n]+" ) +@@ -145,7 +145,7 @@ def choosePathExist( choices , default=None): + return default + + def filterExists(paths): +- return filter(os.path.exists, paths) ++ return list(filter(os.path.exists, paths)) + + def ensureDir( name ): + d = os.path.dirname( name ) +@@ -176,7 +176,7 @@ def didMongodStart( port=27017 , timeout=20 ): + try: + checkMongoPort( port ) + return True +- except Exception,e: ++ except Exception as e: + print( e ) + timeout = timeout - 1 + return False +@@ -213,7 +213,7 @@ def find_python(min_version=(2, 5)): + pass + + version = re.compile(r'[Pp]ython ([\d\.]+)', re.MULTILINE) +- binaries = ('python27', 'python2.7', 'python26', 'python2.6', 'python25', 'python2.5', 'python') ++ binaries = ('python3', 'python27', 'python2.7', 'python26', 'python2.6', 'python25', 'python2.5', 'python') + for binary in binaries: + try: + out, err = subprocess.Popen([binary, '-V'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() +@@ -251,7 +251,7 @@ def run_smoke_command(*args): + # at the position they occurred + def replace_with_repr(unicode_error): + offender = unicode_error.object[unicode_error.start:unicode_error.end] +- return (unicode(repr(offender).strip("'").strip('"')), unicode_error.end) ++ return (str(repr(offender).strip("'").strip('"')), unicode_error.end) + + codecs.register_error('repr', replace_with_repr) + +diff --git a/site_scons/libdeps.py b/site_scons/libdeps.py +index 632ed29be5..1641c3ba90 100644 +--- a/site_scons/libdeps.py ++++ b/site_scons/libdeps.py +@@ -122,7 +122,7 @@ def __get_libdeps(node): + marked.add(n.target_node) + tsorted.append(n.target_node) + +- except DependencyCycleError, e: ++ except DependencyCycleError as e: + if len(e.cycle_nodes) == 1 or e.cycle_nodes[0] != e.cycle_nodes[-1]: + e.cycle_nodes.insert(0, n.target_node) + raise +@@ -150,7 +150,7 @@ def __get_syslibdeps(node): + for lib in __get_libdeps(node): + for syslib in node.get_env().Flatten(lib.get_env().get(syslibdeps_env_var, [])): + if syslib: +- if type(syslib) in (str, unicode) and syslib.startswith(missing_syslibdep): ++ if type(syslib) in (str, str) and syslib.startswith(missing_syslibdep): + print("Target '%s' depends on the availability of a " + "system provided library for '%s', " + "but no suitable library was found during configuration." % +@@ -209,7 +209,7 @@ def get_syslibdeps(source, target, env, for_signature): + # they're believed to represent library short names, that should be prefixed with -l + # or the compiler-specific equivalent. I.e., 'm' becomes '-lm', but 'File("m.a") is passed + # through whole cloth. +- if type(d) in (str, unicode): ++ if type(d) in (str, str): + result.append('%s%s%s' % (lib_link_prefix, d, lib_link_suffix)) + else: + result.append(d) +diff --git a/site_scons/mongo/__init__.py b/site_scons/mongo/__init__.py +index 510bd7bcc2..f77478092b 100644 +--- a/site_scons/mongo/__init__.py ++++ b/site_scons/mongo/__init__.py +@@ -5,4 +5,4 @@ + def print_build_failures(): + from SCons.Script import GetBuildFailures + for bf in GetBuildFailures(): +- print "%s failed: %s" % (bf.node, bf.errstr) ++ print("%s failed: %s" % (bf.node, bf.errstr)) +diff --git a/site_scons/mongo/generators.py b/site_scons/mongo/generators.py +index c07e86a4d1..5958e6923b 100644 +--- a/site_scons/mongo/generators.py ++++ b/site_scons/mongo/generators.py +@@ -1,6 +1,6 @@ + # -*- mode: python; -*- + +-import md5 ++import hashlib + + # Default and alternative generator definitions go here. + +@@ -44,7 +44,7 @@ def default_variant_dir_generator(target, source, env, for_signature): + + # Hash the named options and their values, and take the first 8 characters of the hash as + # the variant name +- hasher = md5.md5() ++ hasher = hashlib.md5() + for option in variant_options: + hasher.update(option) + hasher.update(str(env.GetOption(option))) +diff --git a/site_scons/site_tools/dagger/__init__.py b/site_scons/site_tools/dagger/__init__.py +index f05228cfe4..f10b4027e1 100644 +--- a/site_scons/site_tools/dagger/__init__.py ++++ b/site_scons/site_tools/dagger/__init__.py +@@ -5,7 +5,7 @@ import logging + + import SCons + +-import dagger ++from . import dagger + + def generate(env, **kwargs): + """The entry point for our tool. However, the builder for +diff --git a/site_scons/site_tools/dagger/dagger.py b/site_scons/site_tools/dagger/dagger.py +index 1eeefe1ea3..03e7603d29 100644 +--- a/site_scons/site_tools/dagger/dagger.py ++++ b/site_scons/site_tools/dagger/dagger.py +@@ -40,8 +40,8 @@ import sys + + import SCons + +-import graph +-import graph_consts ++from . import graph ++from . import graph_consts + + + LIB_DB = [] # Stores every SCons library nodes +@@ -269,7 +269,7 @@ def write_obj_db(target, source, env): + for obj in OBJ_DB: + __generate_file_rels(obj, g) + +- for exe in EXE_DB.keys(): ++ for exe in list(EXE_DB.keys()): + __generate_exe_rels(exe, g) + + # target is given as a list of target SCons nodes - this builder is only responsible for +diff --git a/site_scons/site_tools/dagger/graph.py b/site_scons/site_tools/dagger/graph.py +index 5ebe6f4506..379d5245e6 100644 +--- a/site_scons/site_tools/dagger/graph.py ++++ b/site_scons/site_tools/dagger/graph.py +@@ -4,11 +4,13 @@ import abc + import json + import copy + +-import graph_consts ++from . import graph_consts + + if sys.version_info >= (3, 0): + basestring = str + ++ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) ++ + class Graph(object): + """Graph class for storing the build dependency graph. The graph stores the + directed edges as a nested dict of { RelationshipType: {From_Node: Set of +@@ -141,7 +143,7 @@ class Graph(object): + node_dict["id"] = id + node_dict["node"] = {} + +- for property, value in vars(node).iteritems(): ++ for property, value in vars(node).items(): + if isinstance(value, set): + node_dict["node"][property] = list(value) + else: +@@ -170,10 +172,9 @@ class Graph(object): + sum(len(x) for x in self._edges.values()), hash(self)) + + +-class NodeInterface(object): ++class NodeInterface(ABC): + """Abstract base class for all Node Objects - All nodes must have an id and name + """ +- __metaclass__ = abc.ABCMeta + + @abc.abstractproperty + def id(self): +@@ -190,7 +191,7 @@ class NodeLib(NodeInterface): + def __init__(self, id, name, input=None): + if isinstance(input, dict): + should_fail = False +- for k, v in input.iteritems(): ++ for k, v in input.items(): + try: + if isinstance(v, list): + setattr(self, k, set(v)) +@@ -310,7 +311,7 @@ class NodeSymbol(NodeInterface): + if isinstance(input, dict): + should_fail = False + +- for k, v in input.iteritems(): ++ for k, v in input.items(): + try: + if isinstance(v, list): + setattr(self, k, set(v)) +@@ -435,7 +436,7 @@ class NodeFile(NodeInterface): + def __init__(self, id, name, input=None): + if isinstance(input, dict): + should_fail = False +- for k, v in input.iteritems(): ++ for k, v in input.items(): + try: + if isinstance(v, list): + setattr(self, k, set(v)) +@@ -551,7 +552,7 @@ class NodeExe(NodeInterface): + def __init__(self, id, name, input=None): + if isinstance(input, dict): + should_fail = False +- for k, v in input.iteritems(): ++ for k, v in input.items(): + try: + if isinstance(v, list): + setattr(self, k, set(v)) +diff --git a/site_scons/site_tools/dagger/graph_consts.py b/site_scons/site_tools/dagger/graph_consts.py +index 81fe86d75c..a922a4f3f6 100644 +--- a/site_scons/site_tools/dagger/graph_consts.py ++++ b/site_scons/site_tools/dagger/graph_consts.py +@@ -17,8 +17,8 @@ NODE_SYM = 2 + NODE_FILE = 3 + NODE_EXE = 4 + +-RELATIONSHIP_TYPES = range(1, 9) +-NODE_TYPES = range(1, 5) ++RELATIONSHIP_TYPES = list(range(1, 9)) ++NODE_TYPES = list(range(1, 5)) + + + """Error/query codes""" +diff --git a/site_scons/site_tools/dagger/graph_test.py b/site_scons/site_tools/dagger/graph_test.py +index bc84f5868c..6c0168cf97 100644 +--- a/site_scons/site_tools/dagger/graph_test.py ++++ b/site_scons/site_tools/dagger/graph_test.py +@@ -5,8 +5,8 @@ from JSON + + import json + import unittest +-import graph +-import graph_consts ++from . import graph ++from . import graph_consts + + + def generate_graph(): +@@ -122,15 +122,15 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions): + node = graph.NodeLib("test_node", "test_node") + self.g._nodes = {"test_node": node} + +- self.assertEquals(self.g.get_node("test_node"), node) ++ self.assertEqual(self.g.get_node("test_node"), node) + +- self.assertEquals(self.g.get_node("missing_node"), None) ++ self.assertEqual(self.g.get_node("missing_node"), None) + + def test_add_node(self): + node = graph.NodeLib("test_node", "test_node") + self.g.add_node(node) + +- self.assertEquals(self.g.get_node("test_node"), node) ++ self.assertEqual(self.g.get_node("test_node"), node) + + self.assertRaises(ValueError, self.g.add_node, node) + +@@ -153,16 +153,16 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions): + self.g.add_edge(graph_consts.LIB_FIL, self.from_node_lib.id, + self.to_node_file.id) + +- self.assertEquals(self.g.edges[graph_consts.LIB_LIB][ ++ self.assertEqual(self.g.edges[graph_consts.LIB_LIB][ + self.from_node_lib.id], set([self.to_node_lib.id])) + +- self.assertEquals(self.g.edges[graph_consts.LIB_SYM][ ++ self.assertEqual(self.g.edges[graph_consts.LIB_SYM][ + self.from_node_lib.id], set([self.to_node_sym.id])) + +- self.assertEquals(self.g.edges[graph_consts.LIB_FIL][ ++ self.assertEqual(self.g.edges[graph_consts.LIB_FIL][ + self.from_node_lib.id], set([self.to_node_file.id])) + +- self.assertEquals(self.to_node_lib.dependent_libs, ++ self.assertEqual(self.to_node_lib.dependent_libs, + set([self.from_node_lib.id])) + + def test_add_edge_files(self): +@@ -173,14 +173,14 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions): + self.g.add_edge(graph_consts.FIL_LIB, self.from_node_file.id, + self.to_node_lib.id) + +- self.assertEquals(self.g.edges[graph_consts.FIL_FIL][ ++ self.assertEqual(self.g.edges[graph_consts.FIL_FIL][ + self.from_node_file.id], set([self.to_node_file.id])) +- self.assertEquals(self.g.edges[graph_consts.FIL_SYM][ ++ self.assertEqual(self.g.edges[graph_consts.FIL_SYM][ + self.from_node_file.id], set([self.to_node_sym.id])) +- self.assertEquals(self.g.edges[graph_consts.FIL_LIB][ ++ self.assertEqual(self.g.edges[graph_consts.FIL_LIB][ + self.from_node_file.id], set([self.to_node_lib.id])) + +- self.assertEquals(self.to_node_file.dependent_files, ++ self.assertEqual(self.to_node_file.dependent_files, + set([self.from_node_file.id])) + + def test_export_to_json(self): +@@ -188,7 +188,7 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions): + generated_graph.export_to_json("export_test.json") + generated = open("export_test.json", "r") + correct = open("test_graph.json", "r") +- self.assertEquals(json.load(generated), json.load(correct)) ++ self.assertEqual(json.load(generated), json.load(correct)) + generated.close() + correct.close() + +@@ -205,7 +205,7 @@ class TestGraphMethods(unittest.TestCase, CustomAssertions): + self.assertNodeEquals( + graph_fromJSON.get_node(id), correct_graph.get_node(id)) + +- self.assertEquals(graph_fromJSON.edges, correct_graph.edges) ++ self.assertEqual(graph_fromJSON.edges, correct_graph.edges) + + + if __name__ == '__main__': +diff --git a/site_scons/site_tools/distsrc.py b/site_scons/site_tools/distsrc.py +index 861f5d9e2e..d2dff0b612 100644 +--- a/site_scons/site_tools/distsrc.py ++++ b/site_scons/site_tools/distsrc.py +@@ -20,7 +20,7 @@ import shutil + import tarfile + import time + import zipfile +-import StringIO ++import io + + from distutils.spawn import find_executable + +@@ -82,7 +82,7 @@ class DistSrcTarArchive(DistSrcArchive): + + def append_file_contents(self, filename, file_contents, + mtime=time.time(), +- mode=0644, ++ mode=0o644, + uname="root", + gname="root"): + file_metadata = tarfile.TarInfo(name=filename) +@@ -91,7 +91,7 @@ class DistSrcTarArchive(DistSrcArchive): + file_metadata.uname = uname + file_metadata.gname = gname + file_metadata.size = len(file_contents) +- file_buf = StringIO.StringIO(file_contents) ++ file_buf = io.StringIO(file_contents) + if self.archive_mode == 'r': + self.archive_file.close() + self.archive_file = tarfile.open( +@@ -119,7 +119,7 @@ class DistSrcZipArchive(DistSrcArchive): + name=key, + size=item_data.file_size, + mtime=time.mktime(fixed_time), +- mode=0775 if is_dir else 0664, ++ mode=0o775 if is_dir else 0o664, + type=tarfile.DIRTYPE if is_dir else tarfile.REGTYPE, + uid=0, + gid=0, +@@ -129,7 +129,7 @@ class DistSrcZipArchive(DistSrcArchive): + + def append_file_contents(self, filename, file_contents, + mtime=time.time(), +- mode=0644, ++ mode=0o644, + uname="root", + gname="root"): + self.archive_file.writestr(filename, file_contents) +@@ -139,7 +139,7 @@ class DistSrcZipArchive(DistSrcArchive): + + def build_error_action(msg): + def error_stub(target=None, source=None, env=None): +- print msg ++ print(msg) + env.Exit(1) + return [ error_stub ] + +@@ -162,7 +162,7 @@ def distsrc_action_generator(source, target, env, for_signature): + + target_ext = str(target[0])[-3:] + if not target_ext in [ 'zip', 'tar' ]: +- print "Invalid file format for distsrc. Must be tar or zip file" ++ print("Invalid file format for distsrc. Must be tar or zip file") + env.Exit(1) + + git_cmd = "\"%s\" archive --format %s --output %s --prefix ${MONGO_DIST_SRC_PREFIX} HEAD" % ( +diff --git a/site_scons/site_tools/icecream.py b/site_scons/site_tools/icecream.py +index 9838b63349..fdf0c26030 100644 +--- a/site_scons/site_tools/icecream.py ++++ b/site_scons/site_tools/icecream.py +@@ -99,7 +99,7 @@ def generate(env): + suffixes = _CSuffixes + _CXXSuffixes + for object_builder in SCons.Tool.createObjBuilders(env): + emitterdict = object_builder.builder.emitter +- for suffix in emitterdict.iterkeys(): ++ for suffix in emitterdict.keys(): + if not suffix in suffixes: + continue + base = emitterdict[suffix] +diff --git a/site_scons/site_tools/idl_tool.py b/site_scons/site_tools/idl_tool.py +index 78bedfaa74..628f345361 100755 +--- a/site_scons/site_tools/idl_tool.py ++++ b/site_scons/site_tools/idl_tool.py +@@ -47,7 +47,7 @@ def idl_scanner(node, env, path): + + deps_list = deps_str.splitlines() + +- nodes_deps_list = [ env.File(d) for d in deps_list] ++ nodes_deps_list = [ env.File(d.decode("utf-8")) for d in deps_list] + nodes_deps_list.extend(env.Glob('#buildscripts/idl/*.py')) + nodes_deps_list.extend(env.Glob('#buildscripts/idl/idl/*.py')) + +diff --git a/site_scons/site_tools/jstoh.py b/site_scons/site_tools/jstoh.py +index dc90b324b2..567958a50f 100644 +--- a/site_scons/site_tools/jstoh.py ++++ b/site_scons/site_tools/jstoh.py +@@ -1,3 +1,5 @@ ++from __future__ import unicode_literals ++ + import os + import sys + +@@ -39,8 +41,8 @@ def jsToHeader(target, source): + + text = '\n'.join(h) + +- print "writing: %s" % outFile +- with open(outFile, 'wb') as out: ++ print("writing: %s" % outFile) ++ with open(outFile, 'w') as out: + try: + out.write(text) + finally: +@@ -49,7 +51,7 @@ def jsToHeader(target, source): + + if __name__ == "__main__": + if len(sys.argv) < 3: +- print "Must specify [target] [source] " ++ print("Must specify [target] [source] ") + sys.exit(1) + + jsToHeader(sys.argv[1], sys.argv[2:]) +diff --git a/site_scons/site_tools/mongo_integrationtest.py b/site_scons/site_tools/mongo_integrationtest.py +index ff9a5f451b..fccbbebb47 100644 +--- a/site_scons/site_tools/mongo_integrationtest.py ++++ b/site_scons/site_tools/mongo_integrationtest.py +@@ -12,10 +12,10 @@ def register_integration_test(env, test): + env.Alias('$INTEGRATION_TEST_ALIAS', installed_test) + + def integration_test_list_builder_action(env, target, source): +- ofile = open(str(target[0]), 'wb') ++ ofile = open(str(target[0]), 'w') + try: + for s in _integration_tests: +- print '\t' + str(s) ++ print('\t' + str(s)) + ofile.write('%s\n' % s) + finally: + ofile.close() +diff --git a/site_scons/site_tools/mongo_unittest.py b/site_scons/site_tools/mongo_unittest.py +index ec99ab2d45..a4185a6b41 100644 +--- a/site_scons/site_tools/mongo_unittest.py ++++ b/site_scons/site_tools/mongo_unittest.py +@@ -11,10 +11,10 @@ def register_unit_test(env, test): + env.Alias('$UNITTEST_ALIAS', test) + + def unit_test_list_builder_action(env, target, source): +- ofile = open(str(target[0]), 'wb') ++ ofile = open(str(target[0]), 'w') + try: + for s in _unittests: +- print '\t' + str(s) ++ print('\t' + str(s)) + ofile.write('%s\n' % s) + finally: + ofile.close() +diff --git a/site_scons/site_tools/split_dwarf.py b/site_scons/site_tools/split_dwarf.py +index 95130c9e9a..c02d78619f 100644 +--- a/site_scons/site_tools/split_dwarf.py ++++ b/site_scons/site_tools/split_dwarf.py +@@ -52,7 +52,7 @@ def generate(env): + + for object_builder in SCons.Tool.createObjBuilders(env): + emitterdict = object_builder.builder.emitter +- for suffix in emitterdict.iterkeys(): ++ for suffix in emitterdict.keys(): + if not suffix in suffixes: + continue + base = emitterdict[suffix] +diff --git a/site_scons/site_tools/thin_archive.py b/site_scons/site_tools/thin_archive.py +index 511c0ef6e5..0d8a83b83a 100644 +--- a/site_scons/site_tools/thin_archive.py ++++ b/site_scons/site_tools/thin_archive.py +@@ -41,7 +41,7 @@ def exists(env): + for line in pipe.stdout: + if isgnu: + continue # consume all data +- isgnu = re.search(r'^GNU ar', line) ++ isgnu = re.search(b'^GNU ar', line) + + return bool(isgnu) + +diff --git a/site_scons/site_tools/xcode.py b/site_scons/site_tools/xcode.py +index 9ec68c3547..5ddebb2e00 100644 +--- a/site_scons/site_tools/xcode.py ++++ b/site_scons/site_tools/xcode.py +@@ -9,4 +9,4 @@ def generate(env): + + if 'DEVELOPER_DIR' in os.environ: + env['ENV']['DEVELOPER_DIR'] = os.environ['DEVELOPER_DIR'] +- print "NOTE: Xcode detected; propagating DEVELOPER_DIR from shell environment to subcommands" ++ print("NOTE: Xcode detected; propagating DEVELOPER_DIR from shell environment to subcommands") +diff --git a/src/mongo/SConscript b/src/mongo/SConscript +index 426e57cafd..cc09ab4e0e 100644 +--- a/src/mongo/SConscript ++++ b/src/mongo/SConscript +@@ -156,7 +156,7 @@ js_engine_ver = get_option("js-engine") if get_option("server-js") == "on" else + + # On windows, we need to escape the backslashes in the command-line + # so that windows paths look okay. +-cmd_line = " ".join(sys.argv).encode('string-escape') ++cmd_line = " ".join(sys.argv).encode('unicode_escape') + if env.TargetOSIs('windows'): + cmd_line = cmd_line.replace('\\', r'\\') + +@@ -602,7 +602,7 @@ env.Append(MODULE_BANNERS = [distsrc.File('README'), + distsrc.File('MPL-2')]) + + # If no module has introduced a file named LICENSE.txt, then inject the AGPL. +-if sum(itertools.imap(lambda x: x.name == "LICENSE.txt", env['MODULE_BANNERS'])) == 0: ++if sum(map(lambda x: x.name == "LICENSE.txt", env['MODULE_BANNERS'])) == 0: + env.Append(MODULE_BANNERS = [distsrc.File('GNU-AGPL-3.0')]) + + # All module banners get staged to the top level of the tarfile, so we +@@ -621,7 +621,7 @@ module_banner_transforms = ["--transform %s=$SERVER_DIST_BASENAME" % d for d in + # Allow modules to map original file name directories to subdirectories + # within the archive (e.g. { "src/mongo/db/modules/enterprise/docs": "snmp"}) + archive_addition_transforms = [] +-for full_dir, archive_dir in env["ARCHIVE_ADDITION_DIR_MAP"].items(): ++for full_dir, archive_dir in list(env["ARCHIVE_ADDITION_DIR_MAP"].items()): + archive_addition_transforms.append("--transform \"%s=$SERVER_DIST_BASENAME/%s\"" % + (full_dir, archive_dir)) + +diff --git a/src/mongo/base/generate_error_codes.py b/src/mongo/base/generate_error_codes.py +index 420ee964ff..b704767a01 100644 +--- a/src/mongo/base/generate_error_codes.py ++++ b/src/mongo/base/generate_error_codes.py +@@ -26,6 +26,8 @@ + # delete this exception statement from all source files in the program, + # then also delete it in the license file. + ++from __future__ import unicode_literals ++ + """Generate error_codes.{h,cpp} from error_codes.err. + + Format of error_codes.err: +@@ -93,7 +95,7 @@ def main(argv): + categories=error_classes, + ) + +- with open(output, 'wb') as outfile: ++ with open(output, 'w') as outfile: + outfile.write(text) + + def die(message=None): +diff --git a/src/mongo/db/auth/generate_action_types.py b/src/mongo/db/auth/generate_action_types.py +index b712b29666..39252ed293 100755 +--- a/src/mongo/db/auth/generate_action_types.py ++++ b/src/mongo/db/auth/generate_action_types.py +@@ -227,7 +227,7 @@ def hasDuplicateActionTypes(actionTypes): + prevActionType = sortedActionTypes[0] + for actionType in sortedActionTypes[1:]: + if actionType == prevActionType: +- print 'Duplicate actionType %s\n' % actionType ++ print('Duplicate actionType %s\n' % actionType) + didFail = True + prevActionType = actionType + +@@ -240,7 +240,7 @@ def parseActionTypesFromFile(actionTypesFilename): + + if __name__ == "__main__": + if len(sys.argv) != 4: +- print "Usage: generate_action_types.py
" ++ print("Usage: generate_action_types.py
") + sys.exit(-1) + + actionTypes = parseActionTypesFromFile(sys.argv[1]) +diff --git a/src/mongo/db/fts/generate_stop_words.py b/src/mongo/db/fts/generate_stop_words.py +index e0dc801ca9..e0aad760e8 100644 +--- a/src/mongo/db/fts/generate_stop_words.py ++++ b/src/mongo/db/fts/generate_stop_words.py +@@ -7,7 +7,7 @@ def generate( header, source, language_files ): + for x in language_files: + print( "\t%s" % x ) + +- out = open( header, "wb" ) ++ out = open( header, "w" ) + out.write( """ + #pragma once + #include +@@ -24,7 +24,7 @@ namespace fts { + + + +- out = open( source, "wb" ) ++ out = open( source, "w" ) + out.write( '#include "%s"' % header.rpartition( "/" )[2].rpartition( "\\" )[2] ) + out.write( """ + namespace mongo { +@@ -40,7 +40,7 @@ namespace fts { + out.write( ' // %s\n' % l_file ) + out.write( ' {\n' ) + out.write( ' const char* const words[] = {\n' ) +- for word in open( l_file, "rb" ): ++ for word in open( l_file, "r" ): + out.write( ' "%s",\n' % word.strip() ) + out.write( ' };\n' ) + out.write( ' const size_t wordcnt = sizeof(words) / sizeof(words[0]);\n' ) +diff --git a/src/mongo/db/fts/unicode/gen_diacritic_map.py b/src/mongo/db/fts/unicode/gen_diacritic_map.py +index 08cfa95cda..7c623aff60 100644 +--- a/src/mongo/db/fts/unicode/gen_diacritic_map.py ++++ b/src/mongo/db/fts/unicode/gen_diacritic_map.py +@@ -45,7 +45,7 @@ def add_diacritic_mapping(codepoint): + # c : recomposed unicode character with diacritics removed + a = chr(codepoint) + d = normalize('NFD', a) +- r = u'' ++ r = '' + + for i in range(len(d)): + if ord(d[i]) not in diacritics: +diff --git a/src/mongo/db/query/collation/generate_icu_init_cpp.py b/src/mongo/db/query/collation/generate_icu_init_cpp.py +index 8ae084aeec..7c576f6ffe 100755 +--- a/src/mongo/db/query/collation/generate_icu_init_cpp.py ++++ b/src/mongo/db/query/collation/generate_icu_init_cpp.py +@@ -26,6 +26,9 @@ + # delete this exception statement from all source files in the program, + # then also delete it in the license file. + ++from __future__ import unicode_literals ++ ++import array + import optparse + import os + import sys +@@ -110,8 +113,8 @@ MONGO_INITIALIZER(LoadICUData)(InitializerContext* context) { + ''' + decimal_encoded_data = '' + with open(data_file_path, 'rb') as data_file: +- decimal_encoded_data = ','.join([str(ord(byte)) for byte in data_file.read()]) +- with open(cpp_file_path, 'wb') as cpp_file: ++ decimal_encoded_data = ','.join([str(byte) for byte in array.array("B", data_file.read()).tolist()]) ++ with open(cpp_file_path, 'w') as cpp_file: + cpp_file.write(source_template % dict(decimal_encoded_data=decimal_encoded_data)) + + if __name__ == '__main__': diff --git a/SPECS/mongodb.spec b/SPECS/mongodb.spec new file mode 100644 index 0000000..e51c000 --- /dev/null +++ b/SPECS/mongodb.spec @@ -0,0 +1,1128 @@ +%global _hardened_build 1 +# for better compatibility with SCL spec file +%{?scl:%scl_package mongodb} +%{!?scl:%global pkg_name %{name}} +# mongod daemon +%global daemon mongod +# mongos daemon +%global daemonshard mongos + +# Arches officially supported by MongoDB upstream +%global upstream_arches x86_64 ppc64le aarch64 s390x +# Working storage engines - used for testing +%ifarch s390x ppc64 + %global storageEngines wiredTiger +%else + %global storageEngines wiredTiger mmapv1 +%endif +# MozJS version +%global mozjsVersion 45 + +# Regression tests may take a long time (many cores recommended), skip them by +# passing --nocheck to rpmbuild or by setting runselftest to 0 if defining +# --nocheck is not possible (e.g. in koji build) +%{!?runselftest:%global runselftest 1} +# To disable unit testing (need to be built -> it slows build) +# ('runselftest' has to be enabled) +%{!?rununittests:%global rununittests 0} +# Do we want to package install_tests +%bcond_without install_tests +# Do we want to package install_unit_tests +# ('rununittests' is needed) +%bcond_with install_unit_tests + +%global MONGO_DISTNAME mongo-r%{version} + +# Python SCL (to run scons with python3; test subpackage) +%global scl_python rh-python36 +%global scl_python_prefix %{scl_python}- + +%global devtoolset devtoolset-7 +%global devtoolset_prefix %{devtoolset}- + +# Convert SCL name into uppercase including - to _ conversion +%if 0%{?scl:1} +%global scl_upper %{lua:print(string.upper(string.gsub(rpm.expand("%{scl}"), "-", "_")))} +%global buildscls %{scl} %{devtoolset} %{scl_python} +%endif + +Name: %{?scl_prefix}mongodb +Version: 3.6.3 +Release: 2%{?dist} +Summary: High-performance, schema-free document-oriented database +Group: Applications/Databases +License: AGPLv3 and zlib and ASL 2.0 +# util/md5 is under the zlib license +# manpages and bson are under ASL 2.0 +# everything else is AGPLv3 +URL: http://www.mongodb.org + +Source0: https://github.com/mongodb/mongo/archive/r%{version}.tar.gz +Source1: %{pkg_name}-tmpfile +Source2: %{pkg_name}.logrotate +Source3: %{daemon}.conf +Source4: %{daemon}.init +Source5: %{daemon}.service +Source6: %{daemon}.sysconf +Source7: %{daemonshard}.conf +Source8: %{daemonshard}.init +Source9: %{daemonshard}.service +Source10: %{daemonshard}.sysconf +Source11: README +Source12: daemon-scl-helper.sh + +# Convert build scripts and testsuite to support python3 +# https://jira.mongodb.org/browse/SERVER-32295 +Patch1: python3-buildscripts-tests.patch + +# Few tests fail because of error in altivec implementation of ByteVector +# https://jira.mongodb.org/browse/SERVER-33395 +Patch2: ppc64le-disable-altivec.patch + + +BuildRequires: %{?devtoolset_prefix}gcc-c++ >= 5.3.0 +BuildRequires: %{?scl_prefix}boost-devel >= 1.56 +# Provides tcmalloc +BuildRequires: %{?scl_prefix}gperftools-devel +BuildRequires: libpcap-devel +BuildRequires: %{?scl_prefix}libstemmer-devel +BuildRequires: openssl-devel +BuildRequires: pcre-devel +BuildRequires: scons +BuildRequires: snappy-devel +BuildRequires: %{?scl_prefix}yaml-cpp-devel +BuildRequires: zlib-devel +BuildRequires: valgrind-devel +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +BuildRequires: systemd +%endif +BuildRequires: %{?scl_python_prefix}python-devel +BuildRequires: %{?scl_python_prefix}python-yaml +BuildRequires: %{?scl_prefix}python-requests +# Required by test suite +%if %runselftest +BuildRequires: %{?scl_python_prefix}python-pymongo +%endif +BuildRequires: %{?scl_prefix}python-cheetah + +%{?scl:Requires:%scl_runtime} + +# Mongodb must run on a 64-bit CPU (see bug #630898) +ExcludeArch: ppc %{sparc} s390 + +%description +Mongo (from "humongous") is a high-performance, open source, schema-free +document-oriented database. MongoDB is written in C++ and offers the following +features: + * Collection oriented storage: easy storage of object/JSON-style data + * Dynamic queries + * Full index support, including on inner objects and embedded arrays + * Query profiling + * Replication and fail-over support + * Efficient storage of binary data including large objects (e.g. photos + and videos) + * Auto-sharding for cloud-level scalability (currently in early alpha) + * Commercial Support Available + +A key goal of MongoDB is to bridge the gap between key/value stores (which are +fast and highly scalable) and traditional RDBMS systems (which are deep in +functionality). + + +%package server +Summary: MongoDB server, sharding server and support scripts +Group: Applications/Databases +Requires(pre): shadow-utils +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units +%else +Requires(post): chkconfig +Requires(preun): chkconfig +Requires(postun): initscripts +%endif + +# Same upstream - wiredtiger is primarilly developed for MongoDB +Provides: bundled(wiredtiger) = %{version} +# MongoDB bundles development release of asio 1.11 +# This is not in Fedora yet (only asio-1.10) +Provides: bundled(asio) = 1.11.0 +# MongoDB stores version of icu into database (if using collators) +# - mongod with using different icu version can't cooperate +Provides: bundled(icu) = 57.1 +# https://software.intel.com/en-us/articles/intel-decimal-floating-point-math-library +Provides: bundled(IntelRDFPMathLib) = 20U1 +# https://github.com/derickr/timelib +Provides: bundled(timelib) = 2017.05beta10 +%ifarch %{upstream_arches} +# MongoDB does provides mozjs customization to recover from OOM +Provides: bundled(mozjs45) = 45.5.0 +%endif + +%{?scl:Requires:%scl_runtime} + +%description server +This package provides the mongo server software, mongo sharding server +software, default configuration files, and init scripts. + + +%if %{with install_tests} +%package test +Summary: MongoDB test suite +Group: Applications/Databases +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: %{name}-server%{?_isa} = %{version}-%{release} +Requires: %{?scl_python_prefix}python-pymongo +Requires: %{?scl_python_prefix}python-yaml +Requires: %{?scl_prefix}python-requests + +%{?scl:Requires:%scl_runtime} + +%description test +This package contains the regression test suite distributed with +the MongoDB sources. +%endif + +# syspath subpackages +%if 0%{?scl:1} +%scl_syspaths_package server -d +%scl_syspaths_package -d +%endif + +%prep +%setup -q -n %{MONGO_DISTNAME} + +%patch1 -p1 +%patch2 -p1 + +# CRLF -> LF +sed -i 's/\r//' README + +# Disable optimization for s2 library +# https://jira.mongodb.org/browse/SERVER-17511 +sed -i -r "s|(env.Append\(CCFLAGS=\['-DDEBUG_MODE=false')(\]\))|\1,'-O0'\2|" src/third_party/s2/SConscript + +#TODO - removed unused bundles +# Use system versions of header files (bundled does not differ) +sed -i -r "s|third_party/libstemmer_c/include/libstemmer.h|libstemmer.h|" src/mongo/db/fts/stemmer.h +sed -i -r "s|third_party/yaml-cpp-0.5.1/include/yaml-cpp/yaml.h|yaml-cpp/yaml.h|" src/mongo/util/options_parser/options_parser.cpp + +# by default use system mongod, mongos and mongo binaries in resmoke.py +sed -i -r "s|os.curdir(, \"mongo\")|\"%{_bindir}\"\1|" buildscripts/resmokelib/config.py +sed -i -r "s|os.curdir(, \"mongod\")|\"%{_bindir}\"\1|" buildscripts/resmokelib/config.py +sed -i -r "s|os.curdir(, \"mongos\")|\"%{_bindir}\"\1|" buildscripts/resmokelib/config.py +# set default data prefix in resmoke.py +sed -i -r "s|/data/db|%{_datadir}/%{pkg_name}-test/var|" buildscripts/resmokelib/config.py + +sed -i -r "s|env python|env python3|" buildscripts/resmoke.py + +# set default storage engine for non 64-bit arches - RHBZ#1303846 +%ifnarch %{upstream_arches} ppc64 +sed -i 's|engine = "wiredTiger"|engine = "mmapv1"|' src/mongo/db/storage/storage_options.h +%endif + +# copy them (we will change their content) +cp %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} \ + %{SOURCE6} %{SOURCE7} %{SOURCE8} %{SOURCE9} %{SOURCE10} %{SOURCE11} ./ + +for f in %{SOURCE4} %{SOURCE8}; do + sed -i -r -e "s|/usr/bin|%{_bindir}|g" \ + -e "s|/var(/run/mongodb)|%{_localstatedir}\1|g" \ + -e "s|/var(/log/mongodb)|%{_localstatedir}\1|g" \ + -e "s|/etc(/mongo[ds]\.conf)|%{_sysconfdir}\1|g" \ + -e "s|/etc(/sysconfig)|%{_sysconfdir}\1|g" \ + -e "s|/var(/lock)|%{_localstatedir}\1|g" \ + -e "s|__SCL_SCRIPTS__|%{?_scl_scripts}|g" \ + -e "s|__list of scls__|\$%{scl_upper}_SCLS_ENABLED|g" \ + "$(basename "$f")" +done + +sed -i -r -e "s|/var(/log/mongodb)|%{_localstatedir}\1|g" \ + -e "s|/var(/run/mongodb)|%{_localstatedir}\1|g" \ + "$(basename %{SOURCE2})" + +for f in %{SOURCE3} %{SOURCE7}; do + sed -i -r -e "s|/var/lib(/mongodb)|%{_sharedstatedir}\1|g" \ + -e "s|/var(/run/mongodb)|%{_localstatedir}\1|g" \ + -e "s|/var(/log/mongodb)|%{_localstatedir}\1|g" \ + "$(basename "$f")" +done + +for f in %{SOURCE6} %{SOURCE10}; do + sed -i -r -e "s|/etc(/mongo[ds]\.conf)|%{_sysconfdir}\1|g" \ + "$(basename "$f")" +done + +sed -i -r -e "s|(/run/mongodb)|%{_localstatedir}\1|g" \ + "$(basename %{SOURCE1})" + +for f in %{SOURCE5} %{SOURCE9}; do + #FIXME check if the _SCLS_ENABLED var isn't empty! + sed -i -r -e "s|/var(/run/mongodb)|%{_localstatedir}\1|g" \ + -e "s|/etc(/sysconfig)|%{_sysconfdir}\1|g" \ + -e "s|/usr/bin(/mongo[ds])|%{_bindir}\1|g" \ + -e "s|__SCL_SCRIPTS__|%{?_scl_scripts}|g" \ + -e "s|__list of scls__|\$%{scl_upper}_SCLS_ENABLED|g" \ + -e "s|@libexecdir@|%{_libexecdir}|" \ + "$(basename "$f")" +done + +sed -i -r -e "s|(/usr/share)|%{_datarootdir}|g" \ + "$(basename %{SOURCE11})" + + +%build +export LANG="en_US.UTF-8" +%{?scl:scl enable %{buildscls} - << "SCLEOF"} +set -ex +# Prepare variables for building +cat > variables.list << EOF +CCFLAGS="%{?optflags} -fvisibility=hidden" +LINKFLAGS="%{?__global_ldflags} -Wl,-z,noexecstack -Wl,--reduce-memory-overheads,--no-keep-memory" +VERBOSE=1 +MONGO_VERSION="%{version}" +VARIANT_DIR="rhscl" +ENV=$(python -c 'import os; print(dict(os.environ))') + +%ifarch aarch64 +# Needed for CRC32 instructions in third_party/wiredtiger/src/checksum/arm64/crc32-arm64.c +CCFLAGS+=" -march=armv8-a+crc" +%endif +EOF +cat variables.list + +# Define build options +cat > build-options << EOF + %{?_smp_mflags} \ + --use-system-pcre \ + --use-system-boost \ + --use-system-snappy \ + --use-system-valgrind \ + --use-system-zlib \ + --use-system-stemmer \ + --use-system-tcmalloc \ + --use-system-yaml \ +%ifarch s390x ppc64 + --mmapv1=off +%else + --mmapv1=on \ +%endif + --wiredtiger=on \ +%ifarch s390x + --use-s390x-crc32=off \ +%endif + --ssl \ + --nostrip \ + --disable-warnings-as-errors \ + --variables-files=variables.list +EOF +# --use-system-asio \ + +cat > build-target << EOF +core tools \ +%if 0%{rununittests} +unittests \ +%endif + +EOF + +# see output of "scons --help" for options +#scons --debug=memory --debug=count all $(cat build-options) || (df -h; cat /proc/meminfo; exit 1) +scons $(cat build-target) $(cat build-options) +%{?scl:SCLEOF} + + +%install +install -p -D -m 755 mongod %{buildroot}%{_bindir}/mongod +install -p -D -m 755 mongos %{buildroot}%{_bindir}/mongos +install -p -D -m 755 mongo %{buildroot}%{_bindir}/mongo +install -p -D -m 755 build/*/mongo/mongoperf %{buildroot}%{_bindir}/mongoperf +install -p -D -m 755 build/*/mongo/tools/mongobridge %{buildroot}%{_bindir}/mongobridge + +# Compass isn't open sourced, so not in Fedora +#rm %{buildroot}%{_bindir}/install_compass + +mkdir -p %{buildroot}%{_sharedstatedir}/%{pkg_name} +mkdir -p %{buildroot}%{_localstatedir}/log/%{pkg_name} +mkdir -p %{buildroot}%{_localstatedir}/run/%{pkg_name} +mkdir -p %{buildroot}%{_sysconfdir}/sysconfig + +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +install -p -D -m 644 "$(basename %{SOURCE1})" %{buildroot}%{_tmpfilesdir}/%{?scl_prefix}%{pkg_name}.conf +install -p -D -m 644 "$(basename %{SOURCE5})" %{buildroot}%{_unitdir}/%{?scl_prefix}%{daemon}.service +install -p -D -m 644 "$(basename %{SOURCE9})" %{buildroot}%{_unitdir}/%{?scl_prefix}%{daemonshard}.service + +mkdir -p %{buildroot}%{_libexecdir} +install -p -m 755 %{SOURCE12} %{buildroot}%{_libexecdir}/mongodb-scl-helper +%else +install -p -D -m 755 "$(basename %{SOURCE4})" %{buildroot}%{_initddir}/%{?scl_prefix}%{daemon} +install -p -D -m 755 "$(basename %{SOURCE8})" %{buildroot}%{_initddir}/%{?scl_prefix}%{daemonshard} +%endif +install -p -D -m 644 "$(basename %{SOURCE2})" %{buildroot}%{?scl:%_root_sysconfdir}%{!?scl:%_sysconfdir}/logrotate.d/%{?scl_prefix}%{pkg_name} +install -p -D -m 644 "$(basename %{SOURCE3})" %{buildroot}%{_sysconfdir}/%{daemon}.conf +install -p -D -m 644 "$(basename %{SOURCE7})" %{buildroot}%{_sysconfdir}/%{daemonshard}.conf +install -p -D -m 644 "$(basename %{SOURCE6})" %{buildroot}%{_sysconfdir}/sysconfig/%{daemon} +install -p -D -m 644 "$(basename %{SOURCE10})" %{buildroot}%{_sysconfdir}/sysconfig/%{daemonshard} +# Enable WiredTiger for 64-bit architectures by default +%ifarch %{upstream_arches} ppc64 +sed -i -r "s|(engine: )mmapv1|\1wiredTiger|" %{buildroot}%{_sysconfdir}/%{daemon}.conf +%endif + +#TODO - create man page for mongobridge +install -d -m 755 %{buildroot}%{_mandir}/man1 +install -p -m 644 debian/mongo.1 %{buildroot}%{_mandir}/man1/ +install -p -m 644 debian/mongoperf.1 %{buildroot}%{_mandir}/man1/ +install -p -m 644 debian/mongod.1 %{buildroot}%{_mandir}/man1/ +install -p -m 644 debian/mongos.1 %{buildroot}%{_mandir}/man1/ + +%if %{with install_tests} +mkdir -p %{buildroot}%{_datadir}/%{pkg_name}-test +mkdir -p %{buildroot}%{_datadir}/%{pkg_name}-test/var +mkdir -p %{buildroot}%{_datadir}/%{pkg_name}-test/buildscripts +install -p -D -m 755 buildscripts/resmoke.py %{buildroot}%{_datadir}/%{pkg_name}-test/ +install -p -D -m 444 buildscripts/__init__.py %{buildroot}%{_datadir}/%{pkg_name}-test/buildscripts/ + +cp -R buildscripts/resmokeconfig %{buildroot}%{_datadir}/%{pkg_name}-test/buildscripts/ +cp -R buildscripts/resmokelib %{buildroot}%{_datadir}/%{pkg_name}-test/buildscripts/ +cp -R jstests %{buildroot}%{_datadir}/%{pkg_name}-test/ +# Remove executable flag from JS tests +for file in `find %{buildroot}%{_datadir}/%{pkg_name}-test/jstests -type f`; do + chmod a-x $file +done + +install -p -D -m 444 "$(basename %{SOURCE11})" %{buildroot}%{_datadir}/%{pkg_name}-test/ +%endif +%if %{with install_unit_tests} +mkdir -p %{buildroot}%{_datadir}/%{pkg_name}-test/unittests +while read unittest +do + install -p -D $unittest %{buildroot}%{_datadir}/%{pkg_name}-test/unittests/ +done < ./build/unittests.txt +%endif + +# syspath subpackages +%if 0%{?scl:1} +server_binaries='mongod mongos' +binaries='mongo mongoperf' +binaries_no_man='mongobridge' +for pkg in '' server; do + mans= sep= pkg_name=mongodb${pkg:+-$pkg} + eval "list=\$${pkg:+${pkg}_}binaries" + for bin in $list; do mans+="${sep}man1/$bin.1.gz" ; sep=' '; done + %scl_syspaths_install_wrappers -n $pkg_name -m script -p bin $list + %scl_syspaths_install_wrappers -n $pkg_name -m link -p man $mans +done +%scl_syspaths_install_wrappers -n mongodb-server -m script -p bin $binaries_no_man + +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_sysconfdir}/%{daemon}.conf %{_root_sysconfdir}/%{scl_prefix}%{daemon}.conf +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_sysconfdir}/%{daemonshard}.conf %{_root_sysconfdir}/%{scl_prefix}%{daemonshard}.conf + +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_localstatedir}/log/%{pkg_name} %{_root_localstatedir}/log/%{name} +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_sharedstatedir}/%{pkg_name} %{_root_localstatedir}/lib/%{name} + +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_unitdir}/%{?scl_prefix}%{daemon}.service %{_unitdir}/%{daemon}.service +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_unitdir}/%{?scl_prefix}%{daemonshard}.service %{_unitdir}/%{daemonshard}.service +%else +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_initddir}/%{?scl_prefix}%{daemon} %{_initddir}/%{daemon} +%scl_syspaths_install_wrapper -n mongodb-server -m link %{_initddir}/%{?scl_prefix}%{daemonshard} %{_initddir}/%{daemonshard} +%endif +%endif + + +%check +export LANG="en_US.UTF-8" +%if %runselftest +%{?scl:scl enable %{buildscls} - << "SCLEOF"} +set -ex +# More info about testing: +# http://www.mongodb.org/about/contributors/tutorial/test-the-mongodb-server/ +cd %{_builddir}/%{MONGO_DISTNAME} +mkdir ./var + +# Run old-style heavy unit tests (dbtest binary) +#mkdir ./var/dbtest +#./dbtest --dbpath `pwd`/var/dbtest + +%if 0%{rununittests} +#TODO - failed on x86_64 and aarch64 +sed -i "/session_catalog_migration_destination_test/d" build/unittests.txt +sed -i "/connection_string_test/d" build/unittests.txt +sed -i "/dns_query_test/d" build/unittests.txt +sed -i "/mongo_uri_test/d" build/unittests.txt + +# Run new-style unit tests (*_test files) +./buildscripts/resmoke.py --dbpathPrefix `pwd`/var --continueOnFailure --mongo=%{buildroot}%{_bindir}/mongo --mongod=%{buildroot}%{_bindir}/%{daemon} --mongos=%{buildroot}%{_bindir}/%{daemonshard} --nopreallocj --suites unittests +%endif + +%ifarch ppc64le +rm -f jstests/core/shelltypes.js +%endif + +for engine in %{storageEngines}; do + # Run JavaScript integration tests + ./buildscripts/resmoke.py --dbpathPrefix `pwd`/var --continueOnFailure --mongo=%{buildroot}%{_bindir}/mongo --mongod=%{buildroot}%{_bindir}/%{daemon} --mongos=%{buildroot}%{_bindir}/%{daemonshard} --nopreallocj --suites core --storageEngine=$engine +done + +rm -Rf ./var +%{?scl:SCLEOF} +%endif + +%post -p /sbin/ldconfig + + +%postun -p /sbin/ldconfig + + +%pre server +getent group %{pkg_name} >/dev/null || groupadd -f -g 184 -r %{pkg_name} +if ! getent passwd %{pkg_name} >/dev/null ; then + if ! getent passwd 184 >/dev/null ; then + useradd -r -u 184 -g %{pkg_name} -d /var/lib/%{pkg_name} \ + -s /sbin/nologin -c "MongoDB Database Server" %{pkg_name} + else + useradd -r -g %{pkg_name} -d /var/lib/%{pkg_name} \ + -s /sbin/nologin -c "MongoDB Database Server" %{pkg_name} + fi +fi +exit 0 + + +%post server +%if 0%{?scl:1} +# handle SELinux context for files outside of normal location +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +semanage fcontext -a -e %{_unitdir}/%{daemon}.service %{_unitdir}/%{?scl_prefix}%{daemon}.service >/dev/null 2>&1 || : +semanage fcontext -a -e %{_unitdir}/%{daemonshard}.service %{_unitdir}/%{?scl_prefix}%{daemonshard}.service >/dev/null 2>&1 || : +selinuxenabled && load_policy || : +restorecon %{_unitdir}/%{?scl_prefix}* >/dev/null 2>&1 || : +%else +semanage fcontext -a -e %{_initddir}/%{daemon} %{_initddir}/%{?scl_prefix}%{daemon} >/dev/null 2>&1 || : +semanage fcontext -a -e %{_initddir}/%{daemon} %{_initddir}/%{?scl_prefix}%{daemonshard} >/dev/null 2>&1 || : +selinuxenabled && load_policy || : +restorecon %{_initddir}/%{?scl_prefix}* >/dev/null 2>&1 || : +%endif +restorecon -r %{?_scl_root}/ >/dev/null 2>&1 || : +restorecon -R %{_sharedstatedir}/%{pkg_name} +restorecon -R %{_localstatedir}/log/%{pkg_name} +restorecon -R %{_localstatedir}/run/%{pkg_name} +%endif + +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 + # https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd + # daemon-reload + %systemd_postun +%else + /sbin/chkconfig --add %{?scl_prefix}%{daemon} + /sbin/chkconfig --add %{?scl_prefix}%{daemonshard} +%endif + + +%preun server +if [ "$1" = 0 ]; then +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 + # --no-reload disable; stop + %systemd_preun %{?scl_prefix}%{daemon}.service + %systemd_preun %{?scl_prefix}%{daemonshard}.service +%else + /sbin/service %{?scl_prefix}%{daemon} stop >/dev/null 2>&1 + /sbin/service %{?scl_prefix}%{daemonshard} stop >/dev/null 2>&1 + /sbin/chkconfig --del %{?scl_prefix}%{daemon} + /sbin/chkconfig --del %{?scl_prefix}%{daemonshard} +%endif +fi + + +%postun server +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 + # daemon-reload + %systemd_postun +%endif +if [ "$1" -ge 1 ] ; then +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 + # try-restart + %systemd_postun_with_restart %{?scl_prefix}%{daemon}.service + %systemd_postun_with_restart %{?scl_prefix}%{daemonshard}.service +%else + /sbin/service %{?scl_prefix}%{daemon} condrestart >/dev/null 2>&1 || : + /sbin/service %{?scl_prefix}%{daemonshard} condrestart >/dev/null 2>&1 || : +%endif +fi + + +%files +%{!?_licensedir:%global license %%doc} +%license GNU-AGPL-3.0.txt APACHE-2.0.txt +%doc README +%{_bindir}/mongo +%{_bindir}/mongoperf +%{_bindir}/mongobridge + +%{_mandir}/man1/mongo.1* +%{_mandir}/man1/mongoperf.1* + + +%files server +%{_bindir}/mongod +%{_bindir}/mongos +%{_mandir}/man1/mongod.1* +%{_mandir}/man1/mongos.1* + +%dir %attr(0750, %{pkg_name}, root) %{_sharedstatedir}/%{pkg_name} +%dir %attr(0755, %{pkg_name}, root) %{_localstatedir}/log/%{pkg_name} +%dir %attr(0755, %{pkg_name}, root) %{_localstatedir}/run/%{pkg_name} +%config(noreplace) %{?scl:%_root_sysconfdir}%{!?scl:%_sysconfdir}/logrotate.d/%{?scl_prefix}%{pkg_name} +%config(noreplace) %{_sysconfdir}/%{daemon}.conf +%config(noreplace) %{_sysconfdir}/%{daemonshard}.conf +%config(noreplace) %{_sysconfdir}/sysconfig/%{daemon} +%config(noreplace) %{_sysconfdir}/sysconfig/%{daemonshard} +%if 0%{?fedora} >= 15 || 0%{?rhel} >= 7 +%{_tmpfilesdir}/%{?scl_prefix}%{pkg_name}.conf +%{_unitdir}/%{?scl_prefix}*.service +%{_libexecdir}/mongodb-scl-helper +%else +%{_initddir}/%{?scl_prefix}%{daemon} +%{_initddir}/%{?scl_prefix}%{daemonshard} +%endif + + +%if %{with install_tests} +%files test +%doc %{_datadir}/%{pkg_name}-test/README +%defattr(-,%{pkg_name},root) +%dir %attr(0755, %{pkg_name}, root) %{_datadir}/%{pkg_name}-test +%dir %attr(0755, %{pkg_name}, root) %{_datadir}/%{pkg_name}-test/var +%{_datadir}/%{pkg_name}-test/jstests +%{_datadir}/%{pkg_name}-test/buildscripts +%{_datadir}/%{pkg_name}-test/resmoke.* +%{_datadir}/%{pkg_name}-test/__pycache__ +%if %{with install_unit_tests} +%{_datadir}/%{pkg_name}-test/unittests +%endif +%endif + +# syspath subpackages +%if 0%{?scl:1} +%scl_syspaths_files +%scl_syspaths_files server +%endif + + +%changelog +* Wed Feb 28 2018 Marek Skalický - 3.6.3-2 +- Fix using numactl in service files + +* Fri Feb 23 2018 Marek Skalický - 3.6.3-1 +- Update to latest upstream minor version + +* Thu Feb 22 2018 Marek Skalický - 3.6.2-3 +- Use numactl for service starting + +* Wed Feb 21 2018 Marek Skalický - 3.6.2-2 +- Workaround for unicode test fails on ppc64le + +* Mon Feb 19 2018 Marek Skalický - 3.6.2-1 +- Rebase to latest minor version + +* Tue Jan 09 2018 Marek Skalický - 3.6.0-3 +- Fix wrong -test requires + +* Mon Jan 08 2018 Marek Skalický - 3.6.0-2 +- Add macro to disable running of unittests +- Install python3 __pycache__ directory + +* Fri Dec 15 2017 Marek Skalický - 3.6.0-1 +- Rebase to mongodb 3.6.0 from Fedora 28 + +* Mon Sep 25 2017 Marek Skalický - 3.4.9-1 +- Update to latest minor version + Resolves: RHBZ#1474252 + +* Mon Aug 28 2017 Marek Skalický - 3.4.7-1 +- Update to latest minor version + +* Tue Aug 22 2017 Marek Skalický - 3.4.6-3 +- Fix HOME directory of mongodb user + Resolves: RHBZ#1482018 + +* Tue Aug 08 2017 Marek Skalický - 3.4.6-2 +- Don't include syspaths systemd services into mongodb-server package + +* Fri Jul 21 2017 Marek Skalický - 3.4.6-1 +- Update to 3.4.6 minor version + Resolves: RHBZ#1474252 + +* Fri Jun 23 2017 Marek Skalický - 3.4.3-3 +- Add -syspath subpackages + +* Tue Jun 20 2017 Marek Skalický - 3.4.3-2 +- Use gcc from devtoolset for compilation +- Fix dependencies + +* Mon Jun 5 2017 Marek Skalicky - 3.4.3-1 +- Convert mongodb 3.4.3 from Fedora to SCL + +* Wed Oct 19 2016 Marek Skalický - 3.2.10-1 +- Update to latest upstream minor version (3.2.10) + Resolves: RHBZ#1386229 + +* Fri Sep 16 2016 Marek Skalický - 3.2.9-1 +- Update to latest upstream minor version (3.2.9) + Resolves: RHBZ#1376475 + +* Tue May 10 2016 Marek Skalicky - 3.2.6-2 +- Disable executable stack (since MongoDB 3.2.5) + Resolves: #1333660 + +* Fri May 6 2016 Marek Skalicky - 3.2.6-1 +- Upgrade to MongoDB 3.2.6 + Resolves: #1333660 + +* Wed Apr 6 2016 Marek Skalicky - 3.2.4-1 +- Upgrade to version 3.2.4 + +* Wed Apr 6 2016 Marek Skalicky - 3.2.1-2 +- Fixed permissions in test subpackage + +* Wed Dec 9 2015 Marek Skalicky - 3.2.1-1 +- Configuration files updated + (mongod and mongos also listen on ipv6 localhost by default) +- test subpackage contains resmoke.py tool instead of smoke.py +- Upgrade to latest minor upgrade 3.2.1 + +* Wed Dec 9 2015 Marek Skalicky - 3.2.0-1 +- Upgrade to latest stable version 3.2.0 + (merged changes from Fedora 24) + +* Wed May 13 2015 Marek Skalicky 2.6.9-1 +- Correct SELinux type for slc-helper script + Resolves: #1202013 +- Fix mongodb user HOME (Resolves: #1206157) +- Upgrade to latest minor release 2.6.9 (Resolves: #1207118) + +* Thu Mar 19 2015 Marek Skalicky 2.6.8-4 +- Use mongod_initrc_exex_t SELinux type for slc-helper script + +* Thu Mar 19 2015 Marek Skalicky 2.6.8-3 +- Fixed SELinux context +- Renamed scl-helper script + +* Thu Mar 19 2015 Marek Skalicky 2.6.8-2 +- Resolves: #1202013 (Daemon run with proper SELinux context) + +* Mon Mar 2 2015 Marek Skalicky 2.6.8-1 +- Upgrade to version 2.6.8 +- Resolves: #1194412 (MongoDB Security & Defaults) + +* Fri Feb 27 2015 Honza Horak - 2.6.7-9 +- Remove NFS register feature for questionable usage for DBs +- Allow to skip tests during build +- Simplify few SCL macros + +* Thu Feb 26 2015 Marek Skalicky 2.6.7-8 +- Resolves: #1075736 (initscript doesn't respect LSB) + +* Tue Jan 27 2015 Honza Horak - 2.6.7-7 +- Use 0755 on var directory for tests, mark README as doc + +* Tue Jan 27 2015 Honza Horak - 2.6.7-6 +- Run selinux magic in post, not preun +- Create lock file directory + +* Tue Jan 27 2015 Honza Horak - 2.6.7-5 +- Add removed $ by mistake +- Create dir for config files and data in scl register + +* Tue Jan 27 2015 Honza Horak - 2.6.7-4 +- Implement scl register support + +* Mon Jan 26 2015 Honza Horak - 2.6.7-3 +- Convert - to _ when translating to uppercase scl name +- Do not use & in the init script if daemon call is used + +* Fri Jan 23 2015 Marek Skalicky 2.6.7-2 +- Changed name of conf and log files +- Added service-environment into mongodb package +- Changed location of log files + +* Mon Jan 19 2015 Marek Skalicky 2.6.7-1 +- Merged changes from Fedora Rawhide + +* Tue Nov 18 2014 Marek Skalicky 2.6.5-5 +- Changed and cleaned up requirements + +* Fri Nov 14 2014 Marek Skalicky 2.6.5-4 +- Changed v8 dependency to SCL v8314 +- Added MONGODB_OPTIONS options variable into *.init files + +* Fri Nov 7 2014 Marek Skalicky 2.6.5-3 +- Ported to SCL + +* Thu Oct 9 2014 Marek Skalicky 2.6.5-2 +- Corrected/Finished renaming services and pid files +- Changed default mongos ports + +* Thu Oct 9 2014 Marek Skalicky 2.6.5-1 +- Updated to version 2.6.5 +- Renamed sysmted service files (to reflect mainstream names) + +* Sun Aug 17 2014 Fedora Release Engineering - 2.6.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Jul 9 2014 Jan Pacner - 2.6.3-1 +- Resolves: #1103163 new major release with major differences +- add sharding server daemon init/unit files (and rename existing) +- use ld library path from env +- spec cleanup/clarification +- Resolves: #1047858 (RFE: Turn on PrivateTmp and relocate unix socket file) +- Related: #963824 (bloated binaries; splitting according to latest upstream) + +* Sat Jun 7 2014 Peter Robinson 2.4.9-7 +- aarch64 now has gperftools + +* Sat Jun 07 2014 Fedora Release Engineering - 2.4.9-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Fri May 23 2014 Petr Machata - 2.4.9-5 +- Rebuild for boost 1.55.0 + +* Fri May 23 2014 David Tardon - 2.4.9-4 +- rebuild for boost 1.55.0 + + +* Fri Feb 14 2014 T.C. Hollingsworth - 2.4.9-3 +- rebuild for icu-53 (via v8) + +* Tue Feb 04 2014 Matthias Saou 2.4.9-2 +- Merge el6 branch changes (we shouldn't start diverging now). +- Re-introduce conditionals, but to still support EL6. +- Include run directory only for EL6. +- Don't own the /usr/include directory. +- Make libmongodb requirement arch specific (#1010535). +- Fix multiple_occurrences error from duplicate --quiet options (#1022476). +- Fix broken v8 version specific requirement (#1027157). + +* Sun Jan 19 2014 Peter Robinson 2.4.9-1 +- Update to 2.4.9 +- Drop old < F-15 conditionals +- Cleanup Spec +- Run ldconfig for the lib package, not binary package +- Don't make some directories world readable (RHBZ 857926) + +* Mon Jan 06 2014 Jan Pacner - 2.4.6-3 +- Resolves: #1027157 (mongo shell sefgaults when using arbitrary v8 version) + +* Thu Nov 28 2013 Jan Pacner - 2.4.8-1 +- new release +- Resolves: #1010712 (LimitNOFILE) +- make sysconf options being respected + +* Wed Aug 21 2013 Troy Dawson - 2.4.6-1 +- Updated to 2.4.6 +- Added Requires: v8 (#971595) + +* Sun Jul 28 2013 Petr Machata - 2.4.5-6 +- Rebuild for boost 1.54.0 + +* Sat Jul 27 2013 pmachata@redhat.com - 2.4.5-5 +- Rebuild for boost 1.54.0 + +* Fri Jul 12 2013 Troy Dawson - 2.4.5-4 +- Added Provides: mongodb-devel to libmongodb-devel + +* Fri Jul 12 2013 Troy Dawson - 2.4.5-3 +- Removed hardening section. Currently doesn't work with 2.4.x + Wasn't really being applied when we thought it was. +- Cleaned up RHEL5 spec leftovers + +* Thu Jul 11 2013 David Marlin - 2.4.5-2 +- Updated arm patches to work with 2.4.x + +* Mon Jul 08 2013 Troy Dawson - 2.4.5-1 +- Update to version 2.4.5 to fix CVE-2013-4650 +- Patch3 fixed upstream - https://jira.mongodb.org/browse/SERVER-5575 +- Patch4 fixed upstream - https://jira.mongodb.org/browse/SERVER-6514 +- Put lib dir in correct place +- no longer have to remove duplicate headers + +* Sun Jul 07 2013 Johan Hedin - 2.4.4-4 +- Added patch to make mongodb compile with gcc 4.8 + +* Wed Jul 03 2013 Johan Hedin - 2.4.4-3 +- Added missing daemon name to the preun script for the server +- Fixed init script so that it does not kill the server on shutdown +- Renamed mongodb-devel to libmongdb-devel +- Dependency cleanup between the sub packages +- Moved Requires for the server to the server sub package +- Using %%{_unitdir} macro for where to put systemd unit files +- Fixed rpmlint warnings regarding %% in comments and mixed tabs/spaces +- Run systemd-tmpfiles --create mongodb.conf in post server + +* Mon Jul 01 2013 Troy Dawson - 2.4.4-2 +- Turn on hardened build (#958014) +- Apply patch to accept env flags + +* Sun Jun 30 2013 Johan Hedin - 2.4.4-1 +- Bumped version up to 2.4.4 +- Rebased the old 2.2 patches that are still needed to 2.4.4 +- Added some new patches to build 2.4.4 properly + +* Sat May 04 2013 David Marlin - 2.2.4-2 +- Updated patch to work on both ARMv5 and ARMv7 (#921226) + +* Thu May 02 2013 Troy Dawson - 2.2.4-1 +- Bumped version up to 2.2.4 +- Refreshed all patches to 2.2.4 + +* Fri Apr 26 2013 David Marlin - 2.2.3-5 +- Patch to build on ARM (#921226) + +* Wed Mar 27 2013 Troy Dawson - 2.2.3-4 +- Fix for CVE-2013-1892 + +* Sun Feb 10 2013 Denis Arnaud - 2.2.3-3 +- Rebuild for Boost-1.53.0 + +* Sat Feb 09 2013 Denis Arnaud - 2.2.3-2 +- Rebuild for Boost-1.53.0 + +* Tue Feb 05 2013 Troy Dawson - 2.2.3-1 +- Update to version 2.2.3 + +* Mon Jan 07 2013 Troy Dawson - 2.2.2-2 +- remove duplicate headers (#886064) + +* Wed Dec 05 2012 Troy Dawson - 2.2.2-1 +- Updated to version 2.2.2 + +* Tue Nov 27 2012 Troy Dawson - 2.2.1-3 +- Add ssl build option +- Using the reserved mongod UID for the useradd +- mongod man page in server package (#880351) +- added optional MONGODB_OPTIONS to init script + +* Wed Oct 31 2012 Nathaniel McCallum - 2.2.1-2 +- Make sure build and install flags are the same +- Actually remove the js patch file + +* Wed Oct 31 2012 Nathaniel McCallum - 2.2.1-1 +- Remove fork fix patch (fixed upstream) +- Remove pcre patch (fixed upstream) +- Remove mozjs patch (now using v8 upstream) +- Update to 2.2.1 + +* Tue Oct 02 2012 Troy Dawson - 2.2.0-6 +- full flag patch to get 32 bit builds to work + +* Tue Oct 02 2012 Troy Dawson - 2.2.0-5 +- shared libraries patch +- Fix up minor %%files issues + +* Fri Sep 28 2012 Troy Dawson - 2.2.0-4 +- Fix spec files problems + +* Fri Sep 28 2012 Troy Dawson - 2.2.0-3 +- Updated patch to use system libraries +- Update init script to use a pidfile + +* Thu Sep 27 2012 Troy Dawson - 2.2.0-2 +- Added patch to use system libraries + +* Wed Sep 19 2012 Troy Dawson - 2.2.0-1 +- Updated to 2.2.0 +- Updated patches that were still needed +- use v8 instead of spider_monkey due to bundled library issues + +* Tue Aug 21 2012 Nathaniel McCallum - 2.0.7-1 +- Update to 2.0.7 +- Don't patch for boost-filesystem version 3 on EL6 + +* Mon Aug 13 2012 Nathaniel McCallum - 2.0.6-3 +- Remove EL5 support +- Add patch to use boost-filesystem version 3 + +* Wed Aug 01 2012 Nathaniel McCallum - 2.0.6-2 +- Don't apply fix-xtime patch on EL5 + +* Wed Aug 01 2012 Nathaniel McCallum - 2.0.6-1 +- Update to 2.0.6 +- Update no-term patch +- Add fix-xtime patch for new boost + +* Fri Jul 20 2012 Fedora Release Engineering - 2.0.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Apr 17 2012 Nathaniel McCallum - 2.0.4-1 +- Update to 2.0.4 +- Remove oldpython patch (fixed upstream) +- Remove snappy patch (fixed upstream) + +* Tue Feb 28 2012 Fedora Release Engineering - 2.0.2-10 +- Rebuilt for c++ ABI breakage + +* Fri Feb 10 2012 Petr Pisar - 2.0.2-9 +- Rebuild against PCRE 8.30 + +* Fri Feb 03 2012 Nathaniel McCallum - 2.0.2-8 +- Disable HTTP interface by default (#752331) + +* Fri Feb 03 2012 Nathaniel McCallum - 2.0.2-7 +- Enable journaling by default (#656112) +- Remove BuildRequires on unittest (#755081) + +* Fri Feb 03 2012 Nathaniel McCallum - 2.0.2-6 +- Clean up mongodb-src-r2.0.2-js.patch and fix #787246 + +* Tue Jan 17 2012 Nathaniel McCallum - 2.0.2-5 +- Enable build using external snappy + +* Tue Jan 17 2012 Nathaniel McCallum - 2.0.2-4 +- Patch buildsystem for building on older pythons (RHEL5) + +* Mon Jan 16 2012 Nathaniel McCallum - 2.0.2-3 +- Merge the 2.0.2 spec file with EPEL +- Merge mongodb-sm-pkgconfig.patch into mongodb-src-r2.0.2-js.patch + +* Mon Jan 16 2012 Nathaniel McCallum - 2.0.2-2 +- Add pkg-config enablement patch + +* Sat Jan 14 2012 Nathaniel McCallum - 2.0.2-1 +- Update to 2.0.2 +- Add new files (mongotop and bsondump manpage) +- Update mongodb-src-r1.8.2-js.patch => mongodb-src-r2.0.2-js.patch +- Update mongodb-fix-fork.patch +- Fix pcre linking + +* Fri Jan 13 2012 Fedora Release Engineering - 1.8.2-11 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Sun Nov 20 2011 Chris Lalancette - 1.8.2-10 +- Rebuild for rawhide boost update + +* Thu Sep 22 2011 Chris Lalancette - 1.8.2-9 +- Copy the right source file into place for tmpfiles.d + +* Tue Sep 20 2011 Chris Lalancette - 1.8.2-8 +- Add a tmpfiles.d file to create the /var/run/mongodb subdirectory + +* Mon Sep 12 2011 Chris Lalancette - 1.8.2-7 +- Add a patch to fix the forking to play nice with systemd +- Make the /var/run/mongodb directory owned by mongodb + +* Thu Jul 28 2011 Chris Lalancette - 1.8.2-6 +- BZ 725601 - fix the javascript engine to not hang (thanks to Eduardo Habkost) + +* Mon Jul 25 2011 Chris Lalancette - 1.8.2-5 +- Fixes to post server, preun server, and postun server to use systemd + +* Thu Jul 21 2011 Chris Lalancette - 1.8.2-4 +- Update to use systemd init + +* Thu Jul 21 2011 Chris Lalancette - 1.8.2-3 +- Rebuild for boost ABI break + +* Wed Jul 13 2011 Chris Lalancette - 1.8.2-2 +- Make mongodb-devel require boost-devel (BZ 703184) + +* Fri Jul 01 2011 Chris Lalancette - 1.8.2-1 +- Update to upstream 1.8.2 +- Add patch to ignore TERM + +* Fri Jul 01 2011 Chris Lalancette - 1.8.0-3 +- Bump release to build against new boost package + +* Sat Mar 19 2011 Nathaniel McCallum - 1.8.0-2 +- Make mongod bind only to 127.0.0.1 by default + +* Sat Mar 19 2011 Nathaniel McCallum - 1.8.0-1 +- Update to 1.8.0 +- Remove upstreamed nonce patch + +* Wed Feb 16 2011 Nathaniel McCallum - 1.7.5-5 +- Add nonce patch + +* Sun Feb 13 2011 Nathaniel McCallum - 1.7.5-4 +- Manually define to use boost-fs v2 + +* Sat Feb 12 2011 Nathaniel McCallum - 1.7.5-3 +- Disable extra warnings + +* Fri Feb 11 2011 Nathaniel McCallum - 1.7.5-2 +- Disable compilation errors on warnings + +* Fri Feb 11 2011 Nathaniel McCallum - 1.7.5-1 +- Update to 1.7.5 +- Remove CPPFLAGS override +- Added libmongodb package + +* Tue Feb 08 2011 Fedora Release Engineering - 1.6.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Dec 06 2010 Nathaniel McCallum - 1.6.4-3 +- Add post/postun ldconfig... oops! + +* Mon Dec 06 2010 Nathaniel McCallum - 1.6.4-2 +- Enable --sharedclient option, remove static lib + +* Sat Dec 04 2010 Nathaniel McCallum - 1.6.4-1 +- New upstream release + +* Fri Oct 08 2010 Nathaniel McCallum - 1.6.3-4 +- Put -fPIC onto both the build and install scons calls + +* Fri Oct 08 2010 Nathaniel McCallum - 1.6.3-3 +- Define _initddir when it doesn't exist for el5 and others + +* Fri Oct 08 2010 Nathaniel McCallum - 1.6.3-2 +- Added -fPIC build option which was dropped by accident + +* Thu Oct 7 2010 Ionuț C. Arțăriși - 1.6.3-1 +- removed js Requires +- new upstream release +- added more excludearches: sparc s390, s390x and bugzilla pointer + +* Tue Sep 7 2010 Ionuț C. Arțăriși - 1.6.2-2 +- added ExcludeArch for ppc + +* Fri Sep 3 2010 Ionuț C. Arțăriși - 1.6.2-1 +- new upstream release 1.6.2 +- send mongod the USR1 signal when doing logrotate +- use config options when starting the daemon from the initfile +- removed dbpath patch: rely on config +- added pid directory to config file and created the dir in the spec +- made the init script use options from the config file +- changed logpath in mongodb.conf + +* Wed Sep 1 2010 Ionuț C. Arțăriși - 1.6.1-1 +- new upstream release 1.6.1 +- patched SConstruct to allow setting cppflags +- stopped using sed and chmod macros + +* Fri Aug 6 2010 Ionuț C. Arțăriși - 1.6.0-1 +- new upstream release: 1.6.0 +- added -server package +- added new license file to %%docs +- fix spurious permissions and EOF encodings on some files + +* Tue Jun 15 2010 Ionuț C. Arțăriși - 1.4.3-2 +- added explicit js requirement +- changed some names + +* Wed May 26 2010 Ionuț C. Arțăriși - 1.4.3-1 +- updated to 1.4.3 +- added zlib license for util/md5 +- deleted upstream deb/rpm recipes +- made scons not strip binaries +- made naming more consistent in logfile, lockfiles, init scripts etc. +- included manpages and added corresponding license +- added mongodb.conf to sources + +* Fri Oct 2 2009 Ionuț Arțăriși - 1.0.0-3 +- fixed libpath issue for 64bit systems + +* Thu Oct 1 2009 Ionuț Arțăriși - 1.0.0-2 +- added virtual -static package + +* Mon Aug 31 2009 Ionuț Arțăriși - 1.0.0-1 +- Initial release.