From 66edf86ec374291b7eaabd775cbf6d6b49c5ab75 Mon Sep 17 00:00:00 2001 From: Evgeniy L Date: Thu, 17 Mar 2016 18:03:43 +0300 Subject: [PATCH] Extracted parsing logic and objects creation into separate class --- bareon_dynamic_allocator/allocators.py | 55 ++----------- bareon_dynamic_allocator/objects/space.py | 2 +- bareon_dynamic_allocator/parsers/__init__.py | 18 ++++ .../parsers/dynamic_schema_parser.py | 82 +++++++++++++++++++ .../{parser.py => parsers/expressions.py} | 2 +- 5 files changed, 111 insertions(+), 48 deletions(-) create mode 100644 bareon_dynamic_allocator/parsers/__init__.py create mode 100644 bareon_dynamic_allocator/parsers/dynamic_schema_parser.py rename bareon_dynamic_allocator/{parser.py => parsers/expressions.py} (98%) diff --git a/bareon_dynamic_allocator/allocators.py b/bareon_dynamic_allocator/allocators.py index a28e0a4..e5de893 100644 --- a/bareon_dynamic_allocator/allocators.py +++ b/bareon_dynamic_allocator/allocators.py @@ -23,11 +23,9 @@ from oslo_log import log from scipy.optimize import linprog from bareon_dynamic_allocator import errors +from bareon_dynamic_allocator.parsers import DynamicSchemaParser from bareon_dynamic_allocator import utils -from bareon_dynamic_allocator.objects import Disk -from bareon_dynamic_allocator.objects import Space -from bareon_dynamic_allocator.parser import Parser from bareon_dynamic_allocator.sequences import CrossSumInequalitySequence @@ -37,56 +35,21 @@ LOG = log.getLogger(__name__) class DynamicAllocator(object): def __init__(self, hw_info, schema): - LOG.debug('Hardware information: \n%s', hw_info) - LOG.debug('Spaces schema: \n%s', schema) - self.hw_info = hw_info - self.raw_disks = hw_info['disks'] - self.disks = [Disk(**disk) for disk in self.raw_disks] - rendered_spaces = self.convert_disks_to_indexes( - Parser(schema, hw_info).parse(), - hw_info) - LOG.debug('Rendered spaces schema: \n%s', rendered_spaces) - self.spaces = [Space(**space) - for space in rendered_spaces if space['type'] != 'vg'] + LOG.debug('Hardware information: %s', hw_info) + LOG.debug('Spaces schema: %s', schema) + dynamic_schema = DynamicSchemaParser(hw_info, schema) + LOG.debug('Spaces objects: %s', dynamic_schema.spaces) + LOG.debug('Disks objects: \n%s', dynamic_schema.disks) - # Unallocated is required in order to be able to specify - # spaces with only minimal - self.spaces.append(Space( - id='unallocated', - type='unallocated', - none_order=True, - weight=0)) - - # Add fake volume Unallocated, in order to be able - # to have only volumes with minimal size, without - # additional space allocation - self.solver = DynamicAllocationLinearProgram(self.disks, self.spaces) + self.solver = DynamicAllocationLinearProgram( + dynamic_schema.disks, + dynamic_schema.spaces) def generate_static(self): sizes = self.solver.solve() return sizes - def convert_disks_to_indexes(self, spaces, hw_info): - """Convert disks to indexes. - - Convert disks which are specified in `best_with_disks` - to a list of indexes in `disks` list. - """ - for i, space in enumerate(spaces): - - if space.get('best_with_disks'): - disks_idx = set() - for disk in space['best_with_disks']: - try: - disks_idx.add(self.raw_disks.index(disk)) - except ValueError as exc: - LOG.warn('Warning: %s', exc) - - spaces[i]['best_with_disks'] = disks_idx - - return spaces - class DynamicAllocationLinearProgram(object): """Linear programming allocator. diff --git a/bareon_dynamic_allocator/objects/space.py b/bareon_dynamic_allocator/objects/space.py index 62d1254..7a2d184 100644 --- a/bareon_dynamic_allocator/objects/space.py +++ b/bareon_dynamic_allocator/objects/space.py @@ -26,7 +26,7 @@ class Space(BaseObject): 'best_with_disks': set([]), 'weight': 1 } - required = ['id'] + required = ['id', 'type'] def __init__(self, **kwargs): super(Space, self).__init__(**kwargs) diff --git a/bareon_dynamic_allocator/parsers/__init__.py b/bareon_dynamic_allocator/parsers/__init__.py new file mode 100644 index 0000000..a5befd3 --- /dev/null +++ b/bareon_dynamic_allocator/parsers/__init__.py @@ -0,0 +1,18 @@ +# Copyright 2016 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. + +# flake8: noqa + +from bareon_dynamic_allocator.parsers.expressions import ExpressionsParser +from bareon_dynamic_allocator.parsers.dynamic_schema_parser import DynamicSchemaParser diff --git a/bareon_dynamic_allocator/parsers/dynamic_schema_parser.py b/bareon_dynamic_allocator/parsers/dynamic_schema_parser.py new file mode 100644 index 0000000..cba0a7e --- /dev/null +++ b/bareon_dynamic_allocator/parsers/dynamic_schema_parser.py @@ -0,0 +1,82 @@ +# Copyright 2016 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. + +from oslo_log import log + +from bareon_dynamic_allocator.objects import Disk +from bareon_dynamic_allocator.objects import Space +from bareon_dynamic_allocator.parser import Parser + + +LOG = log.getLogger(__name__) + + +class DynamicSchemaParser(object): + + def __init__(self, hw_info, schema): + self.hw_info = hw_info + self.schema = schema + self.raw_disks = self.hw_info['disks'] + self.rendered_spaces = [] + self.disks = [] + self.spaces = [] + + self.parse() + self.post_parse() + + def parse(self): + self.render_expressions() + + self.disks = [ + Disk(**disk) + for disk in self.raw_disks] + + self.spaces = [ + Space(**space) + for space in self.rendered_spaces if space['type'] != 'vg'] + + def post_parse(self): + # Add fake volume Unallocated, in order to be able + # to have only volumes with minimal size, without + # additional space allocation + self.spaces.append(Space( + id='unallocated', + type='unallocated', + none_order=True, + weight=0)) + + def render_expressions(self): + self.rendered_spaces = self._convert_disks_to_indexes( + Parser(self.schema, self.hw_info).parse(), + self.hw_info) + + def _convert_disks_to_indexes(self, spaces, hw_info): + """Convert disks to indexes. + + Convert disks which are specified in `best_with_disks` + to a list of indexes in `disks` list. + """ + for i, space in enumerate(spaces): + + if space.get('best_with_disks'): + disks_idx = set() + for disk in space['best_with_disks']: + try: + disks_idx.add(self.raw_disks.index(disk)) + except ValueError as exc: + LOG.warn('Warning: %s', exc) + + spaces[i]['best_with_disks'] = disks_idx + + return spaces diff --git a/bareon_dynamic_allocator/parser.py b/bareon_dynamic_allocator/parsers/expressions.py similarity index 98% rename from bareon_dynamic_allocator/parser.py rename to bareon_dynamic_allocator/parsers/expressions.py index 40aaafd..9c03d76 100644 --- a/bareon_dynamic_allocator/parser.py +++ b/bareon_dynamic_allocator/parsers/expressions.py @@ -53,7 +53,7 @@ class NoopParser(object): return self.data -class Parser(object): +class ExpressionsParser(object): yaql_re = re.compile(r'^\s*yaql\s*=\s*')