diff --git a/drush/provision_tasks_extra.drush.inc b/drush/provision_tasks_extra.drush.inc
index 181e2fa..d6ad68f 100644
--- a/drush/provision_tasks_extra.drush.inc
+++ b/drush/provision_tasks_extra.drush.inc
@@ -97,8 +97,15 @@ function drush_provision_tasks_extra_provision_run_cron() {
  */
 function drush_provision_tasks_extra_provision_update() {
   drush_errors_on();
-  provision_backend_invoke(d()->name, 'updatedb');
-  drush_log(dt('Drush updatedb task completed'));
+  $options = d()->options;
+  if (isset($options['entity_updates']) && $options['entity_updates'] && drush_drupal_major_version(d()->root) >= 8) {
+    provision_backend_invoke(d()->name, 'updatedb',  array('--entity-updates'));
+    drush_log(dt('Drush updatedb task completed with --entity-updates'));
+  }
+  else {
+    provision_backend_invoke(d()->name, 'updatedb');
+    drush_log(dt('Drush updatedb task completed w/o --entity-updates'));
+  }
 }
 
 /**
@@ -192,3 +199,23 @@ function drush_provision_tasks_extra_provision_features_revert_all() {
   provision_backend_invoke(d()->name, 'features-revert-all');
   drush_log(dt('All features reverted.'));
 }
+
+/**
+ * Implements drush_HOOK_pre_COMMAND().
+ *
+ * This runs for each tasks during the command
+ *    drush @hostmaster hosting-tasks
+ *
+ * NOTE: This ONLY runs when being called from a hostmaster task.
+ * This hook should ONLY be used to pass Options from a hostmaster task form to
+ * the $task object, or if you don't need this functionality from the command
+ * line.
+ */
+function drush_provision_tasks_extra_pre_hosting_task() {
+  $task = &drush_get_context('HOSTING_TASK');
+
+  // Update.
+  if ($task->ref->type == 'site' && $task->task_type == 'update' && isset($task->task_args['entity_updates'])) {
+    $task->options['entity_updates'] = $task->task_args['entity_updates'];
+  }
+}
diff --git a/fix_ownership/README.md b/fix_ownership/README.md
new file mode 100644
index 0000000..cc81e71
--- /dev/null
+++ b/fix_ownership/README.md
@@ -0,0 +1,13 @@
+FIX OWNERSHIP
+=============
+
+This extension will help Aegir to fix file ownership for Drupal platforms and
+sites.
+
+A full discussion on proper file ownership and permissions in Drupal can be
+found at: https://www.drupal.org/node/244924
+
+On Debian and Ubuntu systems, run `sudo bash scripts/install.sh` in order to
+deploy these scripts, and set up the proper sudoers entry. Other Unixes may
+require slightly different steps to add the sudoers entry.
+
diff --git a/fix_ownership/drush/zz_fix_ownership.drush.inc b/fix_ownership/drush/zz_fix_ownership.drush.inc
new file mode 100644
index 0000000..c9928d2
--- /dev/null
+++ b/fix_ownership/drush/zz_fix_ownership.drush.inc
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @file Drush hooks for the fix_ownership extension.
+ */
+
+/**
+ * Implements drush_HOOK_pre_COMMAND().
+ */
+function drush_zz_fix_ownership_post_provision_verify() {
+  if (d()->type === 'platform') {
+    $success = drush_shell_exec("sudo /usr/local/bin/fix-drupal-platform-ownership.sh --root=%s --script-user=%s --web-group=%s", d()->root, d()->server->script_user, d()->server->web_group);
+  }
+  elseif (d()->type === 'site') {
+    $success = drush_shell_exec("sudo /usr/local/bin/fix-drupal-site-ownership.sh --site-path=%s --script-user=%s --web-group=%s", d()->site_path, d()->server->script_user, d()->server->web_group);
+  }
+  else {
+    return TRUE;
+  }
+
+  $result = drush_shell_exec_output();
+  foreach ($result as $index => $line) {
+    if (!$success) { // Log the entire error as a warning.
+      $line_status = 'warning';
+    }
+    else { // Only log the last line as success.
+      $line_status = $index+1 == count($result) ? 'success' : 'notice';
+    }
+    drush_log($line, $line_status);
+  }
+}
+
+/**
+ * Implements hook_provision_drupal_chgrp_directories_alter().
+ */
+function zz_fix_permissions_provision_drupal_chgrp_directories_alter(&$chgrp, $url) {
+  // We only handle chgrp's for 'verify' tasks, atm.
+  $cmd = drush_get_command();
+  if ($cmd['command'] === 'provision-verify') {
+    foreach ($chgrp as $path => $group) {
+      // Disable Aegir core's chgrp, since we handle it now.
+      $chgrp[$path] = FALSE;
+    }
+  }
+}
+
diff --git a/fix_ownership/fix_ownership.info b/fix_ownership/fix_ownership.info
new file mode 100644
index 0000000..15c259b
--- /dev/null
+++ b/fix_ownership/fix_ownership.info
@@ -0,0 +1,5 @@
+name = Fix Ownership
+description = Fix file ownership of Drupal platforms and sites.
+package = Aegir Extras
+dependencies[] = hosting_site
+core = 7.x
diff --git a/fix_ownership/fix_ownership.module b/fix_ownership/fix_ownership.module
new file mode 100644
index 0000000..6e9e60c
--- /dev/null
+++ b/fix_ownership/fix_ownership.module
@@ -0,0 +1,10 @@
+<?php  # Drupal requires this empty file, in order to recognize this module.
+
+/**
+ * Callback function to execute on enabling this module's feature.
+ *
+ * @see: hosting_example_hosting_feature().
+ */
+function hosting_fix_ownership_feature_enable_callback() {
+  drupal_set_message(t("Fix ownership: Please consult the README of this module to setup the backend part of this module."));
+}
diff --git a/fix_ownership/hosting.feature.fix_ownership.inc b/fix_ownership/hosting.feature.fix_ownership.inc
new file mode 100644
index 0000000..bf515d1
--- /dev/null
+++ b/fix_ownership/hosting.feature.fix_ownership.inc
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @file
+ *   Expose the fix-ownership feature to hostmaster.
+ */
+
+/**
+ * Implements hook_hosting_feature().
+ */
+function hosting_fix_ownership_hosting_feature() {
+  $features['fix_ownership'] = array(
+    'title' => t('Fix Ownership'),
+    'description' => t("Task that fixes file ownership of Drupal platforms and sites."),
+    'status' => HOSTING_FEATURE_DISABLED,
+    'module' => 'fix_ownership',
+    'group' => 'experimental',
+    'enable' => 'hosting_fix_ownership_feature_enable_callback',
+  );
+  return $features;
+}
+
diff --git a/fix_ownership/scripts/fix-drupal-platform-ownership.sh b/fix_ownership/scripts/fix-drupal-platform-ownership.sh
new file mode 100644
index 0000000..ef03d00
--- /dev/null
+++ b/fix_ownership/scripts/fix-drupal-platform-ownership.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# Help menu
+print_help() {
+cat <<-HELP
+This script is used to fix the file ownership of a Drupal platform. You need to
+provide the following arguments:
+
+  --root: Path to the root of your Drupal installation.
+  --script-user: Username of the user to whom you want to give file ownership
+                 (defaults to 'aegir').
+  --web-group: Web server group name (defaults to 'www-data').
+
+Usage: (sudo) ${0##*/} --root=PATH --script-user=USER --web_group=GROUP
+Example: (sudo) ${0##*/} --drupal_path=/var/aegir/platforms/drupal-7.50 --script-user=aegir --web-group=www-data
+HELP
+exit 0
+}
+
+if [ $(id -u) != 0 ]; then
+  printf "Error: You must run this with sudo or root.\n"
+  exit 1
+fi
+
+drupal_root=${1%/}
+script_user=${2:-aegir}
+web_group="${3:-www-data}"
+
+# Parse Command Line Arguments
+while [ "$#" -gt 0 ]; do
+  case "$1" in
+    --root=*)
+        drupal_root="${1#*=}"
+        ;;
+    --script-user=*)
+        script_user="${1#*=}"
+        ;;
+    --web-group=*)
+        web_group="${1#*=}"
+        ;;
+    --help) print_help;;
+    *)
+      printf "Error: Invalid argument, run --help for valid arguments.\n"
+      exit 1
+  esac
+  shift
+done
+
+if [ -z "${drupal_root}" ] || [ ! -d "${drupal_root}/sites" ] || [ ! -f "${drupal_root}/core/modules/system/system.module" ] && [ ! -f "${drupal_root}/modules/system/system.module" ]; then
+  printf "Error: Please provide a valid Drupal root directory.\n"
+  exit 1
+fi
+
+if [ -z "${script_user}" ] || [[ $(id -un "${script_user}" 2> /dev/null) != "${script_user}" ]]; then
+  printf "Error: Please provide a valid user.\n"
+  exit 1
+fi
+
+cd $drupal_root
+
+printf "Changing ownership of all contents of "${drupal_root}":\n user => "${script_user}" \t group => "${web_group}"\n"
+find . \( -path "./sites" -prune \) -exec chown ${script_user}:${web_group} '{}' \+
+chown ${script_user}:${web_group} ./sites/sites.php
+chown -R ${script_user}:${web_group} ./sites/all
+
+echo "Done setting proper ownership of platform files and directories."
diff --git a/fix_ownership/scripts/fix-drupal-site-ownership.sh b/fix_ownership/scripts/fix-drupal-site-ownership.sh
new file mode 100644
index 0000000..c9caa42
--- /dev/null
+++ b/fix_ownership/scripts/fix-drupal-site-ownership.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# Help menu
+print_help() {
+cat <<-HELP
+This script is used to fix the file ownership of a Drupal site. You need to
+provide the following arguments:
+
+  --site-path: Path to the Drupal site directory.
+  --script-user: Username of the user to whom you want to give file ownership
+                 (defaults to 'aegir').
+  --web-group: Web server group name (defaults to 'www-data').
+
+Usage: (sudo) ${0##*/} --site-path=PATH --script-user=USER --web_group=GROUP
+Example: (sudo) ${0##*/} --site-path=/var/aegir/platforms/drupal-7.50/sites/example.com --script-user=aegir --web-group=www-data
+HELP
+exit 0
+}
+
+if [ $(id -u) != 0 ]; then
+  printf "Error: You must run this with sudo or root.\n"
+  exit 1
+fi
+
+site_path=${1%/}
+script_user=${2:-aegir}
+web_group="${3:-www-data}"
+
+# Parse Command Line Arguments
+while [ "$#" -gt 0 ]; do
+  case "$1" in
+    --site-path=*)
+        site_path="${1#*=}"
+        ;;
+    --script-user=*)
+        script_user="${1#*=}"
+        ;;
+    --web-group=*)
+        web_group="${1#*=}"
+        ;;
+    --help) print_help;;
+    *)
+      printf "Error: Invalid argument, run --help for valid arguments.\n"
+      exit 1
+  esac
+  shift
+done
+
+if [ -z "${site_path}" ] || [ ! -f "${site_path}/settings.php" ] ; then
+  printf "Error: Please provide a valid Drupal site directory.\n"
+  exit 1
+fi
+
+if [ -z "${script_user}" ] || [[ $(id -un "${script_user}" 2> /dev/null) != "${script_user}" ]]; then
+  printf "Error: Please provide a valid user.\n"
+  exit 1
+fi
+
+cd $site_path
+
+printf "Changing ownership of all contents of "${site_path}":\n user => "${script_user}" \t group => "${web_group}"\n"
+chown -R ${script_user}:${web_group} .
+
+echo "Done setting proper ownership of site files and directories."
diff --git a/fix_ownership/scripts/install.sh b/fix_ownership/scripts/install.sh
new file mode 100644
index 0000000..8a47ca1
--- /dev/null
+++ b/fix_ownership/scripts/install.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ $(id -u) != 0 ]; then
+  printf "***********************************************\n"
+  printf "* Error: You must run this with sudo or root. *\n"
+  printf "***********************************************\n"
+  exit 1
+fi
+
+DIR=$(dirname "$0")
+SCRIPTS=(fix-drupal-platform-ownership fix-drupal-site-ownership)
+
+for SCRIPT in ${SCRIPTS[@]}; do
+  cp ${DIR}/${SCRIPT}.sh /usr/local/bin
+  chown root:root /usr/local/bin/${SCRIPT}.sh
+  chmod u+x /usr/local/bin/${SCRIPT}.sh
+  echo "aegir ALL=NOPASSWD: /usr/local/bin/${SCRIPT}.sh" > /etc/sudoers.d/${SCRIPT}
+  chmod 0440 /etc/sudoers.d/${SCRIPT}
+done
diff --git a/fix_permissions/README.md b/fix_permissions/README.md
new file mode 100644
index 0000000..a5a9e03
--- /dev/null
+++ b/fix_permissions/README.md
@@ -0,0 +1,13 @@
+FIX PERMISSIONS
+===============
+
+This extension will help Aegir to fix file permissions for Drupal platforms and
+sites.
+
+A full discussion on proper file ownership and permissions in Drupal can be
+found at: https://www.drupal.org/node/244924
+
+On Debian and Ubuntu systems, run `sudo bash scripts/install.sh` in order to
+deploy these scripts, and set up the proper sudoers entry. Other Unixes may
+require slightly different steps to add the sudoers entry.
+
diff --git a/fix_permissions/drush/zz_fix_permissions.drush.inc b/fix_permissions/drush/zz_fix_permissions.drush.inc
new file mode 100644
index 0000000..ce04135
--- /dev/null
+++ b/fix_permissions/drush/zz_fix_permissions.drush.inc
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @file Drush hooks for the fix_permissions extension.
+ */
+
+/**
+ * Implements drush_HOOK_pre_COMMAND().
+ */
+function drush_zz_fix_permissions_post_provision_verify() {
+  if (d()->type === 'platform') {
+    $success = drush_shell_exec("sudo /usr/local/bin/fix-drupal-platform-permissions.sh --root=%s", d()->root);
+  }
+  elseif (d()->type === 'site') {
+    $success = drush_shell_exec("sudo /usr/local/bin/fix-drupal-site-permissions.sh --site-path=%s", d()->site_path);
+  }
+  else {
+    return TRUE;
+  }
+
+  $result = drush_shell_exec_output();
+  foreach ($result as $index => $line) {
+    if (!$success) { // Log the entire error as a warning.
+      $line_status = 'warning';
+    }
+    else { // Only log the last line as success.
+      $line_status = $index+1 == count($result) ? 'success' : 'notice';
+    }
+    drush_log($line, $line_status);
+  }
+}
+
+/**
+ * Implements hook_provision_drupal_create_directories_alter().
+ */
+function zz_fix_permissions_provision_drupal_create_directories_alter(&$chmod, $url) {
+  // We only handle chmod's for 'verify' tasks, atm.
+  $cmd = drush_get_command();
+  if ($cmd['command'] === 'provision-verify') {
+    foreach ($chmod as $path => $perm) {
+      // Disable Aegir core's chmod, since we handle it now.
+      $chmod[$path] = FALSE;
+    }
+  }
+}
+
diff --git a/fix_permissions/fix_permissions.info b/fix_permissions/fix_permissions.info
new file mode 100644
index 0000000..216f6b0
--- /dev/null
+++ b/fix_permissions/fix_permissions.info
@@ -0,0 +1,5 @@
+name = Fix Permissions
+description = Fix file permissions of Drupal platforms and sites.
+package = Aegir Extras
+dependencies[] = hosting_site
+core = 7.x
diff --git a/fix_permissions/fix_permissions.module b/fix_permissions/fix_permissions.module
new file mode 100644
index 0000000..0017396
--- /dev/null
+++ b/fix_permissions/fix_permissions.module
@@ -0,0 +1,10 @@
+<?php  # Drupal requires this empty file, in order to recognize this module.
+
+/**
+ * Callback function to execute on enabling this module's feature.
+ *
+ * @see: hosting_example_hosting_feature().
+ */
+function hosting_fix_permissions_feature_enable_callback() {
+  drupal_set_message(t("Fix Permissions: Please consult the README of this module to setup the backend part of this module."));
+}
diff --git a/fix_permissions/hosting.feature.fix_permissions.inc b/fix_permissions/hosting.feature.fix_permissions.inc
new file mode 100644
index 0000000..32531fe
--- /dev/null
+++ b/fix_permissions/hosting.feature.fix_permissions.inc
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @file
+ *   Expose the fix-permissions feature to hostmaster.
+ */
+
+/**
+ * Implements hook_hosting_feature().
+ */
+function hosting_fix_permissions_hosting_feature() {
+  $features['fix_permissions'] = array(
+    'title' => t('Fix Permissions'),
+    'description' => t("Task that fixes file permissions of Drupal platforms and sites."),
+    'status' => HOSTING_FEATURE_DISABLED,
+    'module' => 'fix_permissions',
+    'group' => 'experimental',
+    'enable' => 'hosting_fix_permission_feature_enable_callback',
+  );
+  return $features;
+}
+
diff --git a/fix_permissions/scripts/fix-drupal-platform-permissions.sh b/fix_permissions/scripts/fix-drupal-platform-permissions.sh
new file mode 100644
index 0000000..14a6977
--- /dev/null
+++ b/fix_permissions/scripts/fix-drupal-platform-permissions.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# Help menu
+print_help() {
+cat <<-HELP
+This script is used to fix the file permissions of a Drupal platform. You need
+to provide the following argument:
+
+  --root: Path to the root of your Drupal installation.
+
+Usage: (sudo) ${0##*/} --root=PATH
+Example: (sudo) ${0##*/} --drupal_path=/var/aegir/platforms/drupal-7.50
+HELP
+exit 0
+}
+
+if [ $(id -u) != 0 ]; then
+  printf "Error: You must run this with sudo or root.\n"
+  exit 1
+fi
+
+drupal_root=${1%/}
+
+# Parse Command Line Arguments
+while [ "$#" -gt 0 ]; do
+  case "$1" in
+    --root=*)
+        drupal_root="${1#*=}"
+        ;;
+    --help) print_help;;
+    *)
+      printf "Error: Invalid argument, run --help for valid arguments.\n"
+      exit 1
+  esac
+  shift
+done
+
+if [ -z "${drupal_root}" ] || [ ! -d "${drupal_root}/sites" ] || [ ! -f "${drupal_root}/core/modules/system/system.module" ] && [ ! -f "${drupal_root}/modules/system/system.module" ]; then
+  printf "Error: Please provide a valid Drupal root directory.\n"
+  exit 1
+fi
+
+cd $drupal_root
+
+printf "Changing permissions of all directories inside "${drupal_root}" to "750"...\n"
+find . \( -path "./sites" -prune \) -type d -exec chmod 750 '{}' \+
+find ./sites/all/ -type d -exec chmod 750 '{}' \+
+chmod 750 ./sites/all/
+
+printf "Changing permissions of all files inside "${drupal_root}" to "640"...\n"
+find . \( -path "./sites" -prune \) -type f -exec chmod 640 '{}' \+
+find ./sites/all/ -type f -exec chmod 640 '{}' \+
+
+echo "Done setting proper permissions on platform files and directories."
diff --git a/fix_permissions/scripts/fix-drupal-site-permissions.sh b/fix_permissions/scripts/fix-drupal-site-permissions.sh
new file mode 100644
index 0000000..3e4177c
--- /dev/null
+++ b/fix_permissions/scripts/fix-drupal-site-permissions.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+# Help menu
+print_help() {
+cat <<-HELP
+This script is used to fix the file permissions of a Drupal site. You need
+to provide the following argument:
+
+  --site-path: Path to the Drupal site's directory.
+
+Usage: (sudo) ${0##*/} --site-path=PATH
+Example: (sudo) ${0##*/} --site-path=/var/aegir/platforms/drupal-7.50/sites/example.com
+HELP
+exit 0
+}
+
+if [ $(id -u) != 0 ]; then
+  printf "Error: You must run this with sudo or root.\n"
+  exit 1
+fi
+
+site_path=${1%/}
+
+# Parse Command Line Arguments
+while [ "$#" -gt 0 ]; do
+  case "$1" in
+    --site-path=*)
+        site_path="${1#*=}"
+        ;;
+    --help) print_help;;
+    *)
+      printf "Error: Invalid argument, run --help for valid arguments.\n"
+      exit 1
+  esac
+  shift
+done
+
+if [ -z "${site_path}" ] || [ ! -f "${site_path}/settings.php" ] ; then
+  printf "Error: Please provide a valid Drupal site directory.\n"
+  exit 1
+fi
+
+cd $site_path
+
+printf "Changing permissions of all directories inside \"${site_path}\" to \"750\"...\n"
+find . \( -path "./files" -o -path "./private" -prune \) -type d -exec chmod 750 '{}' \+
+
+printf "Changing permissions of all files inside \"${site_path}\" to \"640\"...\n"
+find . \( -path "./files" -o -path "./private" -prune \) -type f -exec chmod 640 '{}' \+
+
+printf "Changing permissions of \"files\" directory in \"${site_path}/sites\" to \"770\"...\n"
+chmod 770 files
+
+printf "Changing permissions of all files inside \"files\" directory in \"${site_path}\" to \"660\"...\n"
+find ./files -type f -exec chmod 660 '{}' \+
+
+printf "Changing permissions of all directories inside \"files\" directory in \"${site_path}\" to \"770\"...\n"
+find ./files -type d -exec chmod 770 '{}' \+
+
+printf "Changing permissions of \"private\" directory in \"${site_path}/sites\" to \"770\"...\n"
+chmod 770 private
+
+printf "Changing permissions of all files inside \"private\" directory in \"${site_path}\" to \"660\"...\n"
+find ./private -type f -exec chmod 660 '{}' \+
+
+printf "Changing permissions of all directories inside \"private\" directory in \"${site_path}\" to \"770\"...\n"
+find ./private -type d -exec chmod 770 '{}' \+
+
+echo "Done setting proper permissions on site files and directories."
diff --git a/fix_permissions/scripts/install.sh b/fix_permissions/scripts/install.sh
new file mode 100644
index 0000000..ad2e6ce
--- /dev/null
+++ b/fix_permissions/scripts/install.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ $(id -u) != 0 ]; then
+  printf "***********************************************\n"
+  printf "* Error: You must run this with sudo or root. *\n"
+  printf "***********************************************\n"
+  exit 1
+fi
+
+DIR=$(dirname "$0")
+SCRIPTS=(fix-drupal-platform-permissions fix-drupal-site-permissions)
+
+for SCRIPT in ${SCRIPTS[@]}; do
+  cp ${DIR}/${SCRIPT}.sh /usr/local/bin
+  chown root:root /usr/local/bin/${SCRIPT}.sh
+  chmod u+x /usr/local/bin/${SCRIPT}.sh
+  echo "aegir ALL=NOPASSWD: /usr/local/bin/${SCRIPT}.sh" > /etc/sudoers.d/${SCRIPT}
+  chmod 0440 /etc/sudoers.d/${SCRIPT}
+done
diff --git a/hosting_reinstall/README.txt b/hosting_reinstall/README.txt
new file mode 100644
index 0000000..9d0166a
--- /dev/null
+++ b/hosting_reinstall/README.txt
@@ -0,0 +1,13 @@
+The Hosting Reinstall module provides a Drush command and Hosting task
+so that you can easily reinstall sites in Aegir.
+
+It was originally written for the purpose of testing Drupal install profiles.
+It is also useful for development feature/git-based workflows.
+
+Hosting Reinstall was originally written Stuart Clark and maintained by Stuart
+Clark (deciphered) of Realityloop Pty Ltd.
+- http://www.realityloop.com
+- http://twitter.com/realityloop
+
+The port to Aegir 3 and its on-going maintenance is by Christopher Gervais
+(ergonlogic).
diff --git a/hosting_reinstall/drush/provision_site_reinstall.drush.inc b/hosting_reinstall/drush/provision_site_reinstall.drush.inc
new file mode 100644
index 0000000..ff3a1bd
--- /dev/null
+++ b/hosting_reinstall/drush/provision_site_reinstall.drush.inc
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @file
+ */
+
+/**
+ * Implements hook_drush_command().
+ */
+function provision_site_reinstall_drush_command() {
+  $items = array();
+
+  $items['provision-reinstall'] = array(
+    'description' => 'Reinstall a site.',
+    'examples' => array(
+      'drush @site provision-reinstall' => 'Invokes Provision Delete and Install tasks to simulate a site reinstall.',
+    ),
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT
+  );
+
+  return $items;
+}
+
+/**
+ * Drush Provision Reinstall task callback.
+ *
+ * Invokes Provision Delete and Install tasks to simulate a site reinstall.
+ */
+function drush_provision_site_reinstall_provision_reinstall() {
+  // Preserve our existing Aegir site context data, since it gets deleted along
+  // with ths site.
+  $alias_name = d()->name;
+  $options = provision_sitealias_get_record($alias_name);
+
+  provision_backend_invoke($alias_name, "provision-delete");
+
+  // Recreate our Aegir site context.
+  provision_backend_invoke("@hostmaster", "provision-save", array($alias_name), $options);
+
+  provision_backend_invoke($alias_name, "provision-install");
+}
diff --git a/hosting_reinstall/hosting.feature.reinstall.inc b/hosting_reinstall/hosting.feature.reinstall.inc
new file mode 100644
index 0000000..e7ce30f
--- /dev/null
+++ b/hosting_reinstall/hosting.feature.reinstall.inc
@@ -0,0 +1,22 @@
+<?php
+/**
+ * @file
+ * Expose the reinstall feature to hostmaster.
+ */
+
+/**
+ * Implements hook_hosting_feature().
+ */
+function hosting_reinstall_hosting_feature() {
+  $features = array();
+
+  $features['reinstall'] = array(
+    'title' => t('Site reinstall'),
+    'description' => t('Provides a Hosting task to reinstall sites.'),
+    'status' => HOSTING_FEATURE_DISABLED,
+    'module' => 'hosting_site_reinstall',
+    'group' => 'experimental',
+  );
+
+  return $features;
+}
diff --git a/hosting_reinstall/hosting_site_reinstall.info b/hosting_reinstall/hosting_site_reinstall.info
new file mode 100644
index 0000000..defeea5
--- /dev/null
+++ b/hosting_reinstall/hosting_site_reinstall.info
@@ -0,0 +1,5 @@
+name = Hosting Reinstall
+description = Provides a Hosting task to reinstall sites.
+package = Hosting Development Tools
+dependencies[] = hosting_site
+core = 7.x
diff --git a/hosting_reinstall/hosting_site_reinstall.module b/hosting_reinstall/hosting_site_reinstall.module
new file mode 100644
index 0000000..e52f94b
--- /dev/null
+++ b/hosting_reinstall/hosting_site_reinstall.module
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @file
+ * Contains core functionality for the Hosting Reinstall module.
+ */
+
+/**
+ * Implements hook_hosting_tasks().
+ */
+function hosting_site_reinstall_hosting_tasks() {
+  $tasks = array();
+
+  $tasks['site']['reinstall'] = array(
+    'title' => t('Reinstall'),
+    'description' => t('Reinstall the site.'),
+    'dialog' => TRUE,
+  );
+
+  return $tasks;
+}
diff --git a/hosting_sync/hosting_sync.tasks.inc b/hosting_sync/hosting_sync.tasks.inc
index 4c9c2f5..4fab834 100644
--- a/hosting_sync/hosting_sync.tasks.inc
+++ b/hosting_sync/hosting_sync.tasks.inc
@@ -60,17 +60,6 @@ function hosting_sync_hosting_task_menu_access($node, $task) {
 }
 
 /**
- * Helper to determine if a particular site has a module installed.
- */
-function _hosting_sync_site_has_module($node, $module) {
-  $package = hosting_package_instance_load(array('rid' => $node->nid, 'p.short_name' => $module));
-  if (!is_object($package)) {
-    return FALSE;
-  }
-  return $package->status;
-}
-
-/**
  * Helper to get the list of sites.
  *
  * Similar to hosting_get_sites_by_status() but it calls db_rewrite_sql() so that the
@@ -311,7 +300,7 @@ function hosting_task_sync_form($node) {
     '#type' => 'checkbox',
     '#default_value' => 1,
   );
-  if (_hosting_sync_site_has_module($node, 'features')) {
+  if (_hosting_package_site_has_module($node, 'features')) {
     $form['features_revert_all'] = array(
       '#title' => t('Revert all features'),
       '#type' => 'checkbox',
diff --git a/hosting_tasks_extra.module b/hosting_tasks_extra.module
index 3cbd01d..4e165db 100644
--- a/hosting_tasks_extra.module
+++ b/hosting_tasks_extra.module
@@ -133,6 +133,15 @@ function hosting_task_update_form($node) {
   $form['operations'] = array(
     '#value' => $value,
   );
+
+  $platform_node = node_load($node->platform);
+  $core_major_version = $platform_node->release->version[0];
+  if ($core_major_version >= 8) {
+    $form['entity_updates'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Run automatic entity schema updates at the end of any update hooks.'),
+    );
+  }
   return $form;
 }
 
@@ -149,3 +158,15 @@ function hosting_tasks_extra_hosting_task_update_ops() {
     ),
   );
 }
+
+/**
+ * Implements hosting_task_TASK_TYPE_form_validate().
+ */
+function hosting_task_features_revert_all_form_validate($form, &$form_state) {
+  $site = node_load($form_state['values']['nid']);
+
+  // Check if the features module is enabled.
+  if (!_hosting_package_site_has_module($site, 'features')) {
+    form_set_error('nid', t('You need to enable the Features module on this site and then clear the Drush cache before running this task.'));
+  }
+}
