Use stevedore for plugin config of block device
This patch introduces stevedore plugin mechanism for use with the block device layer. This makes it possible that other projects pass in their own block device plugins. Change-Id: Id3ea56aaf75f5a20a4e1b6ac2a68adb12c56b574 Signed-off-by: Andreas Florath <andreas@florath.net>
This commit is contained in:
parent
f128d08cf0
commit
57c9e0bb41
@ -15,13 +15,12 @@
|
|||||||
import codecs
|
import codecs
|
||||||
from diskimage_builder.block_device.blockdevicesetupexception \
|
from diskimage_builder.block_device.blockdevicesetupexception \
|
||||||
import 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
|
from diskimage_builder.graph.digraph import Digraph
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
from stevedore import extension
|
||||||
import sys
|
import sys
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
@ -85,13 +84,6 @@ class BlockDevice(object):
|
|||||||
# type: ext4
|
# type: ext4
|
||||||
# mount_point: /
|
# 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,
|
def __init__(self, block_device_config, build_dir,
|
||||||
default_image_size, default_image_dir):
|
default_image_size, default_image_dir):
|
||||||
logger.debug("Creating BlockDevice object")
|
logger.debug("Creating BlockDevice object")
|
||||||
@ -109,6 +101,9 @@ class BlockDevice(object):
|
|||||||
"states/block-device")
|
"states/block-device")
|
||||||
self.state_json_file_name \
|
self.state_json_file_name \
|
||||||
= os.path.join(self.state_dir, "state.json")
|
= 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):
|
def write_state(self, result):
|
||||||
logger.debug("Write state [%s]" % self.state_json_file_name)
|
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
|
# As the first step the configured objects are created
|
||||||
# (if it exists)
|
# (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] "
|
logger.error("Configured top level element [%s] "
|
||||||
"does not exists." % cfg_obj_name)
|
"does not exists." % cfg_obj_name)
|
||||||
return 1
|
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)
|
cfg_obj_val, default_config)
|
||||||
# At this point it is only possible to add the nodes:
|
# At this point it is only possible to add the nodes:
|
||||||
# adding the edges needs all nodes first.
|
# adding the edges needs all nodes first.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
from diskimage_builder.block_device.blockdevicesetupexception \
|
from diskimage_builder.block_device.blockdevicesetupexception \
|
||||||
import 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.block_device.utils import parse_abs_size_spec
|
||||||
from diskimage_builder.graph.digraph import Digraph
|
from diskimage_builder.graph.digraph import Digraph
|
||||||
import logging
|
import logging
|
||||||
@ -24,15 +25,13 @@ import subprocess
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LocalLoop(Digraph.Node):
|
class LocalLoop(NodePluginBase):
|
||||||
"""Level0: Local loop image device handling.
|
"""Level0: Local loop image device handling.
|
||||||
|
|
||||||
This class handles local loop devices that can be used
|
This class handles local loop devices that can be used
|
||||||
for VM image installation.
|
for VM image installation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type_string = "local_loop"
|
|
||||||
|
|
||||||
def __init__(self, config, default_config):
|
def __init__(self, config, default_config):
|
||||||
logger.debug("Creating LocalLoop object; config [%s] "
|
logger.debug("Creating LocalLoop object; config [%s] "
|
||||||
"default_config [%s]" % (config, default_config))
|
"default_config [%s]" % (config, default_config))
|
||||||
@ -50,9 +49,6 @@ class LocalLoop(Digraph.Node):
|
|||||||
Digraph.Node.__init__(self, self.name)
|
Digraph.Node.__init__(self, self.name)
|
||||||
self.filename = os.path.join(self.image_dir, self.name + ".raw")
|
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):
|
def insert_edges(self, dg):
|
||||||
"""Because this is created without base, there are no edges."""
|
"""Because this is created without base, there are no edges."""
|
||||||
pass
|
pass
|
||||||
|
@ -16,6 +16,7 @@ import collections
|
|||||||
from diskimage_builder.block_device.blockdevicesetupexception \
|
from diskimage_builder.block_device.blockdevicesetupexception \
|
||||||
import BlockDeviceSetupException
|
import BlockDeviceSetupException
|
||||||
from diskimage_builder.block_device.level1.mbr import MBR
|
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_abs_size_spec
|
||||||
from diskimage_builder.block_device.utils import parse_rel_size_spec
|
from diskimage_builder.block_device.utils import parse_rel_size_spec
|
||||||
from diskimage_builder.graph.digraph import Digraph
|
from diskimage_builder.graph.digraph import Digraph
|
||||||
@ -67,9 +68,7 @@ class Partition(Digraph.Node):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Partitioning(object):
|
class Partitioning(PluginBase):
|
||||||
|
|
||||||
type_string = "partitioning"
|
|
||||||
|
|
||||||
flag_boot = 1
|
flag_boot = 1
|
||||||
flag_primary = 2
|
flag_primary = 2
|
||||||
|
51
diskimage_builder/block_device/plugin_base.py
Normal file
51
diskimage_builder/block_device/plugin_base.py
Normal file
@ -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)
|
@ -6,3 +6,4 @@ pbr>=2.0.0 # Apache-2.0
|
|||||||
PyYAML>=3.10.0 # MIT
|
PyYAML>=3.10.0 # MIT
|
||||||
flake8<2.6.0,>=2.5.4 # MIT
|
flake8<2.6.0,>=2.5.4 # MIT
|
||||||
six>=1.9.0 # MIT
|
six>=1.9.0 # MIT
|
||||||
|
stevedore>=1.20.0 # Apache-2.0
|
||||||
|
@ -56,3 +56,7 @@ console_scripts =
|
|||||||
disk-image-create = diskimage_builder.disk_image_create:main
|
disk-image-create = diskimage_builder.disk_image_create:main
|
||||||
ramdisk-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
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user