2017-01-29 23:52:40 +00:00
|
|
|
# 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 logging
|
|
|
|
import uuid
|
|
|
|
|
2017-05-18 22:42:00 +00:00
|
|
|
from diskimage_builder.block_device.exception \
|
2017-01-29 23:52:40 +00:00
|
|
|
import 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
|
2017-01-29 23:52:40 +00:00
|
|
|
from diskimage_builder.block_device.utils import exec_sudo
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
# There is the need that filesystem labels are unique:
|
|
|
|
# if not the boot and / or mount (with LABEL=) might fail.
|
|
|
|
file_system_labels = set()
|
|
|
|
|
|
|
|
# There is the need to check the length of the label of
|
|
|
|
# the filesystem. The maximum length depends on the used filesystem.
|
|
|
|
# This map provides information about the maximum label length.
|
|
|
|
file_system_max_label_length = {
|
|
|
|
"ext2": 16,
|
|
|
|
"ext3": 16,
|
|
|
|
"ext4": 16,
|
|
|
|
"xfs": 12,
|
|
|
|
"vfat": 11
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-25 01:28:13 +00:00
|
|
|
class FilesystemNode(NodeBase):
|
2017-01-29 23:52:40 +00:00
|
|
|
|
|
|
|
def __init__(self, config):
|
|
|
|
logger.debug("Create filesystem object; config [%s]" % config)
|
2017-05-25 01:28:13 +00:00
|
|
|
super(FilesystemNode, self).__init__(config['name'])
|
|
|
|
|
2017-01-29 23:52:40 +00:00
|
|
|
# Parameter check (mandatory)
|
2017-05-25 01:28:13 +00:00
|
|
|
for pname in ['base', 'type']:
|
2017-01-29 23:52:40 +00:00
|
|
|
if pname not in config:
|
2017-05-09 23:59:26 +00:00
|
|
|
raise BlockDeviceSetupException(
|
|
|
|
"Mkfs config needs [%s]" % pname)
|
2017-01-29 23:52:40 +00:00
|
|
|
setattr(self, pname, config[pname])
|
|
|
|
|
|
|
|
# Parameter check (optional)
|
|
|
|
for pname in ['label', 'opts', 'uuid']:
|
|
|
|
setattr(self, pname,
|
|
|
|
config[pname] if pname in config else None)
|
|
|
|
|
|
|
|
if self.label is None:
|
|
|
|
self.label = self.name
|
|
|
|
|
|
|
|
# Historic reasons - this will hopefully vanish in one of
|
|
|
|
# the next major releases
|
|
|
|
if self.label == "cloudimg-rootfs" and self.type == "xfs":
|
|
|
|
logger.warning("Default label [cloudimg-rootfs] too long for xfs "
|
|
|
|
"file system - using [img-rootfs] instead")
|
|
|
|
self.label = "img-rootfs"
|
|
|
|
|
|
|
|
if self.label in file_system_labels:
|
2017-05-09 23:59:26 +00:00
|
|
|
raise BlockDeviceSetupException(
|
|
|
|
"File system label [%s] used more than once" % self.label)
|
2017-01-29 23:52:40 +00:00
|
|
|
file_system_labels.add(self.label)
|
|
|
|
|
|
|
|
if self.type in file_system_max_label_length:
|
2017-05-09 23:59:26 +00:00
|
|
|
if file_system_max_label_length[self.type] < len(self.label):
|
|
|
|
raise BlockDeviceSetupException(
|
|
|
|
"Label [{label}] too long for filesystem [{type}]: "
|
|
|
|
" [{len}] > [{max_len}]".format({
|
|
|
|
'label': self.label,
|
|
|
|
'type': self.type,
|
|
|
|
'len': len(self.label),
|
|
|
|
'max': file_system_max_label_length[self.type]}))
|
2017-01-29 23:52:40 +00:00
|
|
|
else:
|
|
|
|
logger.warning("Length of label [%s] cannot be checked for "
|
|
|
|
"filesystem [%s]: unknown max length" %
|
|
|
|
(self.label, self.type))
|
|
|
|
logger.warning("Continue - but this might lead to an error")
|
|
|
|
|
|
|
|
if self.opts is not None:
|
|
|
|
self.opts = self.opts.strip().split(' ')
|
|
|
|
|
|
|
|
if self.uuid is None:
|
|
|
|
self.uuid = str(uuid.uuid4())
|
|
|
|
|
|
|
|
logger.debug("Filesystem created [%s]" % self)
|
|
|
|
|
2017-05-23 23:57:32 +00:00
|
|
|
def get_edges(self):
|
|
|
|
edge_from = [self.base]
|
|
|
|
edge_to = []
|
|
|
|
return (edge_from, edge_to)
|
2017-01-29 23:52:40 +00:00
|
|
|
|
|
|
|
def create(self, result, rollback):
|
|
|
|
logger.info("create called; result [%s]" % result)
|
|
|
|
|
|
|
|
cmd = ["mkfs"]
|
|
|
|
|
|
|
|
cmd.extend(['-t', self.type])
|
|
|
|
if self.opts:
|
|
|
|
cmd.extend(self.opts)
|
|
|
|
cmd.extend(["-L", self.label])
|
|
|
|
|
|
|
|
if self.type in ('ext2', 'ext3', 'ext4'):
|
|
|
|
cmd.extend(['-U', self.uuid])
|
|
|
|
elif self.type == 'xfs':
|
|
|
|
cmd.extend(['-m', "uuid=%s" % self.uuid])
|
|
|
|
else:
|
|
|
|
logger.warning("UUID will not be written for fs type [%s]"
|
|
|
|
% self.type)
|
|
|
|
|
|
|
|
if self.type in ('ext2', 'ext3', 'ext4', 'xfs'):
|
|
|
|
cmd.append('-q')
|
|
|
|
|
|
|
|
if 'blockdev' not in result:
|
|
|
|
result['blockdev'] = {}
|
|
|
|
device = result['blockdev'][self.base]['device']
|
|
|
|
cmd.append(device)
|
|
|
|
|
|
|
|
logger.debug("Creating fs command [%s]" % (cmd))
|
|
|
|
exec_sudo(cmd)
|
|
|
|
|
|
|
|
if 'filesys' not in result:
|
|
|
|
result['filesys'] = {}
|
|
|
|
result['filesys'][self.name] \
|
|
|
|
= {'uuid': self.uuid, 'label': self.label,
|
|
|
|
'fstype': self.type, 'opts': self.opts,
|
|
|
|
'device': device}
|
|
|
|
|
|
|
|
|
2017-05-25 01:28:13 +00:00
|
|
|
class Mkfs(PluginBase):
|
|
|
|
"""Create a file system
|
2017-01-29 23:52:40 +00:00
|
|
|
|
|
|
|
This block device module handles creating different file
|
|
|
|
systems.
|
|
|
|
"""
|
|
|
|
|
2017-05-25 01:28:13 +00:00
|
|
|
def __init__(self, config, defaults):
|
|
|
|
super(Mkfs, self).__init__()
|
2017-01-29 23:52:40 +00:00
|
|
|
self.filesystems = {}
|
2017-05-25 01:28:13 +00:00
|
|
|
fs = FilesystemNode(config)
|
2017-01-29 23:52:40 +00:00
|
|
|
self.filesystems[fs.get_name()] = fs
|
|
|
|
|
2017-05-23 23:57:32 +00:00
|
|
|
def get_nodes(self):
|
|
|
|
nodes = []
|
2017-01-29 23:52:40 +00:00
|
|
|
for _, fs in self.filesystems.items():
|
2017-05-23 23:57:32 +00:00
|
|
|
nodes.append(fs)
|
|
|
|
return nodes
|