Alexander Gordeev a6ec436b5a Skip cleaning of MD containers
Add possibility to skip cleaning of MD containers which are usually
represent fake RAID devices. So, those devices won't be cleaned
and removed at the partitioning step. That will effectively save
those devices for further provisioning purposes.

In order to preserve existing behavior, it will be disabled by
default in conf file.

Will be enabled in a separate patch.

Change-Id: I7be1fc438ffe1fec9b8bfae7e47f50cd3a7c36b7
Related-Bug: #1508908
2015-12-02 13:22:17 +03:00

160 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2015 Mirantis, Inc.
#
# 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 copy
from fuel_agent.objects import base
from fuel_agent.openstack.common import log as logging
LOG = logging.getLogger(__name__)
class Parted(base.Serializable):
def __init__(self, name, label, partitions=None, install_bootloader=False):
self.name = name
self.label = label
self.partitions = partitions or []
self.install_bootloader = install_bootloader
def add_partition(self, **kwargs):
# TODO(kozhukalov): validate before appending
# calculating partition name based on device name and partition count
kwargs['name'] = self.next_name()
kwargs['count'] = self.next_count()
kwargs['device'] = self.name
# if begin is given use its value else use end of last partition
kwargs['begin'] = kwargs.get('begin', self.next_begin())
# if end is given use its value else
# try to calculate it based on size kwarg or
# raise KeyError
# (kwargs.pop['size'] will raise error if size is not set)
kwargs['end'] = kwargs.get('end') or \
kwargs['begin'] + kwargs.pop('size')
# if partition_type is given use its value else
# try to calculate it automatically
kwargs['partition_type'] = \
kwargs.get('partition_type', self.next_type())
partition = Partition(**kwargs)
self.partitions.append(partition)
return partition
@property
def logical(self):
return [x for x in self.partitions if x.type == 'logical']
@property
def primary(self):
return [x for x in self.partitions if x.type == 'primary']
@property
def extended(self):
return next((x for x in self.partitions if x.type == 'extended'), None)
def next_type(self):
if self.label == 'gpt':
return 'primary'
elif self.label == 'msdos':
if self.extended:
return 'logical'
elif len(self.partitions) < 3 and not self.extended:
return 'primary'
elif len(self.partitions) == 3 and not self.extended:
return 'extended'
# NOTE(agordeev): how to reach that condition?
else:
return 'logical'
def next_count(self, next_type=None):
next_type = next_type or self.next_type()
if next_type == 'logical':
return len(self.logical) + 5
return len(self.partitions) + 1
def next_begin(self):
if not self.partitions:
return 1
if self.partitions[-1] == self.extended:
return self.partitions[-1].begin
return self.partitions[-1].end
def next_name(self):
if self.next_type() == 'extended':
return None
separator = ''
special_devices = ('cciss', 'nvme', 'loop', 'md')
if any(n in self.name for n in special_devices):
separator = 'p'
return '%s%s%s' % (self.name, separator, self.next_count())
def partition_by_name(self, name):
return next((x for x in self.partitions if x.name == name), None)
def to_dict(self):
partitions = [partition.to_dict() for partition in self.partitions]
return {
'name': self.name,
'label': self.label,
'partitions': partitions,
'install_bootloader': self.install_bootloader,
}
@classmethod
def from_dict(cls, data):
data = copy.deepcopy(data)
raw_partitions = data.pop('partitions')
partitions = [Partition.from_dict(partition)
for partition in raw_partitions]
return cls(partitions=partitions, **data)
class Partition(base.Serializable):
def __init__(self, name, count, device, begin, end, partition_type,
flags=None, guid=None, configdrive=False, keep_data=False):
self.keep_data = keep_data
self.name = name
self.count = count
self.device = device
self.begin = begin
self.end = end
self.type = partition_type
self.flags = flags or []
self.guid = guid
self.configdrive = configdrive
def set_flag(self, flag):
if flag not in self.flags:
self.flags.append(flag)
def set_guid(self, guid):
self.guid = guid
def to_dict(self):
return {
'name': self.name,
'count': self.count,
'device': self.device,
'begin': self.begin,
'end': self.end,
'partition_type': self.type,
'flags': self.flags,
'guid': self.guid,
'configdrive': self.configdrive,
'keep_data': self.keep_data,
}