Skip to content

Commit

Permalink
Feat/flavor0103 add extras (#645)
Browse files Browse the repository at this point in the history
* flavor-add-extra-specs.py: Adds extra specs to SCS flavors.
  This helper inspects existing SCS- flavors, does some snaity checks and
  and adds the needed extra specs defined in scs-0104-v1.
* The relevant standard is 0103 not 0104.
* Add scs:cpu-type and disk0-type checks and setting.
* Improve documentation.
* You can explicitly pass --cpu-type and FLAVORS now.
  This generates the SCS extra specs even for non-SCS flavors.
  Mostly for operators, that are still finding their way into the
  SCS ecosystem and would want to see how their existing flavors map.
* Add scs:name-v3 as requested in #630.
* Mute flake8.
* Add -n|--no-change mode.
* use isinstance
* Remove commented out imports.
* Simplify OS_CLOUD default pickup from environment.
   As suggested by Matthias Büchse <[email protected]>.
* Drop setting scs:name-v3 again.
* Improve check_name_extra().
  This is however not yet the big rewrite as intended ...
* Implement flavor_filter as suggested by mbuechse.
* Save one variable (compute).
* simplify logic using extant (partly improved) library
* adapt unit test
* simplify flavor filter logic, improve error output
* Fix computation of which extra_specs to remove
* appease flake8
* implement actions report, ask, apply
* Bugfix: do not report existing values when no value exists
* appease flake8
* Demote error to warning because we can't tell if it's a mistake
* Convert our RAM in GiB to OpenStack RAM in MiB.
* Option -A/--all-names to produce all scs:name-vN.
   Normally, if one of them exists, we produce no more.
* Revert "Convert our RAM in GiB to OpenStack RAM in MiB."
   This reverts commit 90a75ab.
   While it does match what OpenStack expects, it's unused and
   breaks the CI. Needs more investigation.
* Use longest SCS- name to derive reference specs.
* Update help text to document -A|--all-names
* Reenable -q|--quiet. Report changes without it.
* Fix import order: builtins, external, internal
* use logger consistently, decouple `usage` a bit
* remove redundant code
* use all flavornames, not just one reference name

Signed-off-by: Kurt Garloff <[email protected]>
Signed-off-by: Matthias Büchse <[email protected]>
Co-authored-by: Matthias Büchse <[email protected]>
garloff and mbuechse authored Aug 20, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent dcb9ddd commit 39acbd3
Showing 8 changed files with 617 additions and 245 deletions.
6 changes: 3 additions & 3 deletions Tests/iaas/flavor-naming/check_yaml.py
Original file line number Diff line number Diff line change
@@ -17,8 +17,8 @@
from flavor_names import parser_v2, flavorname_to_dict


REQUIRED_FIELDS = ['name-v1', 'name-v2', 'name', 'cpus', 'ram', 'cpu-type']
DEFAULTS = {'disk0-type': 'network'}
REQUIRED_FIELDS = ['scs:name-v1', 'scs:name-v2', 'name', 'cpus', 'ram', 'scs:cpu-type']
DEFAULTS = {'scs:disk0-type': 'network'}


class Undefined:
@@ -47,7 +47,7 @@ def check_spec(self, flavor_spec):
self.emit(f"flavor spec missing keys {', '.join(missing)}: {flavor_spec}")
return
name = flavor_spec['name']
name_v2 = flavor_spec['name-v2']
name_v2 = flavor_spec['scs:name-v2']
try:
flavorname = parser_v2(name_v2)
except Exception:
6 changes: 3 additions & 3 deletions Tests/iaas/flavor-naming/check_yaml_test.py
Original file line number Diff line number Diff line change
@@ -17,12 +17,12 @@
BUGGY_YAML_DIR = Path(TEST_ROOT, "testing")

EXPECTED_ERRORS = """
ERROR: flavor 'SCS-1V-4': field 'cpu-type' contradicting name-v2 'SCS-1V-4'; found 'crowded-core', expected 'shared-core'
ERROR: flavor 'SCS-2V-8': field 'name-v1' contradicting name-v2 'SCS-2V-8'; found 'SCS-2V-8', expected 'SCS-2V:8'
ERROR: flavor 'SCS-1V-4': field 'scs:cpu-type' contradicting name-v2 'SCS-1V-4'; found 'crowded-core', expected 'shared-core'
ERROR: flavor 'SCS-2V-8': field 'scs:name-v1' contradicting name-v2 'SCS-2V-8'; found 'SCS-2V-8', expected 'SCS-2V:8'
ERROR: flavor 'SCS-4V-16': field 'ram' contradicting name-v2 'SCS-4V-16'; found 12, expected 16.0
ERROR: flavor 'SCS-8V-32': field 'disk' contradicting name-v2 'SCS-8V-32'; found 128, expected undefined
ERROR: flavor 'SCS-1V-2': field 'cpus' contradicting name-v2 'SCS-1V-2'; found 2, expected 1
ERROR: flavor 'SCS-2V-4-20s': field 'disk0-type' contradicting name-v2 'SCS-2V-4-20s'; found 'network', expected 'ssd'
ERROR: flavor 'SCS-2V-4-20s': field 'scs:disk0-type' contradicting name-v2 'SCS-2V-4-20s'; found 'network', expected 'ssd'
ERROR: flavor 'SCS-4V-16-100s': field 'disk' contradicting name-v2 'SCS-4V-16-100s'; found 10, expected 100
ERROR: file 'scs-0103-v1-flavors-wrong.yaml': found 7 errors
""".strip()
63 changes: 13 additions & 50 deletions Tests/iaas/flavor-naming/cli.py
Original file line number Diff line number Diff line change
@@ -6,55 +6,18 @@
import click
import yaml

from flavor_names import parser_v1, parser_v2, parser_v3, inputflavor, outputter, flavorname_to_dict, prettyname


logger = logging.getLogger(__name__)


class ParsingStrategy:
"""class to model parsing that accepts multiple versions of the syntax in different ways"""

def __init__(self, parsers=(), tolerated_parsers=(), invalid_parsers=()):
self.parsers = parsers
self.tolerated_parsers = tolerated_parsers
self.invalid_parsers = invalid_parsers

def parse(self, namestr):
exc = None
for parser in self.parsers:
try:
return parser(namestr)
except Exception as e:
if exc is None:
exc = e
# at this point, if `self.parsers` is not empty, then `exc` is not `None`
for parser in self.tolerated_parsers:
try:
result = parser(namestr)
except Exception:
pass
else:
logger.warning(f"Name is merely tolerated {parser.vstr}: {namestr}")
return result
for parser in self.invalid_parsers:
try:
result = parser(namestr)
except Exception:
pass
else:
raise ValueError(f"Name is non-tolerable {parser.vstr}")
raise exc
from flavor_names import parser_v1, parser_v2, parser_v3, inputflavor, outputter, flavorname_to_dict, \
prettyname, ParsingStrategy


VERSIONS = {
'v1': ParsingStrategy(parsers=(parser_v1, ), invalid_parsers=(parser_v2, )),
'v1/v2': ParsingStrategy(parsers=(parser_v1, ), tolerated_parsers=(parser_v2, )),
'v2/v1': ParsingStrategy(parsers=(parser_v2, ), tolerated_parsers=(parser_v1, )),
'v2': ParsingStrategy(parsers=(parser_v2, ), invalid_parsers=(parser_v1, )),
'v3': ParsingStrategy(parsers=(parser_v3, ), invalid_parsers=(parser_v1, )),
}
_, VERSIONS['latest'] = max(VERSIONS.items())
PARSERS = {ps.vstr: ps for ps in [
ParsingStrategy(vstr='v1', parsers=(parser_v1, ), invalid_parsers=(parser_v2, )),
ParsingStrategy(vstr='v1/v2', parsers=(parser_v1, ), tolerated_parsers=(parser_v2, )),
ParsingStrategy(vstr='v2/v1', parsers=(parser_v2, ), tolerated_parsers=(parser_v1, )),
ParsingStrategy(vstr='v2', parsers=(parser_v2, ), invalid_parsers=(parser_v1, )),
ParsingStrategy(vstr='v3', parsers=(parser_v3, ), invalid_parsers=(parser_v1, )),
]}
_, PARSERS['latest'] = max(PARSERS.items())


def noop(*args, **kwargs):
@@ -84,7 +47,7 @@ def process_pipeline(rc, *args, **kwargs):


@cli.command()
@click.argument('version', type=click.Choice(list(VERSIONS), case_sensitive=False))
@click.argument('version', type=click.Choice(list(PARSERS), case_sensitive=False))
@click.argument('name', nargs=-1)
@click.option('-o', '--output', 'output', type=click.Choice(['none', 'prose', 'yaml']),
help='select output format (default: none)')
@@ -96,12 +59,12 @@ def parse(cfg, version, name, output='none'):
validation. With 'v1/v2', flavor names of both kinds are accepted, but warnings are emitted for v2,
and similarly with 'v2/v1', where warnings are emitted for v1.
"""
version = VERSIONS.get(version)
parser = PARSERS.get(version)
printv = cfg.printv
errors = 0
for namestr in name:
try:
flavorname = version.parse(namestr)
flavorname = parser(namestr)
except ValueError as exc:
print(f"{exc}: {namestr}")
errors += 1
Loading

0 comments on commit 39acbd3

Please sign in to comment.