Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly support mariadb upgrade from 10.1 to 10.2 #1160

Merged
merged 13 commits into from
Oct 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .buildkite/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ if [ "$(docker ps -aq | wc -l)" -gt 0 ] ; then
docker rm -f $(docker ps -aq)
fi
docker system prune --volumes --force
rm -rf ~/.ddev/TestPkg*

# Update all images that could have changed
docker images | awk '/drud/ {print $1":"$2 }' | xargs -L1 docker pull
Expand Down
2 changes: 1 addition & 1 deletion containers/ddev-dbserver/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ENV MYSQL_PASSWORD db
ENV MYSQL_ROOT_PASSWORD root

# Install mariadb and other packages
RUN apk add --no-cache mariadb mariadb-client mariadb-backup bash tzdata shadow sudo
RUN apk add --no-cache mariadb mariadb-client mariadb-backup mariadb-server-utils bash tzdata shadow sudo
# Remove the installed version as we need to set up our own from scratch

RUN rm -rf /var/lib/mysql/* /etc/mysql
Expand Down
4 changes: 4 additions & 0 deletions containers/ddev-dbserver/files/create_base_db.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ EOF
sudo rm -rf $OUTDIR/*
mariabackup --backup --target-dir=$OUTDIR --user root --password root --socket=$SOCKET

# Initialize with current mariadb_version
my_mariadb_version=$(mysql -V | awk '{sub( /\.[0-9]+-MariaDB,/, ""); print $5 }')
echo $my_mariadb_version >$OUTDIR/db_mariadb_version.txt

if ! kill -s TERM "$pid" || ! wait "$pid"; then
echo >&2 'Mariadb initialization process failed.'
exit 5
Expand Down
47 changes: 44 additions & 3 deletions containers/ddev-dbserver/files/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@ set -x
set -eu
set -o pipefail

SOCKET=/var/tmp/mysql.sock

# Wait for mysql server to be ready.
function serverwait {
for i in {60..0};
do
if mysqladmin ping -uroot --socket=$SOCKET >/dev/null 2>&1; then
return 0
fi
# Test to make sure we got it started in the first place. kill -s 0 just tests to see if process exists.
if ! kill -s 0 $pid 2>/dev/null; then
echo "MariaDB initialization startup failed"
return 2
fi
echo "MariaDB initialization startup process in progress... Try# $i"
sleep 1
done
return 1
}

# If we have a restore_snapshot arg, get the snapshot directory
# otherwise, fail and abort startup
if [ $# = "2" -a "${1:-}" = "restore_snapshot" ] ; then
Expand Down Expand Up @@ -32,12 +52,33 @@ if [ ! -d "/var/lib/mysql/mysql" ]; then
name=$(basename $target)
sudo rm -rf /var/lib/mysql/* /var/lib/mysql/.[a-z]* && sudo chmod -R ugo+w /var/lib/mysql
sudo chmod -R ugo+r $target
mariabackup --prepare --target-dir "$target" --user root --password root --socket=/var/tmp/mysql.sock 2>&1 | tee "/var/log/mariabackup_prepare_$name.log"
mariabackup --copy-back --force-non-empty-directories --target-dir "$target" --user root --password root --socket=/var/tmp/mysql.sock 2>&1 | tee "/var/log/mariabackup_copy_back_$name.log"
ls -lR /var/lib/mysql # DEBUG: Don't forget to remove this
mariabackup --prepare --target-dir "$target" --user root --password root --socket=$SOCKET 2>&1 | tee "/var/log/mariabackup_prepare_$name.log"
mariabackup --copy-back --force-non-empty-directories --target-dir "$target" --user root --password root --socket=$SOCKET 2>&1 | tee "/var/log/mariabackup_copy_back_$name.log"
echo 'Database initialized from $target'
fi

if [ -f /var/lib/mysql/db_mariadb_version.txt ]; then
db_mariadb_version=$(cat /var/lib/mysql/db_mariadb_version.txt)
else
echo "No existing db_mariadb_version.txt was found, so assuming it was mariadb 10.1"
db_mariadb_version="10.1" # Assume it was 10.1; we didn't maintain this before 10.2
fi

my_mariadb_version=$(mysql -V | awk '{sub( /\.[0-9]+-MariaDB,/, ""); print $5 }')
if [ "$my_mariadb_version" != "$db_mariadb_version" ]; then
mysqld --skip-networking --skip-grant-tables --socket=$SOCKET >/tmp/mysqld_temp_startup.log 2>&1 &
pid=$!
if ! serverwait ; then
echo "Failed to get mysqld running to run mysql_upgrade"
exit 103
fi
echo "Running mysql_upgrade because my_mariadb_version=$my_mariadb_version is not the same as db_mariadb_version=$db_mariadb_version"
mysql_upgrade --socket=$SOCKET
kill $pid
fi

# And use the mariadb version we have here.
echo $my_mariadb_version >/var/lib/mysql/db_mariadb_version.txt

echo
echo 'MySQL init process done. Ready for start up.'
Expand Down
2 changes: 1 addition & 1 deletion containers/ddev-dbserver/files/healthcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

set -eo pipefail

mysql -udb -pdb --database=db -e "SHOW DATABASES LIKE 'db';" >/dev/null
mysql --host=127.0.0.1 -udb -pdb --database=db -e "SHOW DATABASES LIKE 'db';" >/dev/null

Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10.2
Binary file modified containers/ddev-dbserver/files/var/tmp/mysqlbase/ib_logfile0
Binary file not shown.
Binary file modified containers/ddev-dbserver/files/var/tmp/mysqlbase/ibdata1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified containers/ddev-dbserver/files/var/tmp/mysqlbase/mysql/db.MYI
Binary file not shown.
Binary file modified containers/ddev-dbserver/files/var/tmp/mysqlbase/mysql/db.frm
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
�localhost root  [��\�76fbb4f64e67 root  [��\
�localhost root  [�r��d6b935362fff root  [�r�
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
uuid = 8d9c7988-bf58-11e8-aac8-0242ac110004
uuid = cb689ed9-c9da-11e8-a322-0242ac110002
name =
tool_name = mariabackup
tool_command = --backup --target-dir=/mysqlbase --user root --password=... root --socket=/var/tmp/mysql.sock
tool_version = 10.2.15-MariaDB
ibbackup_version = 10.2.15-MariaDB
server_version = 10.2.15-MariaDB-log
start_time = 2018-09-23 17:46:07
end_time = 2018-09-23 17:46:08
start_time = 2018-10-07 02:43:37
end_time = 2018-10-07 02:43:38
lock_time = 0
binlog_pos = filename 'on.000002', position '4282389', GTID of the last change '0-1-4723'
innodb_from_lsn = 0
Expand Down
Binary file not shown.
48 changes: 37 additions & 11 deletions containers/ddev-dbserver/test/testserver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fi
function cleanup {
echo "Removing ${CONTAINER_NAME}"
docker rm -f $CONTAINER_NAME 2>/dev/null || true
docker volume rm $VOLUME || true
docker volume rm $VOLUME 2>/dev/null || true
# We use MYTMPDIR for a bogus temp dir since mktemp -d creates a dir
# outside a docker-mountable directory on macOS
rm -rf $outdir/* $outdir/.git*
Expand All @@ -48,13 +48,12 @@ function containercheck {
}


# Just to make sure we're starting with a clean environment.
cleanup

echo "Starting image with database image $IMAGE"
if ! docker run -u "$MOUNTUID:$MOUNTGID" -v $VOLUME:/var/lib/mysql --name=$CONTAINER_NAME -p $HOSTPORT:3306 -d $IMAGE; then
echo "MySQL server start failed with error code $?"
exit 2
exit 101
fi

# Now that we've got a container running, we need to make sure to clean up
Expand All @@ -63,18 +62,18 @@ trap cleanup EXIT

echo "Waiting for database server to become ready..."
if ! containercheck; then
exit 1
exit 102
fi
echo "Connected to mysql server."
echo "DB Server container started up successfully"

# Try basic connection using root user/password.
if ! mysql --user=root --password=root --database=mysql --host=127.0.0.1 --port=$HOSTPORT -e "SELECT 1;"; then
exit 2;
exit 103
fi

# Test to make sure the db user and database are installed properly
if ! mysql -udb -pdb --database=db --host=127.0.0.1 --port=$HOSTPORT -e "SHOW TABLES;"; then
exit 3
exit 104
fi

# Make sure we have the right mysql version and can query it (and have root user setup)
Expand All @@ -89,7 +88,7 @@ then
echo "Version check ok - found '$MYSQL_VERSION'"
else
echo "Expected to see $versionregex. Actual output: $OUTPUT"
exit 4
exit 105
fi

# With the standard config, our collation should be utf8mb4_bin
Expand All @@ -101,11 +100,11 @@ cleanup
# mysqld will ignore world-writeable config file, so we make it ro for sure
if ! docker run -u "$MOUNTUID:$MOUNTGID" -v $VOLUME:/var/lib/mysql -v /$PWD/test/testdata:/mnt/ddev_config:ro --name=$CONTAINER_NAME -p $HOSTPORT:3306 -d $IMAGE; then
echo "MySQL server start failed with error code $?"
exit 3
exit 106
fi

if ! containercheck; then
exit 5
exit 107
fi

# Make sure the custom config is present in the container.
Expand All @@ -122,7 +121,7 @@ rm -rf $outdir/files/var/tmp/*
docker run -u "$MOUNTUID:$MOUNTGID" -t -v /$outdir://mysqlbase --rm --entrypoint=//create_base_db.sh $IMAGE
if [ ! -f "$outdir/ibdata1" ] ; then
echo "Failed to build test starter database for mariadb."
exit 4
exit 108
fi
command="rm -rf $outdir $MYTMPDIR"
if [ $(uname -s) = "Linux" ] ; then
Expand All @@ -131,5 +130,32 @@ else
$command
fi

cleanup


# Start up with a Mariadb 10.1 database and verify that it gets upgraded successfully to 10.2
docker volume rm $VOLUME && docker volume create $VOLUME
# Populate the volume with the contents of our 10.1 tarball. Here it doesn't matter that
# we're putting it in /var/lib/mysql, but it's put there just for clarity of purpose.
docker run -i --rm -v "$VOLUME:/var/lib/mysql" busybox tar -C //var/lib/mysql -zxf - <test/testdata/d6git_basic_mariadb_10_1.tgz
# Now start up the container with the populated volume
if ! docker run -u "$MOUNTUID:$MOUNTGID" -v "$VOLUME:/var/lib/mysql" --name=$CONTAINER_NAME -d $IMAGE; then
echo "MySQL server start failed with error code $?"
exit 109
fi
containercheck
# Here we should show an upgrade happening because this was a 10.1 database
(docker logs $CONTAINER_NAME 2>&1 | grep "Running mysql_upgrade because my_mariadb_version=10.2 is not the same as db_mariadb_version=10.1" >/dev/null 2>&1) || (echo "Failed to find mysql_upgrade clause in docker logs" && exit 4)

docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME
# Now run the container again with the same volume (now upgraded) and make sure we don't have the upgrade action
if ! docker run -u "$MOUNTUID:$MOUNTGID" -v "$VOLUME:/var/lib/mysql" --name=$CONTAINER_NAME -d $IMAGE; then
echo "MySQL server start failed with error code $?"
exit 110
fi
containercheck
(docker logs $CONTAINER_NAME 2>&1 | grep -v "Running mysql_upgrade" >/dev/null 2>&1) || (echo "Found mysql_upgrade clause in docker logs when upgrade should not have happened" && exit 6)


echo "Tests passed"
exit 0
13 changes: 13 additions & 0 deletions docs/users/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ If you get a 404 with "No input file specified" (nginx) or a 403 with "Forbidden
* Misconfigured docroot: If the docroot isn't where the webserver thinks it is, then the webserver won't find the index.php. Look at your .ddev/config.yaml to verify it has a docroot that will lead to the index.php. It should be a relative path from the project root to the directory where the index.php is.
* Docker not mounting your code: If you `ddev ssh` and `ls` and there's nothing there, Docker may not be mounting your code. See [docker installation](./docker_installation.md) for testing docker install. (Is Docker, the drive or directory where your project is must be shared. In Docker Toolbox it *must* be a subdirectory of your home directory unless you [make special accomodations for Docker Toolbox](http://support.divio.com/local-development/docker/how-to-use-a-directory-outside-cusers-with-docker-toolbox-on-windowsdocker-for-windows)).

<a name="old-snapshot"></a>
## Can't restore snapshot created before ddev v1.3

Database snapshot from before v1.3.0 are not compatible with ddev v1.3+ because the mariabackup with MariaDB 10.2 is not compatible with earlier backups. However, if you really need that snapshot and don't have a database dump to run with `ddev import-db`, there's a fairly easy workaround:

1. In .ddev/config.yaml temporarily set `dbimage: drud/ddev-webserver:v1.2.0`.
2. `ddev start` to start with the new version
3. Use `ddev restore-snapshot` to restore the snapshot by name.
4. `ddev rm`
5. Remove the `dbimage` line from .ddev/config.yaml.
6. `ddev start`
7. Make a new snapshot with `ddev snapshot`.

## More Support

[Support options](https://ddev.readthedocs.io/en/latest/#support) has a variety of options.
37 changes: 5 additions & 32 deletions pkg/ddevapp/ddevapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ func (app *DdevApp) SnapshotDatabase(snapshotName string) (string, error) {
}

util.Warning("Creating database snapshot %s", snapshotName)
stdout, stderr, err := app.Exec("db", "bash", "-c", fmt.Sprintf("mariabackup --backup --target-dir=%s --user root --password root --socket=/var/tmp/mysql.sock 2>/var/log/mariadbackup_backup_%s.log", containerSnapshotDir, snapshotName))
stdout, stderr, err := app.Exec("db", "bash", "-c", fmt.Sprintf("mariabackup --backup --target-dir=%s --user root --password root --socket=/var/tmp/mysql.sock 2>/var/log/mariadbackup_backup_%s.log && cp /var/lib/mysql/db_mariadb_version.txt %s", containerSnapshotDir, snapshotName, containerSnapshotDir))
if err != nil {
util.Warning("Failed to create snapshot: %v, stdout=%s, stderr=%s", err, stdout, stderr)
return "", err
Expand All @@ -879,6 +879,9 @@ func (app *DdevApp) RestoreSnapshot(snapshotName string) error {
if !fileutil.FileExists(hostSnapshotDir) {
return fmt.Errorf("Failed to find a snapshot in %s", hostSnapshotDir)
}
if !fileutil.FileExists(filepath.Join(hostSnapshotDir, "db_mariadb_version.txt")) {
return fmt.Errorf("snapshot %s is not compatible with this version of ddev and mariadb. Please use the instructions at %s for a workaround to restore it", snapshotDir, "https://ddev.readthedocs.io/en/latest/users/troubleshooting/#old-snapshot")
}

if app.SiteStatus() == SiteRunning || app.SiteStatus() == SiteStopped {
err := app.Down(false, false)
Expand Down Expand Up @@ -1234,38 +1237,8 @@ func (app *DdevApp) GetProvider() (Provider, error) {
func (app *DdevApp) migrateDbIfRequired() (bool, error) {
dataDir := filepath.Join(util.GetGlobalDdevDir(), app.Name, "mysql")

var err error
if fileutil.FileExists(dataDir) {
// If the dataDir exists, mount it onto ddev-dbserver and run script there that converts to a snapshot
// Then do a restore-snapshot on that snapshot.
// Old datadir can be renamed to .bak
output.UserOut.Print("Migrating bind-mounted database in ~/.ddev to docker-volume mounted database")
if app.SiteStatus() == SiteRunning || app.SiteStatus() == SiteStopped || app.SiteStatus() == "db service stopped" || app.SiteStatus() == "web service stopped" {
err = app.Down(false, false)
}
if err != nil {
return false, fmt.Errorf("failed to stop/remove project %s: %v", app.Name, err)
}

t := time.Now()
snapshotName := fmt.Sprintf("%s_volume_migration_snapshot_%s", app.Name, t.Format("20060102150405"))

out, err := dockerutil.RunSimpleContainer(version.DBImg+":"+version.DBTag, app.Name+"_migrate_volume", nil, []string{"/migrate_file_to_volume.sh", UIDStr, GIDStr}, []string{"SNAPSHOT_NAME=" + snapshotName}, []string{app.GetConfigPath("") + ":" + "/mnt/ddev_config", dataDir + ":/mysqlmount"}, UIDStr)
if err != nil {
return false, fmt.Errorf("failed to run migrate_file_to_volume.sh, err=%v output=%v", err, out)
}
err = os.Rename(dataDir, dataDir+"_migrated.bak")
if err != nil {
return false, fmt.Errorf("Unable to rename %s to %s; you can remove the directory manually if that's ok: %v", dataDir, dataDir+"_migrated.bak", err)
}

// RestoreSnapshot() does a Start(); start doesn't do the migration because dataDir now isn't there.
err = app.RestoreSnapshot(snapshotName)
if err != nil {
return false, fmt.Errorf("failed to restore migration snapshot %s: %v", snapshotName, err)
}
util.Success("Migrated bind-mounted db from %s to docker-volume mounted db.", dataDir)
return true, nil
return false, fmt.Errorf("sorry, it is not possible to migrate bind-mounted databases using ddev v1.3+, please use ddev v1.2 to migrate, or just 'mv ~/.ddev/%s/mysql ~/.ddev/%s/mysql.saved' and then restart and reload with 'ddev import-db'", app.Name, app.Name)
}
return false, nil
}