Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
# Copyright 2016 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.
|
|
|
|
|
2017-05-02 03:43:43 +00:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
|
2017-05-18 22:42:00 +00:00
|
|
|
from diskimage_builder.block_device.exception import \
|
2017-05-02 05:32:47 +00:00
|
|
|
BlockDeviceSetupException
|
2017-05-25 01:28:13 +00:00
|
|
|
from diskimage_builder.block_device.plugin import NodeBase
|
|
|
|
from diskimage_builder.block_device.plugin import PluginBase
|
2018-06-28 00:54:40 +00:00
|
|
|
from diskimage_builder.block_device.utils import exec_sudo
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
from diskimage_builder.block_device.utils import parse_abs_size_spec
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2017-06-05 04:36:30 +00:00
|
|
|
def image_create(filename, size):
|
|
|
|
logger.info("Create image file [%s]", filename)
|
|
|
|
with open(filename, "w") as fd:
|
|
|
|
fd.seek(size - 1)
|
|
|
|
fd.write("\0")
|
|
|
|
|
|
|
|
|
|
|
|
def image_delete(filename):
|
|
|
|
logger.info("Remove image file [%s]", filename)
|
|
|
|
os.remove(filename)
|
|
|
|
|
|
|
|
|
|
|
|
def loopdev_attach(filename):
|
|
|
|
logger.info("loopdev attach")
|
|
|
|
logger.debug("Calling [sudo losetup --show -f %s]", filename)
|
2018-06-28 00:54:40 +00:00
|
|
|
block_device = exec_sudo(["losetup", "--show", "-f", filename])
|
|
|
|
# [:-1]: Cut of the newline
|
|
|
|
block_device = block_device[:-1]
|
|
|
|
logger.info("New block device [%s]", block_device)
|
|
|
|
return block_device
|
2017-06-05 04:36:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
def loopdev_detach(loopdev):
|
|
|
|
logger.info("loopdev detach")
|
|
|
|
# loopback dev may be tied up a bit by udev events triggered
|
|
|
|
# by partition events
|
|
|
|
for try_cnt in range(10, 1, -1):
|
2018-06-28 00:54:40 +00:00
|
|
|
try:
|
|
|
|
exec_sudo(["losetup", "-d", loopdev])
|
|
|
|
return
|
|
|
|
except BlockDeviceSetupException as e:
|
2017-06-05 04:36:30 +00:00
|
|
|
# Do not raise an error - maybe other cleanup methods
|
|
|
|
# can at least do some more work.
|
2018-06-28 00:54:40 +00:00
|
|
|
logger.error("loopdev detach failed (%s)", e.returncode)
|
|
|
|
|
2017-06-05 04:36:30 +00:00
|
|
|
logger.debug("Gave up trying to detach [%s]", loopdev)
|
2018-06-28 00:54:40 +00:00
|
|
|
return 1
|
2017-06-05 04:36:30 +00:00
|
|
|
|
|
|
|
|
2017-05-25 01:28:13 +00:00
|
|
|
class LocalLoopNode(NodeBase):
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
"""Level0: Local loop image device handling.
|
|
|
|
|
|
|
|
This class handles local loop devices that can be used
|
|
|
|
for VM image installation.
|
|
|
|
"""
|
2017-06-01 04:31:49 +00:00
|
|
|
def __init__(self, config, default_config, state):
|
2016-07-16 20:16:13 +00:00
|
|
|
logger.debug("Creating LocalLoop object; config [%s] "
|
2017-05-28 05:19:05 +00:00
|
|
|
"default_config [%s]", config, default_config)
|
2017-06-01 04:31:49 +00:00
|
|
|
super(LocalLoopNode, self).__init__(config['name'], state)
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
if 'size' in config:
|
|
|
|
self.size = parse_abs_size_spec(config['size'])
|
2017-05-28 05:19:05 +00:00
|
|
|
logger.debug("Image size [%s]", self.size)
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
else:
|
2017-04-22 07:49:22 +00:00
|
|
|
self.size = parse_abs_size_spec(default_config['image-size'])
|
2017-05-28 05:19:05 +00:00
|
|
|
logger.debug("Using default image size [%s]", self.size)
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
if 'directory' in config:
|
|
|
|
self.image_dir = config['directory']
|
|
|
|
else:
|
2017-04-22 07:49:22 +00:00
|
|
|
self.image_dir = default_config['image-dir']
|
Refactor: block-device handling (local loop)
Block device handling can be somewhat complex - especially
when taking things like md, lvm or encryption into account.
This patch factors out the creation and deletion of the local
loop image device handling into a python library.
The main propose of this patch is to implement the needed
infrastructure. Based on this, more advanced functions can be added.
Example: (advanced) partitioning, LVM, handling different boot
scenarios (BIOS, UEFI, ...), possibility of handling multiple images
(local loop image, iSCSI, physical hard disk, ...), handling of
different filesystems for different partitions / LVs.
Change-Id: Ib626b36a00f8a5dc3dbde8df3e2619a2438eaaf1
Signed-off-by: Andreas Florath <andreas@florath.net>
2016-05-21 19:32:35 +00:00
|
|
|
self.filename = os.path.join(self.image_dir, self.name + ".raw")
|
|
|
|
|
2017-05-23 23:57:32 +00:00
|
|
|
def get_edges(self):
|
2016-07-16 20:16:13 +00:00
|
|
|
"""Because this is created without base, there are no edges."""
|
2017-05-23 23:57:32 +00:00
|
|
|
return ([], [])
|
2016-07-16 20:16:13 +00:00
|
|
|
|
2017-06-02 00:57:06 +00:00
|
|
|
def create(self):
|
2017-05-28 05:19:05 +00:00
|
|
|
logger.debug("[%s] Creating loop on [%s] with size [%d]",
|
|
|
|
self.name, self.filename, self.size)
|
2016-07-16 20:16:13 +00:00
|
|
|
|
2017-06-02 00:57:06 +00:00
|
|
|
self.add_rollback(image_delete, self.filename)
|
2017-06-05 04:36:30 +00:00
|
|
|
image_create(self.filename, self.size)
|
2016-07-16 20:16:13 +00:00
|
|
|
|
2017-06-05 04:36:30 +00:00
|
|
|
block_device = loopdev_attach(self.filename)
|
2017-06-02 00:57:06 +00:00
|
|
|
self.add_rollback(loopdev_detach, block_device)
|
2016-07-16 20:16:13 +00:00
|
|
|
|
2017-06-01 04:31:49 +00:00
|
|
|
if 'blockdev' not in self.state:
|
|
|
|
self.state['blockdev'] = {}
|
2017-05-01 07:19:49 +00:00
|
|
|
|
2017-06-01 04:31:49 +00:00
|
|
|
self.state['blockdev'][self.name] = {"device": block_device,
|
|
|
|
"image": self.filename}
|
2017-05-28 05:19:05 +00:00
|
|
|
logger.debug("Created loop name [%s] device [%s] image [%s]",
|
|
|
|
self.name, block_device, self.filename)
|
2016-07-16 20:16:13 +00:00
|
|
|
return
|
|
|
|
|
2017-06-01 04:57:34 +00:00
|
|
|
def umount(self):
|
|
|
|
loopdev_detach(self.state['blockdev'][self.name]['device'])
|
2016-07-16 20:16:13 +00:00
|
|
|
|
2017-06-01 04:57:34 +00:00
|
|
|
def delete(self):
|
|
|
|
image_delete(self.state['blockdev'][self.name]['image'])
|
2017-05-25 01:28:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
class LocalLoop(PluginBase):
|
|
|
|
|
2017-06-01 04:31:49 +00:00
|
|
|
def __init__(self, config, defaults, state):
|
2017-06-07 23:43:47 +00:00
|
|
|
super(LocalLoop, self).__init__()
|
2017-06-01 04:31:49 +00:00
|
|
|
self.node = LocalLoopNode(config, defaults, state)
|
2017-05-25 01:28:13 +00:00
|
|
|
|
|
|
|
def get_nodes(self):
|
|
|
|
return [self.node]
|