From 50e13e0403b0d6e8a63ec64ea95df77a315f8d2b Mon Sep 17 00:00:00 2001 From: Warren Usui Date: Mon, 8 Sep 2014 20:12:24 -0700 Subject: [PATCH] Check os-type and os-version for vps Fixes: 8712 Signed-off-by: Warren Usui warren.usui@inktank.com --- teuthology/lock.py | 83 +++++++++++++++++++ teuthology/task/internal.py | 2 + .../test_vps_os_vers_parameter_checking.py | 67 +++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 teuthology/test/test_vps_os_vers_parameter_checking.py diff --git a/teuthology/lock.py b/teuthology/lock.py index 16272e337e..a4119610f8 100644 --- a/teuthology/lock.py +++ b/teuthology/lock.py @@ -9,6 +9,7 @@ import os import time import requests import urllib +from distutils.spawn import find_executable import teuthology from . import misc @@ -23,6 +24,80 @@ logging.getLogger("requests.packages.urllib3.connectionpool").setLevel( is_vpm = lambda name: 'vpm' in name +def get_distro_from_downburst(): + """ + Return a table of valid distros. + + If downburst is in path use it. If either downburst is unavailable, + or if downburst is unable to produce a json list, then use a default + table. + """ + default_table = {u'rhel_minimal': [u'6.4', u'6.5'], + u'fedora': [u'17', u'18', u'19', u'20'], + u'centos': [u'6.3', u'6.4', u'6.5', u'7.0'], + u'opensuse': [u'12.2'], + u'rhel': [u'6.3', u'6.4', u'6.5', u'7.0', u'7beta'], + u'centos_minimal': [u'6.4', u'6.5'], + u'ubuntu': [u'8.04(hardy)', u'9.10(karmic)', + u'10.04(lucid)', u'10.10(maverick)', + u'11.04(natty)', u'11.10(oneiric)', + u'12.04(precise)', u'12.10(quantal)', + u'13.04(raring)', u'13.10(saucy)', + u'14.04(trusty)', u'utopic(utopic)'], + u'sles': [u'11-sp2'], + u'debian': [u'6.0', u'7.0']} + executable_cmd = find_executable('downburst') + if not executable_cmd: + log.info('Using default values for supported os_type/os_version') + return default_table + try: + p = subprocess.Popen([executable_cmd, 'list-json'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE,) + output, err = p.communicate() + downburst_data = json.loads(output) + return downburst_data + except OSError: + log.info('Using default values for supported os_type/os_version') + return default_table + + +def vps_version_or_type_valid(machine_type, os_type, os_version): + """ + Check os-type and os-version parameters when locking a vps. + Os-type will always be set (defaults to ubuntu). + + In the case where downburst does not handle list-json (an older version + of downburst, for instance), a message is printed and this checking + is skipped (so that this code should behave as it did before this + check was added). + """ + if not machine_type == 'vps': + return True + valid_os_and_version = get_distro_from_downburst() + if os_type not in valid_os_and_version: + log.error('os-type is invalid') + return False + if not validate_distro_version(os_version, + valid_os_and_version[os_type]): + log.error('os-version is invalid') + return False + return True + +def validate_distro_version(version, supported_versions): + """ + Return True if the version is valid. For Ubuntu, possible + supported version values are of the form '12.04 (precise)' where + either the number of the version name is acceptable. + """ + if version in supported_versions: + return True + for parts in supported_versions: + part = parts.split('(') + if len(part) == 2: + if version == part[0]: + return True + if version == part[1][0:len(part[1])-1]: + return True def main(ctx): if ctx.verbose: @@ -158,6 +233,10 @@ def main(ctx): return 0 elif ctx.lock: + if not vps_version_or_type_valid(ctx.machine_type, ctx.os_type, + ctx.os_version): + log.error('Invalid os-type or version detected -- lock failed') + return 1 for machine in machines: if not lock_one(machine, user, ctx.desc): ret = 1 @@ -224,6 +303,10 @@ def main(ctx): def lock_many(ctx, num, machinetype, user=None, description=None): + if not vps_version_or_type_valid(ctx.machine_type, ctx.os_type, + ctx.os_version): + log.error('Invalid os-type or version detected -- lock failed') + return machinetypes = misc.get_multi_machine_types(machinetype) if user is None: user = misc.get_user() diff --git a/teuthology/task/internal.py b/teuthology/task/internal.py index cb0b41ce0d..b4430e0ffa 100644 --- a/teuthology/task/internal.py +++ b/teuthology/task/internal.py @@ -96,6 +96,8 @@ def lock_machines(ctx, config): newly_locked = lock.lock_many(ctx, how_many, machine_type, ctx.owner, ctx.archive) + if not newly_locked and not isinstance(newly_locked, list): + raise RuntimeError('Invalid parameters specified') if len(newly_locked) == how_many: vmlist = [] for lmach in newly_locked: diff --git a/teuthology/test/test_vps_os_vers_parameter_checking.py b/teuthology/test/test_vps_os_vers_parameter_checking.py new file mode 100644 index 0000000000..d3b5fe9cbe --- /dev/null +++ b/teuthology/test/test_vps_os_vers_parameter_checking.py @@ -0,0 +1,67 @@ +from .. import lock + +class Mock: pass + +class TestVpsOsVersionParamCheck(object): + + def setup(self): + self.fake_ctx = Mock() + self.fake_ctx.machine_type = 'vps' + self.fake_ctx.num_to_lock = 1 + self.fake_ctx.lock = False + + def test_ubuntu_precise(self): + self.fake_ctx.os_type = 'ubuntu' + self.fake_ctx.os_version = 'precise' + check_value = lock.vps_version_or_type_valid( + self.fake_ctx.machine_type, + self.fake_ctx.os_type, + self.fake_ctx.os_version) + + assert check_value + + def test_ubuntu_number(self): + self.fake_ctx.os_type = 'ubuntu' + self.fake_ctx.os_version = '12.04' + check_value = lock.vps_version_or_type_valid( + self.fake_ctx.machine_type, + self.fake_ctx.os_type, + self.fake_ctx.os_version) + assert check_value + + def test_rhel(self): + self.fake_ctx.os_type = 'rhel' + self.fake_ctx.os_version = '6.5' + check_value = lock.vps_version_or_type_valid( + self.fake_ctx.machine_type, + self.fake_ctx.os_type, + self.fake_ctx.os_version) + assert check_value + + def test_mixup(self): + self.fake_ctx.os_type = '6.5' + self.fake_ctx.os_version = 'rhel' + check_value = lock.vps_version_or_type_valid( + self.fake_ctx.machine_type, + self.fake_ctx.os_type, + self.fake_ctx.os_version) + assert not check_value + + def test_bad_type(self): + self.fake_ctx.os_type = 'aardvark' + self.fake_ctx.os_version = '6.5' + check_value = lock.vps_version_or_type_valid( + self.fake_ctx.machine_type, + self.fake_ctx.os_type, + self.fake_ctx.os_version) + assert not check_value + + def test_bad_version(self): + self.fake_ctx.os_type = 'rhel' + self.fake_ctx.os_version = 'vampire_bat' + check_value = lock.vps_version_or_type_valid( + self.fake_ctx.machine_type, + self.fake_ctx.os_type, + self.fake_ctx.os_version) + assert not check_value + -- 2.39.5