diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalRunForm.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalRunForm.php
new file mode 100644
index 0000000..3218a42
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Form/MigrateDrupalRunForm.php
@@ -0,0 +1,142 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Form\MigrateDrupalRun.
+ */
+
+namespace Drupal\migrate_drupal\Form;
+
+use Drupal\Component\Utility\MapArray;
+use Drupal\Core\Database\Database;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Form\FormBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+class MigrateDrupalRunForm extends FormBase {
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $storage;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'migrate_drupal_run_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    // The multistep is for testing only. The final version will run a fixed
+    // set of migrations.
+    if (isset($form_state['database'])) {
+      Database::addConnectionInfo('migrate', 'default', $form_state['database']);
+      $migrations = $this->storage()->loadMultiple();
+      $form['migrations'] = array(
+        '#type' => 'checkboxes',
+        '#options' => MapArray::copyValuesToKeys(array_keys($migrations)),
+      );
+    }
+    else {
+      $form['db_url'] = array(
+        '#type' => 'textfield',
+        '#title' => $this->t('Database URL from D6'),
+        '#size' => 40,
+      );
+    }
+    $form['submit'] = array(
+      '#type' => 'submit',
+      '#value' => $this->t('Submit'),
+    );
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    if (isset($form_state['values']['db_url'])) {
+      $form_state['rebuild'] = TRUE;
+      $form_state['database'] = $this->convertDbUrl($form_state['values']['db_url']);
+    }
+    else {
+      $migration_ids = array_keys(array_filter($form_state['values']['migrations']));
+      $batch = array(
+        'title' => t('Running migrations'),
+        'operations' => array(
+          array(array('Drupal\migrate_drupal\MigrateDrupalRunBatch', 'run'), array($migration_ids, $form_state['database'])),
+        ),
+        'finished' => array('Drupal\migrate_drupal\MigrateDrupalRunBatch', 'finished'),
+        'progress_message' => '',
+        'init_message' => t('Processing migration @num of @max.', array('@num' => '1', '@max' => count($migration_ids))),
+      );
+      $this->batchSet($batch);
+    }
+  }
+
+  /**
+   * Converts a D6 database URL to a new style DB configuration array.
+   *
+   * @param $db_url
+   *  The D6 database url.
+   * @return array
+   *   The new style database array.
+   */
+  protected function convertDbUrl($db_url) {
+    $url = parse_url($db_url);
+    // Fill in defaults to prevent notices.
+    $url += array(
+      'driver' => NULL,
+      'user' => NULL,
+      'pass' => NULL,
+      'host' => NULL,
+      'port' => NULL,
+      'path' => NULL,
+      'database' => NULL,
+    );
+    $url = (object) array_map('urldecode', $url);
+    return array(
+      'driver' => $url->scheme == 'mysqli' ? 'mysql' : $url->scheme,
+      'username' => $url->user,
+      'password' => $url->pass,
+      'port' => $url->port,
+      'host' => $url->host,
+
+      'database' => substr($url->path, 1),
+    );
+  }
+
+  /**
+   * Set a batch.
+   *
+   * @param $batch
+   */
+  protected function batchSet($batch) {
+    batch_set($batch);
+  }
+
+  /**
+   * @return EntityStorageInterface
+   */
+  protected function storage() {
+    if (!isset($this->storage)) {
+      $this->storage = \Drupal::entityManager()->getStorage('migration');
+    }
+    return $this->storage;
+  }
+
+  /**
+   * Returns the properties to be serialized
+   *
+   * @return array
+   */
+  public function __sleep() {
+    // This apparently contains a PDOStatement somewhere.
+    unset($this->storage);
+    return parent::__sleep();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockPluginId.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockPluginId.php
new file mode 100644
index 0000000..3f205b2
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockPluginId.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\BlockAggregator.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateSkipRowException;
+use Drupal\migrate\Plugin\MigratePluginManager;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_block_plugin_id"
+ * )
+ */
+class BlockPluginId extends ProcessPluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * @var \Drupal\migrate\Plugin\MigratePluginManager
+   */
+  protected $processPluginManager;
+
+  /**
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $customBlockStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, MigratePluginManager $process_plugin_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->customBlockStorage = $storage;
+    $this->migration = $migration;
+    $this->processPluginManager = $process_plugin_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
+    $entity_manager = $container->get('entity.manager');
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $entity_manager->getDefinition('custom_block') ? $entity_manager->getStorage('custom_block') : NULL,
+      $container->get('plugin.manager.migrate.process')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the block plugin id.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value)) {
+      list($module, $delta) = $value;
+      switch ($module) {
+        case 'aggregator':
+          list($type, $id) = explode('-', $delta);
+          if ($type == 'category') {
+            // @TODO skip row.
+            // throw new MigrateSkipRowException();
+          }
+          $value = 'aggregator_feed_block';
+          break;
+        case 'menu':
+          $value = "system_menu_block:$delta";
+          break;
+        case 'block':
+          if ($this->customBlockStorage) {
+            $block_ids = $this->processPluginManager
+              ->createInstance('migration', array('migration' => 'd6_custom_block'), $this->migration)
+              ->transform($delta, $migrate_executable, $row, $destination_property);
+            $value = 'custom_block:' . $this->customBlockStorage->load($block_ids[0])->uuid();
+          }
+          else {
+            throw new MigrateSkipRowException();
+          }
+          break;
+        default:
+          throw new MigrateSkipRowException();
+      }
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockSettings.php
new file mode 100644
index 0000000..c039d68
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/BlockSettings.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @file
+ * Contains
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_block_settings"
+ * )
+ */
+class BlockSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the block configuration.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($plugin, $delta, $old_settings) = $value;
+    $settings = array();
+    switch ($plugin) {
+      case 'aggregator_feed_block':
+        list(, $id) = explode('-', $delta);
+        $settings['block_count'] = $old_settings['aggregator']['item_count'];
+        $settings['feed'] = $id;
+        break;
+      case 'book_navigation':
+        $settings['block_mode'] = $old_settings['book']['block_mode'];
+        break;
+      case 'forum_active_block':
+      case 'forum_new_block':
+        $settings['block_count'] = $old_settings['forum']['block_num'];
+        break;
+      case 'statistics_popular_block':
+        $settings['top_day_num'] = $old_settings['statistics']['statistics_block_top_day_num'];
+        $settings['top_all_num'] = $old_settings['statistics']['statistics_block_top_all_num'];
+        $settings['top_last_num'] = $old_settings['statistics']['statistics_block_top_last_num'];
+        break;
+      case 'views_block:who_s_new-block_1':
+        $settings['items_per_page'] = $old_settings['user']['block_whois_new_count'];
+        break;
+      case 'views_block:who_s_online-who_s_online_block':
+        $settings['items_per_page'] = $old_settings['user']['max_list_count'];
+        break;
+    }
+    return $settings;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldFormatterSettingsDefaults.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldFormatterSettingsDefaults.php
new file mode 100644
index 0000000..77f41eb
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldFormatterSettingsDefaults.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\process\d6\FieldSettingsDefaults.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+
+/**
+ * Set the default field settings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_formatter_settings_defaults"
+ * )
+ */
+class FieldFormatterSettingsDefaults extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set field formatter settings when the map didn't map: for date
+   * formatters, the fallback format, for everything else, empty array.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    // If the 1 index is set then the map missed.
+    if (isset($value[1])) {
+      $value = $row->getSourceProperty('module') == 'date' ? array('format_type' => 'fallback') : array();
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldIdGenerator.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldIdGenerator.php
new file mode 100644
index 0000000..039562b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldIdGenerator.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FieldIdGenerator.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Generate the file name for field config entities.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_id_generator"
+ * )
+ */
+class FieldIdGenerator extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    return $value[0] . "." . $value[1];
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceDefaults.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceDefaults.php
new file mode 100644
index 0000000..141eb28
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceDefaults.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\migrate_drupal\Plugin\migrate\d6\FieldInstanceDefaults
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_field_instance_defaults"
+ * )
+ */
+class FieldInstanceDefaults extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the field instance defaults.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($widget_type, $widget_settings) = $value;
+    $default = array();
+
+    switch ($widget_type) {
+      case 'text_textfield':
+      case 'number':
+      case 'phone_textfield':
+        $default['value'] = $widget_settings['default_value'][0]['value'];
+        break;
+
+      case 'imagefield_widget':
+        // @todo, load the image and populate the defaults.
+        // $default['default_image'] = $widget_settings['default_image'];
+        break;
+
+      case 'date_select':
+        $default['value'] = $widget_settings['default_value'];
+        break;
+
+      case 'email_textfield':
+        $default['value'] = $widget_settings['default_value'][0]['email'];
+        break;
+
+      case 'link':
+        $default['title'] = $widget_settings['default_value'][0]['title'];
+        $default['url'] = $widget_settings['default_value'][0]['url'];
+        break;
+    }
+    return array($default);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceSettings.php
new file mode 100644
index 0000000..7f16cef
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceSettings.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\migrate_drupal\Plugin\migrate\d6\FieldInstanceSettings
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * @MigrateProcessPlugin(
+ *   id = "d6_field_instance_settings"
+ * )
+ */
+class FieldInstanceSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Set the field instance defaults.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($widget_type, $widget_settings, $field_settings) = $value;
+    $settings = array();
+    switch ($widget_type) {
+      case 'text_textfield':
+        $settings['text_processing'] = $field_settings['text_processing'];
+        break;
+
+      case 'number':
+        $settings['min'] = $field_settings['min'];
+        $settings['max'] = $field_settings['max'];
+        $settings['prefix'] = $field_settings['prefix'];
+        $settings['suffix'] = $field_settings['suffix'];
+        break;
+
+      case 'link':
+        // $settings['url'] = $widget_settings['default_value'][0]['url'];
+        // D6 has optional, required, value and none. D8 only has disabled (0)
+        // optional (1) and required (2).
+        $map = array('disabled' => 0, 'optional' => 1, 'required' => 2);
+        $settings['title'] = $map[$field_settings['title']];
+        break;
+
+      case 'filefield_widget':
+        $settings['file_extensions'] = $widget_settings['file_extensions'];
+        $settings['file_directory'] = $widget_settings['file_path'];
+        $settings['description_field'] = $field_settings['description_field'];
+        $settings['max_filesize'] = $this->convertSizeUnit($widget_settings['max_filesize_per_file']);
+        break;
+
+      case 'imagefield_widget':
+        $settings['file_extensions'] = $widget_settings['file_extensions'];
+        $settings['file_directory'] = 'public://';
+        $settings['max_filesize'] = $this->convertSizeUnit($widget_settings['max_filesize_per_file']);
+        $settings['alt_field'] = $widget_settings['alt'];
+        $settings['alt_field_required'] = $widget_settings['custom_alt'];
+        $settings['title_field'] = $widget_settings['title'];
+        $settings['title_field_required'] = $widget_settings['custom_title'];
+        $settings['max_resolution'] = $widget_settings['max_resolution'];
+        $settings['min_resolution'] = $widget_settings['min_resolution'];
+        break;
+
+    }
+    return $settings;
+  }
+
+  /**
+   * Convert file size strings into their D8 format.
+   *
+   * D6 stores file size using a "K" for kilobytes and "M" for megabytes where
+   * as D8 uses "KB" and "MB" respectively.
+   *
+   * @param string $size_string
+   *   The size string, eg 10M
+   *
+   * @return string
+   *   The D8 version of the size string.
+   */
+  protected function convertSizeUnit($size_string) {
+    $size_unit = substr($size_string, strlen($size_string) - 1);
+    if ($size_unit == "M" || $size_unit == "K") {
+      return $size_string . "B";
+    }
+    return $size_string;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceWidgetSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceWidgetSettings.php
new file mode 100644
index 0000000..4352483
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldInstanceWidgetSettings.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FieldInstanceWidgetSettings
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Get the field instance widget settings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_instance_widget_settings"
+ * )
+ */
+class FieldInstanceWidgetSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Get the field instance default/mapped widget settings.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($widget_type, $widget_settings) = $value;
+    return $this->getSettings($widget_type, $widget_settings);
+  }
+
+  /**
+   * Merge the default D8 and specified D6 settings for a widget type.
+   *
+   * @param string $widget_type
+   *   The widget type.
+   * @param array $widget_settings
+   *   The widget settings from D6 for this widget.
+   *
+   * @return array
+   *   A valid array of settings.
+   */
+  public function getSettings($widget_type, $widget_settings) {
+    $progress = isset($widget_settings['progress_indicator']) ? $widget_settings['progress_indicator'] : 'throbber';
+    $size = isset($widget_settings['size']) ? $widget_settings['size'] : 60;
+    $rows = isset($widget_settings['rows']) ? $widget_settings['rows'] : 5;
+
+    $settings = array(
+      'text_textfield' => array(
+        'size' => $size,
+        'placeholder' => '',
+      ),
+      'text_textarea' => array(
+        'rows' => $rows,
+        'placeholder' => '',
+      ),
+      'number' => array(
+        'placeholder' => '',
+      ),
+      'email_textfield' => array(
+        'placeholder' => '',
+      ),
+      'link' => array(
+        'placeholder_uri' => '',
+        'placeholder_title' => '',
+      ),
+      'filefield_widget' => array(
+        'progress_indicator' => $progress,
+      ),
+      'imagefield_widget' => array(
+        'progress_indicator' => $progress,
+        'preview_image_style' => 'thumbnail',
+      ),
+      'optionwidgets_onoff' => array(
+        'display_label' => FALSE,
+      ),
+      'phone_textfield' => array(
+        'placeholder' => '',
+      ),
+    );
+
+    return isset($settings[$widget_type]) ? $settings[$widget_type] : array();
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldSettings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldSettings.php
new file mode 100644
index 0000000..e73bab0
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldSettings.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FieldSettings
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Get the field settings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_settings"
+ * )
+ */
+class FieldSettings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Get the field default/mapped settings.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    list($field_type, $global_settings, $widget_settings) = $value;
+    return $this->getSettings($field_type, $global_settings, $widget_settings);
+  }
+
+  /**
+   * Merge the default D8 and specified D6 settings.
+   *
+   * @param string $field_type
+   *   The field type.
+   * @param array $global_settings
+   *   The field settings.
+   * @param array $widget_settings
+   *   The widget settings needed for some settings.
+   *
+   * @return array
+   *   A valid array of settings.
+   */
+  public function getSettings($field_type, $global_settings, $widget_settings) {
+    $image_label = isset($widget_settings['alt']) ? $widget_settings['alt'] : '';
+    $title_label = isset($widget_settings['title']) ? $widget_settings['title'] : '';
+    $max_length = isset($global_settings['max_length']) ? $global_settings['max_length'] : '';
+    $max_length = empty($max_length) ? 255 : $max_length;
+
+    $settings = array(
+      'text' => array(
+        'max_length' => $max_length,
+      ),
+      'image' => array(
+        'column_groups' => array(
+          'alt' => array('label' => $image_label),
+          'title' => array('label' => $title_label),
+        ),
+      ),
+      'datetime' => array('datetime_type' => 'datetime'),
+    );
+
+
+    return isset($settings[$field_type]) ? $settings[$field_type] : array();
+  }
+}
\ No newline at end of file
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldTypeDefaults.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldTypeDefaults.php
new file mode 100644
index 0000000..1d6ab93
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FieldTypeDefaults.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\process\d6\FieldTypeDefaults.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+
+/**
+ * Gives us a change to set per field defaults.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "field_type_defaults"
+ * )
+ */
+class FieldTypeDefaults extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    if (is_array($value)) {
+      if ($row->getSourceProperty('module') == 'date') {
+        $value = 'datetime_default';
+      }
+      else {
+        throw new MigrateException(sprintf('Lookup failed for %s', var_export($value, TRUE)));
+      }
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileImageHandler.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileImageHandler.php
new file mode 100644
index 0000000..b188bee
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileImageHandler.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\system_update_7000.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateSkipRowException;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Decide if it's an image or a file when coming from a D6 filefield.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "file_image_handler"
+ * )
+ */
+class FileImageHandler extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+
+    // If it's an array then the map missed.
+    if (is_array($value)) {
+
+      // Filefields in D6 have no way to tell if it's an image or file so we
+      // have to look at the widget type as well.
+      if ($row->getSourceProperty('module') == 'filefield') {
+        $widget_type = $row->getSourceProperty('widget_type');
+        $value = $widget_type == "imagefield_widget" ? "image" : "file";
+      }
+      else {
+        throw new MigrateSkipRowException();
+      }
+    }
+
+    return $value;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileUri.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileUri.php
new file mode 100644
index 0000000..5383d56
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FileUri.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\FileUri.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\process\d6;
+
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Process the file url into a D8 compatible URL.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "file_uri"
+ * )
+ */
+class FileUri extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+
+    list($filepath, $file_directory_path, $is_public) = $value;
+
+    // Strip the files path from the uri instead of using basename
+    // so any additional folders in the path are preserved.
+    $uri = preg_replace('/^' . preg_quote($file_directory_path, '/') . '/', '', $filepath);
+
+    return $is_public ? "public://$uri" : "private://$uri";
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php
index 07608b6..fc9a4af 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/FilterFormatPermission.php
@@ -64,9 +64,9 @@ public function transform($value, MigrateExecutable $migrate_executable, Row $ro
     $rid = $row->getSourceProperty('rid');
     if ($formats = $row->getSourceProperty("filter_permissions:$rid")) {
       foreach ($formats as $format) {
-        $new_id = $this->migrationPlugin->transform(array($format), $migrate_executable, $row, $destination_property);
+        $new_id = $this->migrationPlugin->transform($format, $migrate_executable, $row, $destination_property);
         if ($new_id) {
-          $value[] = 'use text format ' . $new_id[0];
+          $value[] = 'use text format ' . $new_id;
         }
       }
     }
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/SearchConfigurationRankings.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/SearchConfigurationRankings.php
new file mode 100644
index 0000000..1fdb59f
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/SearchConfigurationRankings.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\SearchPage.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Row;
+
+/**
+ * Generate configuration rankings.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "d6_search_configuration_rankings"
+ * )
+ */
+class SearchConfigurationRankings extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   *
+   * Generate the configuration rankings.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $return = array();
+    foreach ($row->getSource() as $name => $rank) {
+      if (substr($name, 0, 10) == 'node_rank_' && $rank) {
+        $return[substr($name, 10)] = $rank;
+      }
+    }
+    return $return;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserPicture.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserPicture.php
new file mode 100644
index 0000000..1328d2d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserPicture.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\UserPicture.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\Plugin\MigrateProcessInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Split the 'administer nodes' permission from 'access content overview'.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "d6_user_picture"
+ * )
+ */
+class UserPicture extends ProcessPluginBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The migration plugin.
+   *
+   * @var \Drupal\migrate\Plugin\MigrateProcessInterface
+   */
+  protected $migrationPlugin;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, MigrationInterface $migration, MigrateProcessInterface $migration_plugin) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->migration = $migration;
+    $this->migrationPlugin = $migration_plugin;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $migration,
+      $container->get('plugin.manager.migrate.process')->createInstance('migration', array('migration' => 'd6_user_picture_file'), $migration)
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Split the 'administer nodes' permission from 'access content overview'.
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    return $row->getSourceProperty('picture') ? $this->migrationPlugin->transform($value, $migrate_executable, $row, $destination_property) : NULL;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate7002.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate7002.php
new file mode 100644
index 0000000..5deb1fe
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/process/d6/UserUpdate7002.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\Process\d6\UserUpdate7002.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\Process\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * Converts user time zones from time zone offsets to time zone names.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "user_update_7002"
+ * )
+ */
+class UserUpdate7002 extends ProcessPluginBase {
+
+  /**
+   * System timezones.
+   *
+   * @var array
+   */
+  protected static $timezones;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    if (!isset(static::$timezones)) {
+      static::$timezones = system_time_zones();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutable $migrate_executable, Row $row, $destination_property) {
+    $timezone = NULL;
+
+    if ($row->hasSourceProperty('timezone_name')) {
+      if (isset(static::$timezones[$row->getSourceProperty('timezone_name')])) {
+        $timezone = $row->getSourceProperty('timezone_name');
+      }
+    }
+    if (!$timezone && $row->hasSourceProperty('event_timezone')) {
+      if (isset(static::$timezones[$row->getSourceProperty('event_timezone')])) {
+        $timezone = $row->getSourceProperty('event_timezone');
+      }
+    }
+
+    return $timezone;
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableDisplayBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableDisplayBase.php
new file mode 100644
index 0000000..63acddc
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableDisplayBase.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableDisplayBase.
+ */
+
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Base class for Drupal 6 comment variables to Drupal 8 entity display tests.
+ */
+class MigrateCommentVariableDisplayBase extends MigrateDrupalTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  static $modules = array('comment', 'node');
+
+  /**
+   * The database dumps used.
+   *
+   * @var array
+   */
+  protected $dumps;
+
+  /**
+   * The node types being tested.
+   *
+   * @var array
+   */
+  protected $types = array('page', 'story');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+      'name' => 'comment',
+      'type' => 'comment',
+      'translatable' => '0',
+    ))->save();
+    foreach ($this->types as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+      entity_create('field_instance_config', array(
+        'label' => 'Comment settings',
+        'description' => '',
+        'field_name' => 'comment',
+        'entity_type' => 'node',
+        'bundle' => $type,
+        'required' => 1,
+      ))->save();
+    }
+    $this->dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+    );
+    $id_mappings = array(
+      'd6_comment_field_instance' => array(
+        array(array('page'), array('node', 'comment', 'page')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', static::MIGRATION);
+    $this->prepare($migration, $this->dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityDisplay.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityDisplay.php
new file mode 100644
index 0000000..c702f0c
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityDisplay.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableEntityDisplay.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests comment variables migrated into an entity display.
+ */
+class MigrateCommentVariableEntityDisplay extends MigrateCommentVariableDisplayBase {
+
+  /**
+   * The migration to run.
+   */
+  const MIGRATION = 'd6_comment_entity_display';
+
+  /**
+   * The node types being used.
+   */
+  protected $types = array('page', 'story');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to entity displays,',
+      'description'  => 'Upgrade comment variables to entity.display.node.*.default.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * Tests comment variables migrated into an entity display.
+   */
+  public function testCommentEntityDisplay() {
+    foreach ($this->types as $type) {
+      $component = entity_get_display('node', $type, 'default')->getComponent('comment');
+      $this->assertEqual($component['label'], 'hidden');
+      $this->assertEqual($component['type'], 'comment_default');
+      $this->assertEqual($component['weight'], 20);
+    }
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityFormDisplay.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityFormDisplay.php
new file mode 100644
index 0000000..4d1700a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableEntityFormDisplay.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableEntityFormDisplay.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+use Drupal\migrate\MigrateExecutable;
+
+/**
+ * Tests comment variables migrated into an entity display.
+ */
+class MigrateCommentVariableEntityFormDisplay extends MigrateCommentVariableDisplayBase {
+
+  /**
+   * The migration to run.
+   */
+  const MIGRATION = 'd6_comment_entity_form_display';
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to entity form displays,',
+      'description'  => 'Upgrade comment variables to entity.form_display.node.*.default.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * Tests comment variables migrated into an entity display.
+   */
+  public function testCommentEntityFormDisplay() {
+    foreach ($this->types as $type) {
+      $component = entity_get_form_display('node', $type, 'default')->getComponent('comment');
+      $this->assertEqual($component['type'], 'comment_default');
+      $this->assertEqual($component['weight'], 20);
+    }
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableField.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableField.php
new file mode 100644
index 0000000..6c5d11d
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableField.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableField.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests comment variables migrated into a field entity.
+ */
+class MigrateCommentVariableField extends MigrateDrupalTestBase {
+
+  static $modules = array('comment', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to a field,',
+      'description'  => 'Upgrade comment variables  to field.field.node.comment.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    foreach (array('page', 'story', 'test') as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+    }
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_comment_field');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests comment variables migrated into a field entity.
+   */
+  public function testCommentField() {
+    $this->assertTrue(is_object(entity_load('field_config', 'node.comment')));
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableInstance.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableInstance.php
new file mode 100644
index 0000000..0e37c12
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentVariableInstance.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentVariableInstance.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests comment variables migrated into a field instance.
+ */
+class MigrateCommentVariableInstance extends MigrateDrupalTestBase {
+
+  static $modules = array('comment', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment variables to a field instance,',
+      'description'  => 'Upgrade comment variables to field.instance.node.*.comment.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Add some id mappings for the dependant migrations.
+    $id_mappings = array(
+      'd6_comment_field' => array(
+        array(array('page'), array('node', 'page')),
+      ),
+      'd6_node_type' => array(
+        array(array('page'), array('page')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    foreach (array('page', 'story') as $type) {
+      entity_create('node_type', array('type' => $type))->save();
+    }
+    entity_create('field_config', array(
+      'entity_type' => 'node',
+        'name' => 'comment',
+        'type' => 'comment',
+        'translatable' => '0',
+    ))->save();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_comment_field_instance');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6CommentVariable.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Test the migrated field instance values.
+   */
+  public function testCommentFieldInstance() {
+    $node = entity_create('node', array('type' => 'page'));
+    $this->assertEqual($node->comment->status, 0);
+    $node = entity_create('node', array('type' => 'story'));
+    $this->assertEqual($node->comment->status, 2);
+    $settings = $node->comment->getFieldDefinition()->getSettings();
+    $this->assertEqual($settings['default_mode'], 2);
+    $this->assertEqual($settings['per_page'], 70);
+    $this->assertEqual($settings['anonymous'], 1);
+    $this->assertEqual($settings['subject'], 0);
+    $this->assertEqual($settings['form_location'], 0);
+    $this->assertEqual($settings['preview'], 0);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTestBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTestBase.php
new file mode 100644
index 0000000..48e9d0a
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateNodeTestBase.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateNodeTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateNodeTestBase extends MigrateDrupalTestBase {
+
+  static $modules = array('node');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $node_type = entity_create('node_type', array('type' => 'story'));
+    $node_type->save();
+    node_add_body_field($node_type);
+
+    $id_mappings = array(
+      'd6_node_type' => array(
+        array(array('test_story'), array('story')),
+      ),
+      'd6_filter_format' => array(
+        array(array(1), array('filtered_html')),
+        array(array(2), array('full_html')),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    // Create a test node.
+    $node = entity_create('node', array(
+      'type' => 'story',
+      'nid' => 1,
+      'vid' => 1,
+    ));
+    $node->enforceIsNew();
+    $node->save();
+
+    // Load dumps.
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6NodeType.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6FieldInstance.php',
+    );
+    $this->loadDumps($dumps);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTestBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTestBase.php
new file mode 100644
index 0000000..c1f333b
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateTermNodeTestBase.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateTermNodeTestBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateTermNodeTestBase extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  static $modules = array('node', 'taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $vocabulary = entity_create('taxonomy_vocabulary', array(
+      'vid' => 'test',
+    ));
+    $vocabulary->save();
+    $node_type = entity_create('node_type', array('type' => 'story'));
+    $node_type->save();
+    foreach (array('vocabulary_1_i_0_', 'vocabulary_2_i_1_', 'vocabulary_3_i_2_') as $name) {
+      entity_create('field_config', array(
+        'name' => $name,
+        'entity_type' => 'node',
+        'type' => 'taxonomy_term_reference',
+        'cardinality' => -1,
+        'settings' => array(
+          'allowed_values' => array(
+            array(
+              'vocabulary' => $vocabulary->id(),
+              'parent' => '0',
+            ),
+          ),
+        ),
+      ))->save();
+      entity_create('field_instance_config', array(
+        'field_name' => $name,
+        'entity_type' => 'node',
+        'bundle' => 'story',
+      ))->save();
+
+    }
+    $id_mappings = array(
+      'd6_vocabulary_field_instance' => array(
+        array(array(1, 'page'), array('node', 'page', 'test')),
+      ),
+      'd6_vocabulary_entity_display' => array(
+        array(array(1, 'page'), array('node', 'page', 'default', 'test')),
+      ),
+      'd6_vocabulary_entity_form_display' => array(
+        array(array(1, 'page'), array('node', 'page', 'default', 'test')),
+      ),
+      'd6_node' => array(
+        array(array(1), array(1)),
+        array(array(2), array(2)),
+      ),
+    );
+    $this->prepareIdMappings($id_mappings);
+
+    $vids = array(1, 2, 3);
+    for ($i = 1; $i <= 2; $i++) {
+      $node = entity_create('node', array(
+        'type' => 'story',
+        'nid' => $i,
+        'vid' => array_shift($vids),
+      ));
+      $node->enforceIsNew();
+      $node->save();
+      if ($i == 1) {
+        $node->vid->value = array_shift($vids);
+        $node->enforceIsNew(FALSE);
+        $node->setNewRevision();
+        $node->isDefaultRevision(FALSE);
+        $node->save();
+      }
+    }
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TermNode.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyTerm.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6TaxonomyVocabulary.php',
+    );
+    $this->loadDumps($dumps);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadBase.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadBase.php
new file mode 100644
index 0000000..90b46de
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateUploadBase.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateUploadBase.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateUploadBase extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  static $modules = array('file', 'node');
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    // Create new file entities.
+    for ($i = 1; $i <= 3; $i++) {
+      $file = entity_create('file', array(
+        'fid' => $i,
+        'uid' => 1,
+        'filename' => 'druplicon.txt',
+        'uri' => "public://druplicon-$i.txt",
+        'filemime' => 'text/plain',
+        'created' => 1,
+        'changed' => 1,
+        'status' => FILE_STATUS_PERMANENT,
+      ));
+      $file->enforceIsNew();
+      file_put_contents($file->getFileUri(), 'hello world');
+
+      // Save it, inserting a new record.
+      $file->save();
+      $id_mappings['d6_file'][] = array(array($i), array($i));
+    }
+
+    // Add a node type.
+    $node_type = entity_create('node_type', array('type' => 'story'));
+    $node_type->save();
+
+    // Add a file field.
+    entity_create('field_config', array(
+      'name' => 'upload',
+      'entity_type' => 'node',
+      'type' => 'file',
+      'cardinality' => -1,
+      'settings' => array(
+        'display_field' => TRUE,
+      ),
+    ))->save();
+    entity_create('field_instance_config', array(
+      'field_name' => 'upload',
+      'entity_type' => 'node',
+      'bundle' => 'story',
+    ))->save();
+    $id_mappings['d6_node'] = array(
+      array(array(1), array(1)),
+      array(array(2), array(2)),
+    );
+    $this->prepareIdMappings($id_mappings);
+    $vids = array(1, 2, 3);
+    for ($i = 1; $i <= 2; $i++) {
+      $node = entity_create('node', array(
+        'type' => 'story',
+        'nid' => $i,
+        'vid' => array_shift($vids),
+      ));
+      $node->enforceIsNew();
+      $node->save();
+      if ($i == 1) {
+        $node->vid->value = array_shift($vids);
+        $node->enforceIsNew(FALSE);
+        $node->isDefaultRevision(FALSE);
+        $node->save();
+      }
+    }
+    $path = drupal_get_path('module', 'migrate_drupal');
+    $dumps = array(
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Node.php',
+      $path . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Upload.php',
+    );
+    $this->loadDumps($dumps);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/migrate_drupal.module b/core/modules/migrate_drupal/migrate_drupal.module
index 7b85d80..5a71396 100644
--- a/core/modules/migrate_drupal/migrate_drupal.module
+++ b/core/modules/migrate_drupal/migrate_drupal.module
@@ -1,4 +1,5 @@
 <?php
+use Drupal\Core\Entity\EntityInterface;
 
 /**
  * Implements hook_entity_type_alter().
diff --git a/core/modules/migrate_drupal/migrate_drupal.routing.yml b/core/modules/migrate_drupal/migrate_drupal.routing.yml
new file mode 100644
index 0000000..a7e8fef
--- /dev/null
+++ b/core/modules/migrate_drupal/migrate_drupal.routing.yml
@@ -0,0 +1,7 @@
+migrate_drupal.run:
+  path: '/admin/structure/migrate/run'
+  defaults:
+    _form: '\Drupal\migrate_drupal\Form\MigrateDrupalRunForm'
+    _title: 'Run'
+  requirements:
+    _permission: 'administer site configuration'
