diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py
index 897c0d4bc..18b5e55e8 100644
--- a/diskimage_builder/block_device/blockdevice.py
+++ b/diskimage_builder/block_device/blockdevice.py
@@ -15,13 +15,12 @@
 import codecs
 from diskimage_builder.block_device.blockdevicesetupexception \
     import BlockDeviceSetupException
-from diskimage_builder.block_device.level0 import LocalLoop
-from diskimage_builder.block_device.level1 import Partitioning
 from diskimage_builder.graph.digraph import Digraph
 import json
 import logging
 import os
 import shutil
+from stevedore import extension
 import sys
 import yaml
 
@@ -85,13 +84,6 @@ class BlockDevice(object):
 #  type: ext4
 #  mount_point: /
 
-    # A dictionary to map sensible names to internal implementation.
-    cfg_type_map = {
-        'local_loop': LocalLoop,
-        'partitioning': Partitioning,
-        'mkfs': 'not yet implemented',
-    }
-
     def __init__(self, block_device_config, build_dir,
                  default_image_size, default_image_dir):
         logger.debug("Creating BlockDevice object")
@@ -109,6 +101,9 @@ class BlockDevice(object):
                                       "states/block-device")
         self.state_json_file_name \
             = os.path.join(self.state_dir, "state.json")
+        self.plugin_manager = extension.ExtensionManager(
+            namespace='diskimage_builder.block_device.plugin',
+            invoke_on_load=False)
 
     def write_state(self, result):
         logger.debug("Write state [%s]" % self.state_json_file_name)
@@ -138,11 +133,11 @@ class BlockDevice(object):
 
             # As the first step the configured objects are created
             # (if it exists)
-            if cfg_obj_name not in BlockDevice.cfg_type_map:
+            if cfg_obj_name not in self.plugin_manager:
                 logger.error("Configured top level element [%s] "
                              "does not exists." % cfg_obj_name)
                 return 1
-            cfg_obj = BlockDevice.cfg_type_map[cfg_obj_name](
+            cfg_obj = self.plugin_manager[cfg_obj_name].plugin(
                 cfg_obj_val, default_config)
             # At this point it is only possible to add the nodes:
             # adding the edges needs all nodes first.
diff --git a/diskimage_builder/block_device/level0/localloop.py b/diskimage_builder/block_device/level0/localloop.py
index 7fd21b3d3..dfa543d8d 100644
--- a/diskimage_builder/block_device/level0/localloop.py
+++ b/diskimage_builder/block_device/level0/localloop.py
@@ -14,6 +14,7 @@
 
 from diskimage_builder.block_device.blockdevicesetupexception \
     import BlockDeviceSetupException
+from diskimage_builder.block_device.plugin_base import NodePluginBase
 from diskimage_builder.block_device.utils import parse_abs_size_spec
 from diskimage_builder.graph.digraph import Digraph
 import logging
@@ -24,15 +25,13 @@ import subprocess
 logger = logging.getLogger(__name__)
 
 
-class LocalLoop(Digraph.Node):
+class LocalLoop(NodePluginBase):
     """Level0: Local loop image device handling.
 
     This class handles local loop devices that can be used
     for VM image installation.
     """
 
-    type_string = "local_loop"
-
     def __init__(self, config, default_config):
         logger.debug("Creating LocalLoop object; config [%s] "
                      "default_config [%s]" % (config, default_config))
@@ -50,9 +49,6 @@ class LocalLoop(Digraph.Node):
         Digraph.Node.__init__(self, self.name)
         self.filename = os.path.join(self.image_dir, self.name + ".raw")
 
-    def insert_nodes(self, dg):
-        dg.add_node(self)
-
     def insert_edges(self, dg):
         """Because this is created without base, there are no edges."""
         pass
diff --git a/diskimage_builder/block_device/level1/partitioning.py b/diskimage_builder/block_device/level1/partitioning.py
index 28f2a688e..2d79ddb5c 100644
--- a/diskimage_builder/block_device/level1/partitioning.py
+++ b/diskimage_builder/block_device/level1/partitioning.py
@@ -16,6 +16,7 @@ import collections
 from diskimage_builder.block_device.blockdevicesetupexception \
     import BlockDeviceSetupException
 from diskimage_builder.block_device.level1.mbr import MBR
+from diskimage_builder.block_device.plugin_base import PluginBase
 from diskimage_builder.block_device.utils import parse_abs_size_spec
 from diskimage_builder.block_device.utils import parse_rel_size_spec
 from diskimage_builder.graph.digraph import Digraph
@@ -67,9 +68,7 @@ class Partition(Digraph.Node):
         pass
 
 
-class Partitioning(object):
-
-    type_string = "partitioning"
+class Partitioning(PluginBase):
 
     flag_boot = 1
     flag_primary = 2
diff --git a/diskimage_builder/block_device/plugin_base.py b/diskimage_builder/block_device/plugin_base.py
new file mode 100644
index 000000000..c92ff77c9
--- /dev/null
+++ b/diskimage_builder/block_device/plugin_base.py
@@ -0,0 +1,51 @@
+# Copyright 2017 Andreas Florath (andreas@florath.net)
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import abc
+from diskimage_builder.graph.digraph import Digraph
+import six
+
+
+@six.add_metaclass(abc.ABCMeta)
+class PluginBase(object):
+    """Abstract base class for block device plugins"""
+
+    def __init__(self, name):
+        """All plugins must have a name"""
+        self.name = name
+
+    @abc.abstractmethod
+    def create(self, state, rollback):
+        """Create the block device plugin
+
+        :param state: a dictionary to store results for this plugin.
+                      These are used in two scenarios: other plugins
+                      can use this to get information about the
+                      result of the plugin and it can be used in
+                      later runs of dib-block-device for cleaning up.
+        :type state: dict(str:?)
+
+        :param rollback: a list of python functions that will be
+                         called in reversed order to cleanup if there
+                         occurs an error later within the same
+                         dib-block-device run.
+        :type rollback: list(function)
+        """
+
+
+class NodePluginBase(PluginBase, Digraph.Node):
+
+    def insert_nodes(self, dg):
+        """Adds self as a node to the given digraph"""
+        dg.add_node(self)
diff --git a/requirements.txt b/requirements.txt
index 2f2d10936..6077f0c3f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,3 +6,4 @@ pbr>=2.0.0 # Apache-2.0
 PyYAML>=3.10.0 # MIT
 flake8<2.6.0,>=2.5.4 # MIT
 six>=1.9.0 # MIT
+stevedore>=1.20.0 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index 5eac87455..6a42eb0c7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -56,3 +56,7 @@ console_scripts =
     disk-image-create = diskimage_builder.disk_image_create:main
     ramdisk-image-create = diskimage_builder.disk_image_create:main
     dib-run-parts = diskimage_builder.dib_run_parts:main
+
+diskimage_builder.block_device.plugin =
+    local_loop = diskimage_builder.block_device.level0.localloop:LocalLoop
+    partitioning = diskimage_builder.block_device.level1.partitioning:Partitioning