Extend usage of jsonschema
Validate all data feeded into bareon by jsonschema, not only data related to disk partitioning. It allows ironic-driver to make early data validation (https://review.openstack.org/410841). Change-Id: Ic1acf6b162ada83950ad4a890d32ca2a80152302
This commit is contained in:
parent
af70312e49
commit
c1fb86038f
@ -0,0 +1,48 @@
|
||||
#
|
||||
# Copyright 2015 Cray Inc. All Rights Reserved.
|
||||
#
|
||||
# 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 json
|
||||
|
||||
import jsonschema.validators
|
||||
|
||||
from bareon import errors
|
||||
|
||||
|
||||
def validate(schema_path, payload):
|
||||
schema = _load_validator_schema(schema_path)
|
||||
|
||||
cls = jsonschema.validators.validator_for(schema)
|
||||
cls.check_schema(schema)
|
||||
schema_validator = cls(schema, format_checker=jsonschema.FormatChecker())
|
||||
|
||||
defects = schema_validator.iter_errors(payload)
|
||||
defects = list(defects)
|
||||
if defects:
|
||||
raise errors.InputDataSchemaValidationError(defects)
|
||||
|
||||
|
||||
def _load_validator_schema(schema_path):
|
||||
try:
|
||||
with open(schema_path, 'rt') as storage:
|
||||
schema = json.load(storage)
|
||||
except IOError as e:
|
||||
raise errors.ApplicationDataCorruptError(
|
||||
'Can\'t read validation schema "{}": {} {}'.format(
|
||||
e.filename, e.errno, e.strerror))
|
||||
except (ValueError, TypeError) as e:
|
||||
raise errors.ApplicationDataCorruptError(
|
||||
'Corrupted validation schema "{}": {}'.format(schema_path, e))
|
||||
|
||||
return schema
|
@ -14,9 +14,13 @@
|
||||
|
||||
import abc
|
||||
import copy
|
||||
import os
|
||||
|
||||
import pkg_resources
|
||||
import six
|
||||
|
||||
import bareon.drivers.data
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class BaseDataDriver(object):
|
||||
@ -26,11 +30,21 @@ class BaseDataDriver(object):
|
||||
methods for getting object schemes, etc.
|
||||
"""
|
||||
|
||||
data_validation_schema = None
|
||||
|
||||
def __init__(self, data):
|
||||
self.validate_data(data)
|
||||
self.data = copy.deepcopy(data)
|
||||
if 'flow' in self.data:
|
||||
self.flow = self.data['flow']
|
||||
|
||||
@classmethod
|
||||
def validate_data(cls, data):
|
||||
root = pkg_resources.resource_filename(
|
||||
'bareon.drivers.data', 'json_schemes')
|
||||
schema_path = os.path.join(root, cls.data_validation_schema)
|
||||
bareon.drivers.data.validate(schema_path, data)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class PartitioningDataDriverMixin(object):
|
||||
@ -82,3 +96,7 @@ class MultibootDeploymentMixin(object):
|
||||
@abc.abstractmethod
|
||||
def get_os_ids(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _partition_data(self):
|
||||
pass
|
||||
|
@ -12,11 +12,14 @@
|
||||
# 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 os
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from bareon import errors
|
||||
from bareon.utils.partition import MiB
|
||||
from bareon.utils.partition import TiB
|
||||
from bareon.utils import utils
|
||||
|
||||
from bareon.drivers.data.base import BaseDataDriver
|
||||
@ -167,7 +170,7 @@ class GenericDataDriver(BaseDataDriver,
|
||||
@property
|
||||
def _small_ks_disks(self):
|
||||
"""Get those disks which are smaller than 2T"""
|
||||
return [d for d in self._ks_disks if d['size'] <= 2 * 1024 * 1024]
|
||||
return [x for x in self._ks_disks if x['size'] <= 2 * TiB / MiB]
|
||||
|
||||
def get_os_ids(self):
|
||||
raise NotImplementedError
|
||||
|
@ -22,7 +22,6 @@ from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from bareon.drivers.data.generic import GenericDataDriver
|
||||
from bareon.drivers.data import ks_spaces_validator
|
||||
from bareon import errors
|
||||
from bareon import objects
|
||||
from bareon.utils import hardware as hu
|
||||
@ -39,11 +38,14 @@ DEFAULT_GRUB_SIZE = 24
|
||||
|
||||
|
||||
class Ironic(GenericDataDriver):
|
||||
data_validation_schema = 'ironic.json'
|
||||
|
||||
_root_on_lvm = None
|
||||
_boot_on_lvm = None
|
||||
|
||||
def __init__(self, data):
|
||||
super(Ironic, self).__init__(data)
|
||||
self._root_on_lvm = None
|
||||
self._boot_on_lvm = None
|
||||
convert_size(self.data['partitions'])
|
||||
|
||||
def _get_image_meta(self):
|
||||
pass
|
||||
@ -120,15 +122,11 @@ class Ironic(GenericDataDriver):
|
||||
scanning/comparing the underlying node hardware.
|
||||
"""
|
||||
LOG.debug('--- Preparing partition scheme ---')
|
||||
# TODO(oberezovskyi): make validator work
|
||||
data = self._partition_data()
|
||||
ks_spaces_validator.validate(data, 'ironic')
|
||||
data = convert_size(data)
|
||||
partition_schema = objects.PartitionScheme()
|
||||
LOG.debug('Looping over all disks in provision data')
|
||||
|
||||
multiboot_installed = False
|
||||
|
||||
LOG.debug('Looping over all disks in provision data')
|
||||
partition_schema = objects.PartitionScheme()
|
||||
for disk in self._ks_disks:
|
||||
# # skipping disk if there are no volumes with size >0
|
||||
# # to be allocated on it which are not boot partitions
|
||||
@ -602,6 +600,18 @@ class Ironic(GenericDataDriver):
|
||||
else:
|
||||
return fnmatch.fnmatch(hu_data.get(id_type, ''), id_value)
|
||||
|
||||
@classmethod
|
||||
def validate_data(cls, data):
|
||||
super(Ironic, cls).validate_data(data)
|
||||
|
||||
disks = data['partitions']
|
||||
|
||||
# scheme is not valid if the number of disks is 0
|
||||
if not [d for d in disks if d['type'] == 'disk']:
|
||||
raise errors.WrongInputDataError(
|
||||
'Invalid partition schema: You must specify at least one '
|
||||
'disk.')
|
||||
|
||||
|
||||
def convert_size(data):
|
||||
data = convert_string_sizes(data)
|
||||
|
@ -1,54 +1,223 @@
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "array",
|
||||
"title": "Ironic partition schema",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"volumes",
|
||||
"size"
|
||||
],
|
||||
"title": "Ironic deployment config schema",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"partitions",
|
||||
"images"
|
||||
],
|
||||
"properties": {
|
||||
"images": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"image_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_uuid": {
|
||||
"type": "string"
|
||||
},
|
||||
"image_pull_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"target": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"volumes": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"boot": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "integer"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"image_deploy_flags": {
|
||||
"type": "object"
|
||||
},
|
||||
"partitions_policy": {
|
||||
"enum": [
|
||||
"verify",
|
||||
"clean",
|
||||
"nailgun_legacy"
|
||||
]
|
||||
},
|
||||
"partitions": {
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"volumes",
|
||||
"size"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"volumes": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size",
|
||||
"vg"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vg": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"pv"
|
||||
]
|
||||
},
|
||||
"keep_data": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"lvm_meta_size": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mount": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"raid",
|
||||
"partition"
|
||||
]
|
||||
},
|
||||
"keep_data": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"file_system": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"boot"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
},
|
||||
"keep_data": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"lvm_meta_pool"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"disk"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"scsi",
|
||||
"path",
|
||||
"name"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"volumes"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_allocate_size": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"min_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"volumes": {
|
||||
"items": {
|
||||
"required": [
|
||||
"type",
|
||||
"size",
|
||||
"vg"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vg": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"pv"
|
||||
]
|
||||
},
|
||||
"lvm_meta_size": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
"name"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -57,142 +226,48 @@
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"raid",
|
||||
"partition"
|
||||
"lv"
|
||||
]
|
||||
},
|
||||
"file_system": {
|
||||
"type": "string"
|
||||
"keep_data": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"file_system": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"boot"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"lvm_meta_pool"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"disk"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"required": [
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"scsi",
|
||||
"path",
|
||||
"name"
|
||||
"vg"
|
||||
]
|
||||
},
|
||||
"keep_data": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"volumes"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_allocate_size": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"min_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"volumes": {
|
||||
"items": {
|
||||
"required": [
|
||||
"type",
|
||||
"size",
|
||||
"name"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mount": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"lv"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"file_system": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"vg"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"deploy_data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kernel_params": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "object"
|
||||
}
|
@ -1,99 +1,314 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "Partition scheme",
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type", "id", "volumes", "name",
|
||||
"size", "extra", "free_space"],
|
||||
"properties": {
|
||||
"type": {"enum": ["disk"]},
|
||||
"id": {"type": "string"},
|
||||
"name": {"type": "string"},
|
||||
"size": {"type": "integer"},
|
||||
"free_space": {"type": "integer"},
|
||||
"extra": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"title": "Nailgun partition schema",
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ks_meta"
|
||||
],
|
||||
"properties": {
|
||||
"hostname": {
|
||||
"type": "string"
|
||||
},
|
||||
"name_servers": {
|
||||
"type": "string"
|
||||
},
|
||||
"name_servers_search": {
|
||||
"type": "string"
|
||||
},
|
||||
"profile": {
|
||||
"type": "string"
|
||||
},
|
||||
"ks_meta": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"pm_data"
|
||||
],
|
||||
"properties": {
|
||||
"timezone": {
|
||||
"type": "string"
|
||||
},
|
||||
"master_ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"gw": {
|
||||
"type": "string"
|
||||
},
|
||||
"auth_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"pm_data": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"ks_spaces"
|
||||
],
|
||||
"properties": {
|
||||
"kernel_params": {
|
||||
"type": "string"
|
||||
},
|
||||
"ks_spaces": {
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"volumes",
|
||||
"name",
|
||||
"size",
|
||||
"extra",
|
||||
"free_space"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"extra": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"free_space": {
|
||||
"type": "integer"
|
||||
},
|
||||
"volumes": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type", "size",
|
||||
"lvm_meta_size", "vg"],
|
||||
"properties": {
|
||||
"type": {"enum": ["pv"]},
|
||||
"size": {"type": "integer"},
|
||||
"lvm_meta_size": {"type": "integer"},
|
||||
"vg": {"type": "string"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type", "size"],
|
||||
"properties": {
|
||||
"type": {"enum": ["raid",
|
||||
"partition"]},
|
||||
"size": {"type": "integer"},
|
||||
"mount": {"type": "string"},
|
||||
"file_system": {"type": "string"},
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type", "size"],
|
||||
"properties": {
|
||||
"type": {"enum": ["boot"]},
|
||||
"size": {"type": "integer"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type", "size"],
|
||||
"properties": {
|
||||
"type": {"enum": ["lvm_meta_pool"]},
|
||||
"size": {"type": "integer"}
|
||||
}
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size",
|
||||
"vg"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vg": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"pv"
|
||||
]
|
||||
},
|
||||
"lvm_meta_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mount": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"raid",
|
||||
"partition"
|
||||
]
|
||||
},
|
||||
"file_system": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"boot"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"size"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"lvm_meta_pool"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"disk"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"type",
|
||||
"id",
|
||||
"volumes"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_allocate_size": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"min_size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"volumes": {
|
||||
"items": {
|
||||
"required": [
|
||||
"type",
|
||||
"size",
|
||||
"name"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mount": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"lv"
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"file_system": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"vg"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"image_data": {
|
||||
"type": "object"
|
||||
},
|
||||
"repo_setup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repos": {
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"puppet_master": {
|
||||
"type": "string"
|
||||
},
|
||||
"puppet_enable": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type", "id", "volumes"],
|
||||
"properties": {
|
||||
"type": {"enum": ["vg"]},
|
||||
"id": {"type": "string"},
|
||||
"label": {"type": "string"},
|
||||
"min_size": {"type": "integer"},
|
||||
"_allocate_size": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["type", "size", "name"],
|
||||
"properties": {
|
||||
"type": {"enum": ["lv"]},
|
||||
"size": {"type": "integer"},
|
||||
"name": {"type": "string"},
|
||||
"mount": {"type": "string"},
|
||||
"file_system": {"type": "string"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"type": "integer"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"mco_pskey": {
|
||||
"type": "string"
|
||||
},
|
||||
"mco_vhost": {
|
||||
"type": "string"
|
||||
},
|
||||
"mco_host": {
|
||||
"type": "string"
|
||||
},
|
||||
"mco_user": {
|
||||
"type": "string"
|
||||
},
|
||||
"mco_password": {
|
||||
"type": "string"
|
||||
},
|
||||
"mco_connector": {
|
||||
"type": "string"
|
||||
},
|
||||
"mco_enable": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "integer"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"kernel_options": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"netcfg/choose_interface": {
|
||||
"type": "string"
|
||||
},
|
||||
"udevrules": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"interfaces": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
# Copyright 2014 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 json
|
||||
import jsonschema
|
||||
import os
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from bareon import errors
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def validate(data, schema_file='nailgun'):
|
||||
"""Validates a given partition scheme using jsonschema.
|
||||
|
||||
:param scheme: partition scheme to validate
|
||||
"""
|
||||
base_path = os.path.dirname(__file__)
|
||||
schemas_path = os.path.join(base_path, 'json_schemes')
|
||||
with open(os.path.join(schemas_path, '%s.json' % schema_file)) as file:
|
||||
schema = json.load(file)
|
||||
|
||||
try:
|
||||
checker = jsonschema.FormatChecker()
|
||||
jsonschema.validate(data, schema,
|
||||
format_checker=checker)
|
||||
except Exception as exc:
|
||||
LOG.exception(exc)
|
||||
raise errors.WrongPartitionSchemeError(str(exc))
|
||||
|
||||
# scheme is not valid if the number of disks is 0
|
||||
if not [d for d in data if d['type'] == 'disk']:
|
||||
raise errors.WrongPartitionSchemeError(
|
||||
'Partition scheme seems empty')
|
||||
|
||||
# TODO(lobur): Must be done after unit conversion
|
||||
# for space in data:
|
||||
# for volume in space.get('volumes', []):
|
||||
# if volume['size'] > 16777216 and volume.get('mount') == '/':
|
||||
# raise errors.WrongPartitionSchemeError(
|
||||
# 'Root file system must be less than 16T')
|
||||
|
||||
# TODO(kozhukalov): need to have additional logical verifications
|
||||
# maybe sizes and format of string values
|
@ -32,7 +32,6 @@ from bareon.drivers.data.base import ConfigDriveDataDriverMixin
|
||||
from bareon.drivers.data.base import GrubBootloaderDataDriverMixin
|
||||
from bareon.drivers.data.base import PartitioningDataDriverMixin
|
||||
from bareon.drivers.data.base import ProvisioningDataDriverMixin
|
||||
from bareon.drivers.data import ks_spaces_validator
|
||||
from bareon import errors
|
||||
from bareon import objects
|
||||
|
||||
@ -84,6 +83,9 @@ class Nailgun(BaseDataDriver,
|
||||
GrubBootloaderDataDriverMixin):
|
||||
"""Driver for parsing regular volumes metadata from Nailgun."""
|
||||
|
||||
data_validation_schema = 'nailgun.json'
|
||||
partitions_policy = 'nailgun_legacy'
|
||||
|
||||
def __init__(self, data):
|
||||
super(Nailgun, self).__init__(data)
|
||||
|
||||
@ -336,15 +338,13 @@ class Nailgun(BaseDataDriver,
|
||||
|
||||
def parse_partition_scheme(self):
|
||||
LOG.debug('--- Preparing partition scheme ---')
|
||||
data = self.partition_data()
|
||||
ks_spaces_validator.validate(data)
|
||||
partition_scheme = objects.PartitionScheme()
|
||||
|
||||
ceph_osds = self._num_ceph_osds()
|
||||
journals_left = ceph_osds
|
||||
ceph_journals = self._num_ceph_journals()
|
||||
|
||||
LOG.debug('Looping over all disks in provision data')
|
||||
partition_scheme = objects.PartitionScheme()
|
||||
for disk in self.ks_disks:
|
||||
# skipping disk if there are no volumes with size >0
|
||||
# to be allocated on it which are not boot partitions
|
||||
@ -710,6 +710,18 @@ class Nailgun(BaseDataDriver,
|
||||
)
|
||||
return image_scheme
|
||||
|
||||
@classmethod
|
||||
def validate_data(cls, data):
|
||||
super(Nailgun, cls).validate_data(data)
|
||||
|
||||
disks = data['ks_meta']['pm_data']['ks_spaces']
|
||||
|
||||
# scheme is not valid if the number of disks is 0
|
||||
if not [d for d in disks if d['type'] == 'disk']:
|
||||
raise errors.WrongInputDataError(
|
||||
'Invalid partition schema: You must specify at least one '
|
||||
'disk.')
|
||||
|
||||
|
||||
class Ironic(Nailgun):
|
||||
def __init__(self, data):
|
||||
@ -723,6 +735,7 @@ class NailgunBuildImage(BaseDataDriver,
|
||||
ProvisioningDataDriverMixin,
|
||||
ConfigDriveDataDriverMixin,
|
||||
GrubBootloaderDataDriverMixin):
|
||||
data_validation_schema = 'nailgun-build-image.json'
|
||||
|
||||
DEFAULT_TRUSTY_PACKAGES = [
|
||||
"acl",
|
||||
|
@ -19,10 +19,32 @@ class BaseError(Exception):
|
||||
super(BaseError, self).__init__(message, *args, **kwargs)
|
||||
|
||||
|
||||
class ApplicationDataCorruptError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class WrongInputDataError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class InputDataSchemaValidationError(WrongInputDataError):
|
||||
def __init__(self, defects):
|
||||
human_readable_defects = []
|
||||
for idx, d in enumerate(defects):
|
||||
path = [''] + list(d.path)
|
||||
path = '/'.join((str(x) for x in path))
|
||||
human_readable_defects.append(
|
||||
'#{} ({}): {}'.format(idx, path, d.message))
|
||||
|
||||
indent = ' ' * 4
|
||||
separator = '\n{}'.format(indent)
|
||||
message = 'Invalid input data:\n{}{}'.format(
|
||||
indent, separator.join(human_readable_defects))
|
||||
|
||||
super(WrongInputDataError, self).__init__(message, defects)
|
||||
self.defects = defects
|
||||
|
||||
|
||||
class WrongPartitionSchemeError(BaseError):
|
||||
pass
|
||||
|
||||
|
12
bareon/tests/fixtures/simple_nailgun_driver.json
vendored
12
bareon/tests/fixtures/simple_nailgun_driver.json
vendored
@ -63,7 +63,17 @@
|
||||
"mco_identity": -1,
|
||||
"pm_data": {
|
||||
"kernel_params": "console=ttyS0,9600 console=tty0 rootdelay=90 nomodeset",
|
||||
"ks_spaces": []
|
||||
"ks_spaces": [
|
||||
{
|
||||
"type": "disk",
|
||||
"id": "dummy-disk-id",
|
||||
"name": "dummy0",
|
||||
"free_space": 0,
|
||||
"size": 128,
|
||||
"extra": [],
|
||||
"volumes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"puppet_auto_setup": 1,
|
||||
"puppet_enable": 0,
|
||||
|
@ -17,12 +17,14 @@ import mock
|
||||
import unittest2
|
||||
|
||||
from bareon.drivers.data import generic
|
||||
from bareon.utils.partition import MiB
|
||||
from bareon.utils.partition import TiB
|
||||
|
||||
|
||||
class TestKsDisks(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestKsDisks, self).__init__(*args, **kwargs)
|
||||
self.driver = generic.GenericDataDriver({})
|
||||
def setUp(self):
|
||||
super(TestKsDisks, self).setUp()
|
||||
self.driver = _DummyDataDriver({})
|
||||
self.driver._partition_data = self.mock_part_data = mock.MagicMock()
|
||||
|
||||
def test_no_partition_data(self):
|
||||
@ -72,9 +74,9 @@ class TestKsDisks(unittest2.TestCase):
|
||||
|
||||
|
||||
class TestKsVgs(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestKsVgs, self).__init__(*args, **kwargs)
|
||||
self.driver = generic.GenericDataDriver({})
|
||||
def setUp(self):
|
||||
super(TestKsVgs, self).setUp()
|
||||
self.driver = _DummyDataDriver({})
|
||||
self.driver._partition_data = self.mock_part_data = mock.MagicMock()
|
||||
|
||||
def test_no_partition_data(self):
|
||||
@ -112,9 +114,9 @@ class TestKsVgs(unittest2.TestCase):
|
||||
|
||||
|
||||
class TestSmallKsDisks(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestSmallKsDisks, self).__init__(*args, **kwargs)
|
||||
self.driver = generic.GenericDataDriver({})
|
||||
def setUp(self):
|
||||
super(TestSmallKsDisks, self).setUp()
|
||||
self.driver = _DummyDataDriver({})
|
||||
self.driver._partition_data = self.mock_part_data = mock.MagicMock()
|
||||
|
||||
def test_no_partition_data(self):
|
||||
@ -128,8 +130,8 @@ class TestSmallKsDisks(unittest2.TestCase):
|
||||
|
||||
def test_no_partitions_valid_size(self):
|
||||
self.mock_part_data.return_value = [
|
||||
{'size': 3 * 1024 * 1024, 'type': 'disk'},
|
||||
{'size': 5 * 1024 * 1024, 'type': 'disk'}
|
||||
{'size': 3 * TiB, 'type': 'disk'},
|
||||
{'size': 5 * TiB, 'type': 'disk'}
|
||||
]
|
||||
desired = []
|
||||
|
||||
@ -140,10 +142,10 @@ class TestSmallKsDisks(unittest2.TestCase):
|
||||
|
||||
def test_valid_data(self):
|
||||
self.mock_part_data.return_value = [
|
||||
{'size': 3 * 1024 * 1024, 'type': 'vg'},
|
||||
{'size': 1 * 1024 * 1024, 'type': 'disk'}
|
||||
{'size': 3 * MiB, 'type': 'vg'},
|
||||
{'size': 1 * MiB, 'type': 'disk'}
|
||||
]
|
||||
desired = [{'size': 1 * 1024 * 1024, 'type': 'disk'}]
|
||||
desired = [{'size': 1 * MiB, 'type': 'disk'}]
|
||||
|
||||
result = self.driver._small_ks_disks
|
||||
|
||||
@ -152,9 +154,9 @@ class TestSmallKsDisks(unittest2.TestCase):
|
||||
|
||||
|
||||
class TestGetLabel(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestGetLabel, self).__init__(*args, **kwargs)
|
||||
self.driver = generic.GenericDataDriver({})
|
||||
def setUp(self):
|
||||
super(TestGetLabel, self).setUp()
|
||||
self.driver = _DummyDataDriver({})
|
||||
|
||||
def test_no_label(self):
|
||||
label = None
|
||||
@ -179,3 +181,12 @@ class TestGetLabel(unittest2.TestCase):
|
||||
result = self.driver._getlabel(label)
|
||||
|
||||
self.assertEqual(result, desired)
|
||||
|
||||
|
||||
class _DummyDataDriver(generic.GenericDataDriver):
|
||||
def _partition_data(self):
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def validate_data(cls, payload):
|
||||
pass
|
||||
|
@ -226,11 +226,14 @@ LIST_BLOCK_DEVICES_SAMPLE = [
|
||||
]
|
||||
|
||||
|
||||
class TestIronicMatch(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestIronicMatch, self).__init__(*args, **kwargs)
|
||||
self.data_driver = ironic.Ironic('')
|
||||
class _IronicTest(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(_IronicTest, self).setUp()
|
||||
with mock.patch.object(ironic.Ironic, 'validate_data'):
|
||||
self.data_driver = ironic.Ironic({'partitions': []})
|
||||
|
||||
|
||||
class TestIronicMatch(_IronicTest):
|
||||
def test_match_device_by_scsi_matches(self):
|
||||
# matches by scsi address
|
||||
fake_ks_disk = {
|
||||
@ -319,10 +322,11 @@ class TestIronicMatch(unittest2.TestCase):
|
||||
self.data_driver._match_device(fake_hu_disk, fake_ks_disk))
|
||||
|
||||
|
||||
@mock.patch('bareon.drivers.data.ironic.hu.scsi_address')
|
||||
class TestNailgunMockedMeta(unittest2.TestCase):
|
||||
def test_partition_scheme(self, mock_scsi_address):
|
||||
data_driver = ironic.Ironic(PROVISION_SAMPLE_DATA_SWIFT)
|
||||
@mock.patch('bareon.utils.hardware.scsi_address', mock.Mock())
|
||||
class TestNailgunMockedMeta(_IronicTest):
|
||||
def test_partition_scheme(self):
|
||||
with mock.patch.object(ironic.Ironic, 'validate_data'):
|
||||
data_driver = ironic.Ironic(PROVISION_SAMPLE_DATA_SWIFT)
|
||||
|
||||
data_driver.get_image_ids = mock.MagicMock
|
||||
mock_devices = data_driver._get_block_devices = mock.MagicMock()
|
||||
@ -336,18 +340,17 @@ class TestNailgunMockedMeta(unittest2.TestCase):
|
||||
self.assertEqual(3, len(p_scheme.parteds))
|
||||
|
||||
|
||||
@mock.patch('bareon.drivers.data.ironic.hu.get_block_devices_from_udev_db')
|
||||
class TestGetBlockDevices(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestGetBlockDevices, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic('')
|
||||
self.mock_devices = mock.MagicMock()
|
||||
self.driver._get_block_device_info = self.mock_devices
|
||||
@mock.patch('bareon.utils.hardware.get_block_devices_from_udev_db')
|
||||
class TestGetBlockDevices(_IronicTest):
|
||||
def setUp(self):
|
||||
super(TestGetBlockDevices, self).setUp()
|
||||
self.mock_devices = mock.Mock()
|
||||
self.data_driver._get_block_device_info = self.mock_devices
|
||||
|
||||
def test_no_devices(self, mock_get_block_devices_from_udev_db):
|
||||
mock_get_block_devices_from_udev_db.return_value = []
|
||||
|
||||
result = self.driver._get_block_devices()
|
||||
result = self.data_driver._get_block_devices()
|
||||
self.assertEqual(result, [])
|
||||
mock_get_block_devices_from_udev_db.assert_called_once_with()
|
||||
self.assertEqual(self.mock_devices.call_count, 0)
|
||||
@ -357,32 +360,30 @@ class TestGetBlockDevices(unittest2.TestCase):
|
||||
|
||||
mock_get_block_devices_from_udev_db.return_value = [data]
|
||||
self.mock_devices.return_value = block_device = 'test_value'
|
||||
result = self.driver._get_block_devices()
|
||||
result = self.data_driver._get_block_devices()
|
||||
self.assertEqual(result, [block_device])
|
||||
mock_get_block_devices_from_udev_db.assert_called_once_with()
|
||||
self.mock_devices.assert_called_once_with(data)
|
||||
|
||||
|
||||
@mock.patch('bareon.drivers.data.ironic.hu.get_device_ids')
|
||||
@mock.patch('bareon.drivers.data.ironic.hu.get_device_info')
|
||||
@mock.patch('bareon.drivers.data.ironic.hu.scsi_address')
|
||||
class TestGetBlockDevice(unittest2.TestCase):
|
||||
@mock.patch('bareon.utils.hardware.get_device_ids')
|
||||
@mock.patch('bareon.utils.hardware.get_device_info')
|
||||
@mock.patch('bareon.utils.hardware.scsi_address')
|
||||
class TestGetBlockDevice(_IronicTest):
|
||||
def test_no_device_info(self, mock_scsi_address, mock_get_device_info,
|
||||
mock_get_device_ids):
|
||||
data_driver = ironic.Ironic('')
|
||||
device = 'fake_device'
|
||||
|
||||
mock_scsi_address.return_value = None
|
||||
mock_get_device_info.return_value = {}
|
||||
mock_get_device_ids.return_value = []
|
||||
|
||||
result = data_driver._get_block_device_info(device)
|
||||
result = self.data_driver._get_block_device_info(device)
|
||||
|
||||
self.assertEqual(result, {'name': 'fake_device'})
|
||||
|
||||
def test_device_info(self, mock_scsi_address, mock_get_device_info,
|
||||
mock_get_device_ids):
|
||||
data_driver = ironic.Ironic('')
|
||||
device = 'fake_device'
|
||||
devpath = ['test/devpath']
|
||||
uspec = {'DEVPATH': devpath}
|
||||
@ -396,19 +397,19 @@ class TestGetBlockDevice(unittest2.TestCase):
|
||||
desired = {'path': devpath, 'name': device, 'scsi': scsi_address,
|
||||
'uspec': uspec}
|
||||
|
||||
result = data_driver._get_block_device_info(device)
|
||||
result = self.data_driver._get_block_device_info(device)
|
||||
self.assertEqual(result, desired)
|
||||
mock_get_device_info.assert_called_once_with(device)
|
||||
mock_scsi_address.assert_called_once_with(device)
|
||||
|
||||
|
||||
@mock.patch('bareon.drivers.data.ironic.Ironic.validate_data', mock.Mock())
|
||||
class TestGetGrub(unittest2.TestCase):
|
||||
|
||||
@mock.patch('bareon.utils.utils.parse_kernel_cmdline')
|
||||
def test_kernel_params(self, cmdline_mock):
|
||||
data = {'deploy_data': {'kernel_params': "test_param=test_val",
|
||||
'other_data': 'test'},
|
||||
'partitions': 'fake_shema'}
|
||||
'partitions': {}}
|
||||
cmdline_mock.return_value = {
|
||||
"BOOTIF": "01-52-54-00-a5-55-58",
|
||||
"extrastuff": "test123"
|
||||
@ -421,24 +422,24 @@ class TestGetGrub(unittest2.TestCase):
|
||||
|
||||
def test_no_kernel_params(self):
|
||||
data = {'deploy_data': {'other_data': "test"},
|
||||
'partitions': 'fake_shema'}
|
||||
'partitions': {}}
|
||||
data_driver = ironic.Ironic(data)
|
||||
|
||||
self.assertEqual('', data_driver.grub.kernel_params)
|
||||
|
||||
|
||||
@mock.patch('bareon.drivers.data.ironic.Ironic.validate_data', mock.Mock())
|
||||
class TestPartitionsPolicy(unittest2.TestCase):
|
||||
|
||||
def test_partitions_policy(self):
|
||||
data = {'partitions_policy': "test_value",
|
||||
'partitions': 'fake_shema'}
|
||||
'partitions': {}}
|
||||
|
||||
data_driver = ironic.Ironic(data)
|
||||
|
||||
self.assertEqual('test_value', data_driver.partitions_policy)
|
||||
|
||||
def test_partitions_policy_default(self):
|
||||
data = {'partitions': 'fake_shema'}
|
||||
data = {'partitions': {}}
|
||||
|
||||
data_driver = ironic.Ironic(data)
|
||||
|
||||
|
@ -23,10 +23,24 @@ from bareon.utils import hardware as hu
|
||||
from bareon.utils import utils
|
||||
|
||||
|
||||
class TestGetImageSchema(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestGetImageSchema, self).__init__(*args, **kwargs)
|
||||
class IronicTestAbstract(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(IronicTestAbstract, self).setUp()
|
||||
self.driver = self.new_data_driver()
|
||||
|
||||
@staticmethod
|
||||
def new_data_driver(payload=None):
|
||||
if payload is None:
|
||||
payload = {}
|
||||
payload.setdefault('partitions', [])
|
||||
|
||||
with mock.patch.object(ironic.Ironic, 'validate_data'):
|
||||
driver = ironic.Ironic(payload)
|
||||
|
||||
return driver
|
||||
|
||||
|
||||
class TestGetImageSchema(IronicTestAbstract):
|
||||
def test_get_image_schema(self):
|
||||
image_uri = 'test_uri'
|
||||
rsync_flags = '-a -X'
|
||||
@ -38,9 +52,9 @@ class TestGetImageSchema(unittest2.TestCase):
|
||||
'name': 'test'
|
||||
}
|
||||
], 'image_deploy_flags': deploy_flags}
|
||||
self.driver = ironic.Ironic(data)
|
||||
driver = self.new_data_driver(data)
|
||||
|
||||
result = self.driver._get_image_scheme()
|
||||
result = driver._get_image_scheme()
|
||||
|
||||
self.assertEqual(len(result.images), 1)
|
||||
|
||||
@ -49,11 +63,7 @@ class TestGetImageSchema(unittest2.TestCase):
|
||||
self.assertEqual(result_image.uri, image_uri)
|
||||
|
||||
|
||||
class TestMatchDevice(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestMatchDevice, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic({})
|
||||
|
||||
class TestMatchDevice(IronicTestAbstract):
|
||||
def test_match_list_value(self):
|
||||
test_type = 'path'
|
||||
test_value = 'test_path'
|
||||
@ -95,10 +105,9 @@ class TestMatchDevice(unittest2.TestCase):
|
||||
self.assertFalse(result)
|
||||
|
||||
|
||||
class TestDiskDev(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestDiskDev, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic({})
|
||||
class TestDiskDev(IronicTestAbstract):
|
||||
def setUp(self):
|
||||
super(TestDiskDev, self).setUp()
|
||||
self.driver._match_device = self.mock_match_device = mock.MagicMock()
|
||||
|
||||
def test_no_valid_disks(self):
|
||||
@ -133,11 +142,7 @@ class TestDiskDev(unittest2.TestCase):
|
||||
self.assertEqual(result, 'disk1')
|
||||
|
||||
|
||||
class TestMatchPartition(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestMatchPartition, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic({})
|
||||
|
||||
class TestMatchPartition(IronicTestAbstract):
|
||||
def test_match_list_value(self):
|
||||
test_type = 'path'
|
||||
test_value = 'test_path'
|
||||
@ -221,10 +226,9 @@ class TestMatchPartition(unittest2.TestCase):
|
||||
self.assertFalse(result)
|
||||
|
||||
|
||||
class TestDiskPartition(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestDiskPartition, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic({})
|
||||
class TestDiskPartition(IronicTestAbstract):
|
||||
def setUp(self):
|
||||
super(TestDiskPartition, self).setUp()
|
||||
self.driver._match_data_by_pattern = \
|
||||
self.mock_match_part = mock.MagicMock()
|
||||
|
||||
@ -262,11 +266,7 @@ class TestDiskPartition(unittest2.TestCase):
|
||||
|
||||
@mock.patch('bareon.utils.hardware.get_partitions_from_udev_db')
|
||||
@mock.patch('bareon.utils.hardware.get_device_ids')
|
||||
class TestGetPartitionIds(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestGetPartitionIds, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic({})
|
||||
|
||||
class TestGetPartitionIds(IronicTestAbstract):
|
||||
def test_no_devices(self, mock_ids, mock_partitions):
|
||||
mock_partitions.return_value = []
|
||||
desired = []
|
||||
@ -299,22 +299,21 @@ class TestGetPartitionIds(unittest2.TestCase):
|
||||
mock_ids.assert_has_calls([mock.call(part) for part in parts])
|
||||
|
||||
|
||||
class TestFindHwFstab(unittest2.TestCase):
|
||||
class TestFindHwFstab(IronicTestAbstract):
|
||||
@mock.patch.object(utils, 'execute')
|
||||
def test__find_hw_fstab_success_single_disk(self, exec_mock):
|
||||
fs = namedtuple('fs', 'mount type device os_id')
|
||||
fss = [fs(mount='/', type='ext4', device='/dev/sda', os_id='1'),
|
||||
fs(mount='/usr', type='ext4', device='/dev/sdb', os_id='1')]
|
||||
|
||||
data_driver = ironic.Ironic({})
|
||||
data_driver._partition_scheme = ironic.objects.PartitionScheme()
|
||||
data_driver.partition_scheme.fss = fss
|
||||
self.driver._partition_scheme = ironic.objects.PartitionScheme()
|
||||
self.driver.partition_scheme.fss = fss
|
||||
|
||||
exec_mock.side_effect = [('stdout', 'stderr'),
|
||||
('fstab_1', 'stderr'),
|
||||
('stdout', 'stderr')]
|
||||
|
||||
res = data_driver._find_hw_fstab()
|
||||
res = self.driver._find_hw_fstab()
|
||||
|
||||
self.assertEqual('\n'.join(('fstab_1',)), res)
|
||||
|
||||
@ -325,9 +324,8 @@ class TestFindHwFstab(unittest2.TestCase):
|
||||
fs(mount='/usr', type='ext4', device='/dev/sdb', os_id='1'),
|
||||
fs(mount='/', type='ext4', device='/dev/sda', os_id='2')]
|
||||
|
||||
data_driver = ironic.Ironic({})
|
||||
data_driver._partition_scheme = ironic.objects.PartitionScheme()
|
||||
data_driver.partition_scheme.fss = fss
|
||||
self.driver._partition_scheme = ironic.objects.PartitionScheme()
|
||||
self.driver.partition_scheme.fss = fss
|
||||
|
||||
exec_mock.side_effect = [('stdout', 'stderr'),
|
||||
('fstab_1', 'stderr'),
|
||||
@ -336,7 +334,7 @@ class TestFindHwFstab(unittest2.TestCase):
|
||||
('fstab_2', 'stderr'),
|
||||
('stdout', 'stderr')]
|
||||
|
||||
res = data_driver._find_hw_fstab()
|
||||
res = self.driver._find_hw_fstab()
|
||||
|
||||
self.assertEqual('\n'.join(('fstab_1', 'fstab_2')), res)
|
||||
|
||||
@ -346,15 +344,14 @@ class TestFindHwFstab(unittest2.TestCase):
|
||||
fss = [fs(mount='/etc', type='ext4', device='/dev/sda', os_id='1'),
|
||||
fs(mount='/', type='ext4', device='/dev/sda', os_id='1')]
|
||||
|
||||
data_driver = ironic.Ironic({})
|
||||
data_driver._partition_scheme = ironic.objects.PartitionScheme()
|
||||
data_driver.partition_scheme.fss = fss
|
||||
self.driver._partition_scheme = ironic.objects.PartitionScheme()
|
||||
self.driver.partition_scheme.fss = fss
|
||||
exec_mock.side_effect = [('stdout', 'stderr'),
|
||||
errors.ProcessExecutionError,
|
||||
('stdout', 'stderr')]
|
||||
|
||||
self.assertRaises(errors.HardwarePartitionSchemeCannotBeReadError,
|
||||
data_driver._find_hw_fstab)
|
||||
self.driver._find_hw_fstab)
|
||||
|
||||
|
||||
class TestConvertStringSize(unittest2.TestCase):
|
||||
@ -847,10 +844,9 @@ class TestConvertPercentSizes(unittest2.TestCase):
|
||||
map(lambda r, d: self.assertDictEqual(r, d), result, desired)
|
||||
|
||||
|
||||
class TestProcessPartition(unittest2.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestProcessPartition, self).__init__(*args, **kwargs)
|
||||
self.driver = ironic.Ironic({})
|
||||
class TestProcessPartition(IronicTestAbstract):
|
||||
def setUp(self):
|
||||
super(TestProcessPartition, self).setUp()
|
||||
self.driver._partition_data = self.mock_part_data = mock.MagicMock()
|
||||
self.driver._add_partition = self.mock_add_part = mock.MagicMock()
|
||||
self.mock_add_part.return_value = self.mock_part = mock.MagicMock()
|
||||
|
@ -16,10 +16,10 @@ import copy
|
||||
|
||||
import unittest2
|
||||
|
||||
from bareon.drivers.data import ks_spaces_validator as kssv
|
||||
from bareon.drivers.data import ironic
|
||||
from bareon import errors
|
||||
|
||||
SAMPLE_SCHEME = [
|
||||
SAMPLE_CHUNK_PARTITIONS = [
|
||||
{
|
||||
"id": {
|
||||
"type": "name",
|
||||
@ -175,67 +175,108 @@ SAMPLE_SCHEME = [
|
||||
}
|
||||
]
|
||||
|
||||
SAMPLE_PAYLOAD = {
|
||||
'partitions': SAMPLE_CHUNK_PARTITIONS,
|
||||
'images': []
|
||||
}
|
||||
|
||||
class TestKSSpacesValidator(unittest2.TestCase):
|
||||
|
||||
class TestIronicDataValidator(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(TestKSSpacesValidator, self).setUp()
|
||||
self.fake_scheme = copy.deepcopy(SAMPLE_SCHEME)
|
||||
super(TestIronicDataValidator, self).setUp()
|
||||
self.payload = copy.deepcopy(SAMPLE_PAYLOAD)
|
||||
|
||||
def test_validate_ok(self):
|
||||
kssv.validate(self.fake_scheme, 'ironic')
|
||||
def test_no_error(self):
|
||||
ironic.Ironic.validate_data(self.payload)
|
||||
|
||||
def test_validate_jsoschema_fail(self):
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, [{}], 'ironic')
|
||||
def test_fail(self):
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data, [{}])
|
||||
|
||||
def test_validate_no_disks_fail(self):
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme[-2:], 'ironic')
|
||||
def test_required_fields(self):
|
||||
for field in ['partitions']:
|
||||
payload = copy.deepcopy(self.payload)
|
||||
del payload[field]
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
payload)
|
||||
|
||||
def test_validate_16T_root_volume_fail(self):
|
||||
self.fake_scheme[3]['volumes'][0]['size'] = 16777216 + 1
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'ironic')
|
||||
def test_disks_no_disks_fail(self):
|
||||
partitions = self.payload['partitions']
|
||||
partitions[:-2] = []
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_volume_type_fail(self):
|
||||
@unittest2.skip(
|
||||
'FIXME(dbogun): Invalid test - failed because invalid data '
|
||||
'type(expect sting in size field) but not because illegal partition '
|
||||
'size')
|
||||
def test_disks_16T_root_volume_fail(self):
|
||||
partitions = self.payload['partitions']
|
||||
partitions[3]['volumes'][0]['size'] = 16777216 + 1
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_disks_volume_type_fail(self):
|
||||
incorrect_values_for_type = [
|
||||
False, True, 0, 1, None, object
|
||||
]
|
||||
partitions = self.payload['partitions']
|
||||
for value in incorrect_values_for_type:
|
||||
self.fake_scheme[0]['volumes'][1]['type'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'ironic')
|
||||
partitions[0]['volumes'][1]['type'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_volume_size_fail(self):
|
||||
def test_disks_volume_size_fail(self):
|
||||
incorrect_values_for_size = [
|
||||
False, True, 0, 1, None, object
|
||||
]
|
||||
partitions = self.payload['partitions']
|
||||
for value in incorrect_values_for_size:
|
||||
self.fake_scheme[0]['volumes'][1]['size'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'ironic')
|
||||
partitions[0]['volumes'][1]['size'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_device_id_fail(self):
|
||||
def test_disks_device_id_fail(self):
|
||||
incorrect_values_for_id = [
|
||||
False, True, 0, 1, None, object
|
||||
]
|
||||
partitions = self.payload['partitions']
|
||||
for value in incorrect_values_for_id:
|
||||
self.fake_scheme[0]['id'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'ironic')
|
||||
partitions[0]['id'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_missed_property(self):
|
||||
def test_disks_missed_property_fail(self):
|
||||
required = ['id', 'size', 'volumes', 'type']
|
||||
for prop in required:
|
||||
fake = copy.deepcopy(self.fake_scheme)
|
||||
del fake[0][prop]
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, fake, 'ironic')
|
||||
fake = copy.deepcopy(self.payload)
|
||||
partitions = fake['partitions']
|
||||
del partitions[0][prop]
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data, fake)
|
||||
|
||||
def test_validate_missed_volume_property(self):
|
||||
required = ['type', 'size', 'vg']
|
||||
for prop in required:
|
||||
fake = copy.deepcopy(self.fake_scheme)
|
||||
del fake[0]['volumes'][3][prop]
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, fake, 'ironic')
|
||||
fake = copy.deepcopy(self.payload)
|
||||
partitions = fake['partitions']
|
||||
del partitions[0]['volumes'][3][prop]
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data, fake)
|
||||
|
||||
def test_disks_keep_data_flag_type(self):
|
||||
partitions = self.payload['partitions']
|
||||
partitions[0]['volumes'][1]['keep_data'] = "True"
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, ironic.Ironic.validate_data,
|
||||
self.payload)
|
||||
|
||||
@staticmethod
|
||||
def _get_disks(payload):
|
||||
return payload['partitions']
|
@ -1,205 +0,0 @@
|
||||
# Copyright 2014 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
|
||||
|
||||
import unittest2
|
||||
|
||||
from bareon.drivers.data import ks_spaces_validator as kssv
|
||||
from bareon import errors
|
||||
|
||||
SAMPLE_SCHEME = [
|
||||
{
|
||||
"name": "sda",
|
||||
"extra": [
|
||||
"disk/by-id/scsi-SATA_VBOX_HARDDISK_VB69050467-b385c7cd",
|
||||
"disk/by-id/ata-VBOX_HARDDISK_VB69050467-b385c7cd"
|
||||
],
|
||||
"free_space": 64907,
|
||||
"volumes": [
|
||||
{
|
||||
"type": "boot",
|
||||
"size": 300
|
||||
},
|
||||
{
|
||||
"mount": "/boot",
|
||||
"size": 200,
|
||||
"type": "raid",
|
||||
"file_system": "ext2",
|
||||
"name": "Boot"
|
||||
},
|
||||
{
|
||||
"type": "lvm_meta_pool",
|
||||
"size": 0
|
||||
},
|
||||
{
|
||||
"size": 19438,
|
||||
"type": "pv",
|
||||
"lvm_meta_size": 64,
|
||||
"vg": "os"
|
||||
},
|
||||
{
|
||||
"size": 45597,
|
||||
"type": "pv",
|
||||
"lvm_meta_size": 64,
|
||||
"vg": "image"
|
||||
}
|
||||
],
|
||||
"type": "disk",
|
||||
"id": "sda",
|
||||
"size": 65535
|
||||
},
|
||||
{
|
||||
"name": "sdb",
|
||||
"extra": [
|
||||
"disk/by-id/scsi-SATA_VBOX_HARDDISK_VBf2923215-708af674",
|
||||
"disk/by-id/ata-VBOX_HARDDISK_VBf2923215-708af674"
|
||||
],
|
||||
"free_space": 64907,
|
||||
"volumes": [
|
||||
{
|
||||
"type": "boot",
|
||||
"size": 300
|
||||
},
|
||||
{
|
||||
"mount": "/boot",
|
||||
"size": 200,
|
||||
"type": "raid",
|
||||
"file_system": "ext2",
|
||||
"name": "Boot"
|
||||
},
|
||||
{
|
||||
"type": "lvm_meta_pool",
|
||||
"size": 64
|
||||
},
|
||||
{
|
||||
"size": 0,
|
||||
"type": "pv",
|
||||
"lvm_meta_size": 0,
|
||||
"vg": "os"
|
||||
},
|
||||
{
|
||||
"size": 64971,
|
||||
"type": "pv",
|
||||
"lvm_meta_size": 64,
|
||||
"vg": "image"
|
||||
}
|
||||
],
|
||||
"type": "disk",
|
||||
"id": "sdb",
|
||||
"size": 65535
|
||||
},
|
||||
{
|
||||
"name": "sdc",
|
||||
"extra": [
|
||||
"disk/by-id/scsi-SATA_VBOX_HARDDISK_VB50ee61eb-84e74fdf",
|
||||
"disk/by-id/ata-VBOX_HARDDISK_VB50ee61eb-84e74fdf"
|
||||
],
|
||||
"free_space": 64907,
|
||||
"volumes": [
|
||||
{
|
||||
"type": "boot",
|
||||
"size": 300
|
||||
},
|
||||
{
|
||||
"mount": "/boot",
|
||||
"size": 200,
|
||||
"type": "raid",
|
||||
"file_system": "ext2",
|
||||
"name": "Boot"
|
||||
},
|
||||
{
|
||||
"type": "lvm_meta_pool",
|
||||
"size": 64
|
||||
},
|
||||
{
|
||||
"size": 0,
|
||||
"type": "pv",
|
||||
"lvm_meta_size": 0,
|
||||
"vg": "os"
|
||||
},
|
||||
{
|
||||
"size": 64971,
|
||||
"type": "pv",
|
||||
"lvm_meta_size": 64,
|
||||
"vg": "image"
|
||||
}
|
||||
],
|
||||
"type": "disk",
|
||||
"id": "disk/by-path/pci-0000:00:0d.0-scsi-0:0:0:0",
|
||||
"size": 65535
|
||||
},
|
||||
{
|
||||
"_allocate_size": "min",
|
||||
"label": "Base System",
|
||||
"min_size": 19374,
|
||||
"volumes": [
|
||||
{
|
||||
"mount": "/",
|
||||
"size": 15360,
|
||||
"type": "lv",
|
||||
"name": "root",
|
||||
"file_system": "ext4"
|
||||
},
|
||||
{
|
||||
"mount": "swap",
|
||||
"size": 4014,
|
||||
"type": "lv",
|
||||
"name": "swap",
|
||||
"file_system": "swap"
|
||||
}
|
||||
],
|
||||
"type": "vg",
|
||||
"id": "os"
|
||||
},
|
||||
{
|
||||
"_allocate_size": "all",
|
||||
"label": "Image Storage",
|
||||
"min_size": 5120,
|
||||
"volumes": [
|
||||
{
|
||||
"mount": "/var/lib/glance",
|
||||
"size": 175347,
|
||||
"type": "lv",
|
||||
"name": "glance",
|
||||
"file_system": "xfs"
|
||||
}
|
||||
],
|
||||
"type": "vg",
|
||||
"id": "image"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class TestKSSpacesValidator(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(TestKSSpacesValidator, self).setUp()
|
||||
self.fake_scheme = copy.deepcopy(SAMPLE_SCHEME)
|
||||
|
||||
def test_validate_ok(self):
|
||||
kssv.validate(self.fake_scheme)
|
||||
|
||||
def test_validate_jsoschema_fail(self):
|
||||
self.assertRaises(errors.WrongPartitionSchemeError, kssv.validate,
|
||||
[{}])
|
||||
|
||||
def test_validate_no_disks_fail(self):
|
||||
self.assertRaises(errors.WrongPartitionSchemeError, kssv.validate,
|
||||
self.fake_scheme[-2:])
|
||||
|
||||
@unittest2.skip("Fix after cray rebase")
|
||||
def test_validate_16T_root_volume_fail(self):
|
||||
self.fake_scheme[3]['volumes'][0]['size'] = 16777216 + 1
|
||||
self.assertRaises(errors.WrongPartitionSchemeError, kssv.validate,
|
||||
self.fake_scheme)
|
@ -16,10 +16,10 @@ import copy
|
||||
|
||||
import unittest2
|
||||
|
||||
from bareon.drivers.data import ks_spaces_validator as kssv
|
||||
from bareon.drivers.data import nailgun
|
||||
from bareon import errors
|
||||
|
||||
SAMPLE_SCHEME = [
|
||||
SAMPLE_CHUNK_SPACES = [
|
||||
{
|
||||
"name": "sda",
|
||||
"extra": [
|
||||
@ -181,71 +181,96 @@ SAMPLE_SCHEME = [
|
||||
}
|
||||
]
|
||||
|
||||
SAMPLE_PAYLOAD = {
|
||||
'ks_meta': {
|
||||
'pm_data': {
|
||||
'ks_spaces': SAMPLE_CHUNK_SPACES
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestKSSpacesValidator(unittest2.TestCase):
|
||||
|
||||
class TestNailgunDataValidator(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(TestKSSpacesValidator, self).setUp()
|
||||
self.fake_scheme = copy.deepcopy(SAMPLE_SCHEME)
|
||||
super(TestNailgunDataValidator, self).setUp()
|
||||
self.payload = copy.deepcopy(SAMPLE_PAYLOAD)
|
||||
self.payload_spaces = self._get_spaces(self.payload)
|
||||
|
||||
def test_validate_ok(self):
|
||||
kssv.validate(self.fake_scheme, 'nailgun')
|
||||
def test_no_error(self):
|
||||
nailgun.Nailgun.validate_data(self.payload)
|
||||
|
||||
def test_validate_jsoschema_fail(self):
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, [{}], 'nailgun')
|
||||
def test_fail(self):
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data, {})
|
||||
|
||||
def test_validate_no_disks_fail(self):
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme[-2:], 'nailgun')
|
||||
def test_disks_no_disks_fail(self):
|
||||
self.payload_spaces[:-2] = []
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_free_space_type_fail(self):
|
||||
def test_disks_free_space_type_fail(self):
|
||||
incorrect_values_for_free_space = [
|
||||
False, True, '0', '1', None, object
|
||||
]
|
||||
for value in incorrect_values_for_free_space:
|
||||
self.fake_scheme[0]['free_space'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'nailgun')
|
||||
self.payload_spaces[0]['free_space'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_volume_type_fail(self):
|
||||
def test_disks_volume_type_fail(self):
|
||||
incorrect_values_for_type = [
|
||||
False, True, 0, 1, None, object
|
||||
]
|
||||
for value in incorrect_values_for_type:
|
||||
self.fake_scheme[0]['volumes'][1]['type'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'nailgun')
|
||||
self.payload_spaces[0]['volumes'][1]['type'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_volume_size_fail(self):
|
||||
def test_disks_volume_size_fail(self):
|
||||
incorrect_values_for_size = [
|
||||
False, True, '0', '1', None, object
|
||||
]
|
||||
for value in incorrect_values_for_size:
|
||||
self.fake_scheme[0]['volumes'][1]['size'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'nailgun')
|
||||
self.payload_spaces[0]['volumes'][1]['size'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_device_id_fail(self):
|
||||
def test_disks_device_id_fail(self):
|
||||
incorrect_values_for_id = [
|
||||
False, True, 0, 1, None, object
|
||||
]
|
||||
for value in incorrect_values_for_id:
|
||||
self.fake_scheme[0]['id'] = value
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, self.fake_scheme, 'nailgun')
|
||||
self.payload_spaces[0]['id'] = value
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
self.payload)
|
||||
|
||||
def test_validate_missed_property(self):
|
||||
def test_disks_missed_property(self):
|
||||
required = ['id', 'size', 'volumes', 'type', 'free_space', 'volumes']
|
||||
for prop in required:
|
||||
fake = copy.deepcopy(self.fake_scheme)
|
||||
del fake[0][prop]
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, fake, 'nailgun')
|
||||
payload = copy.deepcopy(self.payload)
|
||||
spaces = self._get_spaces(payload)
|
||||
del spaces[0][prop]
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
payload)
|
||||
|
||||
def test_validate_missed_volume_property(self):
|
||||
def test_disks_missed_volume_property(self):
|
||||
required = ['type', 'size', 'vg']
|
||||
for prop in required:
|
||||
fake = copy.deepcopy(self.fake_scheme)
|
||||
del fake[0]['volumes'][3][prop]
|
||||
self.assertRaises(errors.WrongPartitionSchemeError,
|
||||
kssv.validate, fake, 'nailgun')
|
||||
payload = copy.deepcopy(self.payload)
|
||||
spaces = self._get_spaces(payload)
|
||||
del spaces[0]['volumes'][3][prop]
|
||||
self.assertRaises(
|
||||
errors.WrongInputDataError, nailgun.Nailgun.validate_data,
|
||||
payload)
|
||||
|
||||
@staticmethod
|
||||
def _get_spaces(payload):
|
||||
payload = payload['ks_meta']
|
||||
payload = payload['pm_data']
|
||||
return payload['ks_spaces']
|
@ -30,25 +30,23 @@ from bareon.tests import base
|
||||
parse_configdrive_scheme=lambda x: objects.ConfigDriveScheme(),
|
||||
parse_image_scheme=lambda x: objects.ImageScheme())
|
||||
class TestObjectDeserialization(unittest2.TestCase):
|
||||
|
||||
def test_driver_always_has_correct_objects(self):
|
||||
driver = simple.NailgunSimpleDriver({})
|
||||
driver = simple.NailgunSimpleDriver(self._minimal_payload())
|
||||
assert isinstance(driver.partition_scheme, objects.PartitionScheme)
|
||||
|
||||
def test_lv_data_is_loaded(self):
|
||||
lv_data = {
|
||||
'partitioning': {
|
||||
'lvs': [
|
||||
{
|
||||
'name': 'lv-name',
|
||||
'size': 12345,
|
||||
'vgname': 'vg-name',
|
||||
},
|
||||
]
|
||||
}
|
||||
payload = self._minimal_payload()
|
||||
payload['partitioning'] = {
|
||||
'lvs': [
|
||||
{
|
||||
'name': 'lv-name',
|
||||
'size': 12345,
|
||||
'vgname': 'vg-name',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
driver = simple.NailgunSimpleDriver(lv_data)
|
||||
driver = simple.NailgunSimpleDriver(payload)
|
||||
lv = driver.partition_scheme.lvs[0]
|
||||
assert len(driver.partition_scheme.lvs) == 1
|
||||
assert isinstance(lv, objects.LV)
|
||||
@ -57,19 +55,18 @@ class TestObjectDeserialization(unittest2.TestCase):
|
||||
assert lv.vgname == 'vg-name'
|
||||
|
||||
def test_pv_data_is_loaded(self):
|
||||
pv_data = {
|
||||
'partitioning': {
|
||||
'pvs': [
|
||||
{
|
||||
'metadatacopies': 2,
|
||||
'metadatasize': 28,
|
||||
'name': '/dev/sda5'
|
||||
},
|
||||
]
|
||||
}
|
||||
payload = self._minimal_payload()
|
||||
payload['partitioning'] = {
|
||||
'pvs': [
|
||||
{
|
||||
'metadatacopies': 2,
|
||||
'metadatasize': 28,
|
||||
'name': '/dev/sda5'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
driver = simple.NailgunSimpleDriver(pv_data)
|
||||
driver = simple.NailgunSimpleDriver(payload)
|
||||
pv = driver.partition_scheme.pvs[0]
|
||||
assert len(driver.partition_scheme.pvs) == 1
|
||||
assert isinstance(pv, objects.PV)
|
||||
@ -78,22 +75,21 @@ class TestObjectDeserialization(unittest2.TestCase):
|
||||
assert pv.metadatasize == 28
|
||||
|
||||
def test_vg_data_is_loaded(self):
|
||||
vg_data = {
|
||||
'partitioning': {
|
||||
'vgs': [
|
||||
{
|
||||
'name': 'image',
|
||||
'pvnames': [
|
||||
'/dev/sda6',
|
||||
'/dev/sdb3',
|
||||
'/dev/sdc3',
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
payload = self._minimal_payload()
|
||||
payload['partitioning'] = {
|
||||
'vgs': [
|
||||
{
|
||||
'name': 'image',
|
||||
'pvnames': [
|
||||
'/dev/sda6',
|
||||
'/dev/sdb3',
|
||||
'/dev/sdc3',
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
driver = simple.NailgunSimpleDriver(vg_data)
|
||||
driver = simple.NailgunSimpleDriver(payload)
|
||||
vg = driver.partition_scheme.vgs[0]
|
||||
assert len(driver.partition_scheme.vgs) == 1
|
||||
assert isinstance(vg, objects.VG)
|
||||
@ -108,21 +104,20 @@ class TestObjectDeserialization(unittest2.TestCase):
|
||||
)
|
||||
|
||||
def test_fs_data_is_loaded(self):
|
||||
fs_data = {
|
||||
'partitioning': {
|
||||
'fss': [
|
||||
{
|
||||
'device': '/dev/sda3',
|
||||
'fs_label': 'some-label',
|
||||
'fs_options': 'some-options',
|
||||
'fs_type': 'ext2',
|
||||
'mount': '/boot'
|
||||
},
|
||||
]
|
||||
}
|
||||
payload = self._minimal_payload()
|
||||
payload['partitioning'] = {
|
||||
'fss': [
|
||||
{
|
||||
'device': '/dev/sda3',
|
||||
'fs_label': 'some-label',
|
||||
'fs_options': 'some-options',
|
||||
'fs_type': 'ext2',
|
||||
'mount': '/boot'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
driver = simple.NailgunSimpleDriver(fs_data)
|
||||
driver = simple.NailgunSimpleDriver(payload)
|
||||
fs = driver.partition_scheme.fss[0]
|
||||
assert len(driver.partition_scheme.fss) == 1
|
||||
assert isinstance(fs, objects.FS)
|
||||
@ -133,34 +128,33 @@ class TestObjectDeserialization(unittest2.TestCase):
|
||||
assert fs.mount == '/boot'
|
||||
|
||||
def test_parted_data_is_loaded(self):
|
||||
parted_data = {
|
||||
'partitioning': {
|
||||
'parteds': [
|
||||
{
|
||||
'label': 'gpt',
|
||||
'name': '/dev/sdb',
|
||||
'partitions': [
|
||||
{
|
||||
'begin': 1,
|
||||
'configdrive': False,
|
||||
'count': 1,
|
||||
'device': '/dev/sdb',
|
||||
'end': 25,
|
||||
'flags': [
|
||||
'bios_grub',
|
||||
'xyz',
|
||||
],
|
||||
'guid': None,
|
||||
'name': '/dev/sdb1',
|
||||
'partition_type': 'primary'
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
payload = self._minimal_payload()
|
||||
payload['partitioning'] = {
|
||||
'parteds': [
|
||||
{
|
||||
'label': 'gpt',
|
||||
'name': '/dev/sdb',
|
||||
'partitions': [
|
||||
{
|
||||
'begin': 1,
|
||||
'configdrive': False,
|
||||
'count': 1,
|
||||
'device': '/dev/sdb',
|
||||
'end': 25,
|
||||
'flags': [
|
||||
'bios_grub',
|
||||
'xyz',
|
||||
],
|
||||
'guid': None,
|
||||
'name': '/dev/sdb1',
|
||||
'partition_type': 'primary'
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
driver = simple.NailgunSimpleDriver(parted_data)
|
||||
driver = simple.NailgunSimpleDriver(payload)
|
||||
parted = driver.partition_scheme.parteds[0]
|
||||
partition = parted.partitions[0]
|
||||
assert len(driver.partition_scheme.parteds) == 1
|
||||
@ -179,26 +173,25 @@ class TestObjectDeserialization(unittest2.TestCase):
|
||||
assert partition.type == 'primary'
|
||||
|
||||
def test_md_data_is_loaded(self):
|
||||
md_data = {
|
||||
'partitioning': {
|
||||
'mds': [
|
||||
{
|
||||
'name': 'some-raid',
|
||||
'level': 1,
|
||||
'devices': [
|
||||
'/dev/sda',
|
||||
'/dev/sdc',
|
||||
],
|
||||
'spares': [
|
||||
'/dev/sdb',
|
||||
'/dev/sdd',
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
payload = self._minimal_payload()
|
||||
payload['partitioning'] = {
|
||||
'mds': [
|
||||
{
|
||||
'name': 'some-raid',
|
||||
'level': 1,
|
||||
'devices': [
|
||||
'/dev/sda',
|
||||
'/dev/sdc',
|
||||
],
|
||||
'spares': [
|
||||
'/dev/sdb',
|
||||
'/dev/sdd',
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
driver = simple.NailgunSimpleDriver(md_data)
|
||||
driver = simple.NailgunSimpleDriver(payload)
|
||||
md = driver.partition_scheme.mds[0]
|
||||
assert len(driver.partition_scheme.mds) == 1
|
||||
assert isinstance(md, objects.MD)
|
||||
@ -207,6 +200,26 @@ class TestObjectDeserialization(unittest2.TestCase):
|
||||
self.assertItemsEqual(md.devices, ['/dev/sda', '/dev/sdc'])
|
||||
self.assertItemsEqual(md.spares, ['/dev/sdb', '/dev/sdd'])
|
||||
|
||||
@staticmethod
|
||||
def _minimal_payload():
|
||||
return {
|
||||
'ks_meta': {
|
||||
'pm_data': {
|
||||
'ks_spaces': [
|
||||
{
|
||||
'type': 'disk',
|
||||
'id': 'dummy-disk-id',
|
||||
'name': 'dummy0',
|
||||
'free_space': 0,
|
||||
'size': 128,
|
||||
'extra': [],
|
||||
'volumes': []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@requests_mock.mock()
|
||||
class TestFullDataRead(unittest2.TestCase):
|
||||
|
@ -22,6 +22,11 @@ from bareon.utils import utils
|
||||
LOG = logging.getLogger(__name__)
|
||||
PARTITION_ALIGMENT = ('none', 'cylinder', 'minimal', 'optimal')
|
||||
|
||||
KiB = 1024
|
||||
MiB = KiB * 1024
|
||||
GiB = MiB * 1024
|
||||
TiB = GiB * 1024
|
||||
|
||||
|
||||
def parse_partition_info(parted_output):
|
||||
lines = parted_output.split('\n')
|
||||
|
Loading…
x
Reference in New Issue
Block a user