From: Loic Dachary Date: Fri, 25 Mar 2016 14:10:51 +0000 (+0100) Subject: openstack: add aarch64 support X-Git-Tag: 1.1.0~259^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=62590bcaf30718be3e25686a506ad2b267b9f48d;p=teuthology.git openstack: add aarch64 support Signed-off-by: Loic Dachary --- diff --git a/teuthology/openstack/__init__.py b/teuthology/openstack/__init__.py index dbe237a46..3e76997dd 100644 --- a/teuthology/openstack/__init__.py +++ b/teuthology/openstack/__init__.py @@ -48,6 +48,9 @@ from teuthology import misc log = logging.getLogger(__name__) +class NoFlavorException(Exception): + pass + def enforce_json_dictionary(something): if type(something) is not types.DictType: raise Exception( @@ -178,29 +181,25 @@ class OpenStackInstance(object): class OpenStack(object): - # wget -O debian-8.0.qcow2 http://cdimage.debian.org/cdimage/openstack/current/debian-8.1.0-openstack-amd64.qcow2 - # wget -O ubuntu-12.04.qcow2 https://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64-disk1.img - # wget -O ubuntu-12.04-i386.qcow2 https://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-i386-disk1.img - # wget -O ubuntu-14.04.qcow2 https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img - # wget -O ubuntu-14.04-i386.qcow2 https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-i386-disk1.img - # wget -O ubuntu-15.04.qcow2 https://cloud-images.ubuntu.com/vivid/current/vivid-server-cloudimg-arm64-disk1.img - # wget -O ubuntu-15.04-i386.qcow2 https://cloud-images.ubuntu.com/vivid/current/vivid-server-cloudimg-i386-disk1.img - # wget -O opensuse-13.2 http://download.opensuse.org/repositories/Cloud:/Images:/openSUSE_13.2/images/openSUSE-13.2-OpenStack-Guest.x86_64.qcow2 - # wget -O opensuse-42.1 http://download.opensuse.org/repositories/Cloud:/Images:/Leap_42.1/images/openSUSE-Leap-42.1-OpenStack.x86_64.qcow2 - # wget -O centos-7.0.qcow2 http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 - # wget -O centos-6.6.qcow2 http://cloud.centos.org/centos/6/images/CentOS-6-x86_64-GenericCloud.qcow2 - # wget -O fedora-22.qcow2 https://download.fedoraproject.org/pub/fedora/linux/releases/22/Cloud/x86_64/Images/Fedora-Cloud-Base-22-20150521.x86_64.qcow2 - # wget -O fedora-21.qcow2 http://fedora.mirrors.ovh.net/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.qcow2 - # wget -O fedora-20.qcow2 http://fedora.mirrors.ovh.net/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2 + # http://cdimage.debian.org/cdimage/openstack/current/ + # https://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64-disk1.img etc. + # http://download.opensuse.org/repositories/Cloud:/Images:/openSUSE_13.2/images/openSUSE-13.2-OpenStack-Guest.x86_64.qcow2 + # http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 etc. + # http://cloud.centos.org/centos/6/images/CentOS-6-x86_64-GenericCloud.qcow2 etc. + # https://download.fedoraproject.org/pub/fedora/linux/releases/22/Cloud/x86_64/Images/Fedora-Cloud-Base-22-20150521.x86_64.qcow2 + # http://fedora.mirrors.ovh.net/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.qcow2 + # http://fedora.mirrors.ovh.net/linux/releases/20/Images/x86_64/Fedora-x86_64-20-20131211.1-sda.qcow2 image2url = { - 'centos-6.5': 'http://cloud.centos.org/centos/6/images/CentOS-6-x86_64-GenericCloud-1508.qcow2', - 'centos-7.0': 'http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1503.qcow2', - 'centos-7.1': 'http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1503.qcow2', - 'centos-7.2': 'http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1511.qcow2', - 'opensuse-42.1': 'http://download.opensuse.org/repositories/Cloud:/Images:/Leap_42.1/images/openSUSE-Leap-42.1-OpenStack.x86_64.qcow2', - 'ubuntu-12.04': 'https://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64-disk1.img', - 'ubuntu-14.04': 'https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img', - 'debian-8.0': 'http://cdimage.debian.org/cdimage/openstack/current/debian-8.2.0-openstack-amd64.qcow2', + 'centos-6.5-x86_64': 'http://cloud.centos.org/centos/6/images/CentOS-6-x86_64-GenericCloud-1508.qcow2', + 'centos-7.0-x86_64': 'http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1503.qcow2', + 'centos-7.1-x86_64': 'http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1503.qcow2', + 'centos-7.2-x86_64': 'http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1511.qcow2', + 'opensuse-42.1-x86_64': 'http://download.opensuse.org/repositories/Cloud:/Images:/Leap_42.1/images/openSUSE-Leap-42.1-OpenStack.x86_64.qcow2', + 'ubuntu-12.04-x86_64': 'https://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64-disk1.img', + 'ubuntu-14.04-x86_64': 'https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img', + 'ubuntu-14.04-arm64': 'https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-arm64-disk1.img', + 'ubuntu-14.04-i686': 'https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-i386-disk1.img', + 'debian-8.0-x86_64': 'http://cdimage.debian.org/cdimage/openstack/current/debian-8.3.0-openstack-amd64.qcow2', } def __init__(self): @@ -282,7 +281,8 @@ class OpenStack(object): def set_provider(self): if 'OS_AUTH_URL' not in os.environ: raise Exception('no OS_AUTH_URL environment variable') - providers = (('cloud.ovh.net', 'ovh'), + providers = (('runabove.io', 'runabove'), + ('cloud.ovh.net', 'ovh'), ('entercloudsuite.com', 'entercloudsuite'), ('rackspacecloud.com', 'rackspace'), ('dream.io', 'dreamhost')) @@ -328,11 +328,11 @@ class OpenStack(object): network)) return self.get_value(r, 'id') - def type_version(self, os_type, os_version): + def type_version_arch(self, os_type, os_version, arch): """ Return the string used to differentiate os_type and os_version in names. """ - return os_type + '-' + os_version + return os_type + '-' + os_version + '-' + arch def image_name(self, name): """ @@ -341,9 +341,9 @@ class OpenStack(object): """ return "teuthology-" + name - def image_create(self, name): + def image_create(self, name, arch): """ - Upload an image into OpenStack with glance. + Upload an image into OpenStack """ misc.sh("wget -c -O " + name + ".qcow2 " + self.image2url[name]) if self.get_provider() == 'dreamhost': @@ -353,22 +353,37 @@ class OpenStack(object): else: image = name + ".qcow2" disk_format = 'qcow2' - misc.sh("glance image-create --property ownedby=teuthology " + + if self.provider == 'runabove': + properties = [ + "--property architecture_restrict=" + arch, + "--property architecture=" + arch + ] + elif self.get_provider() == 'cloudlab': + # if not, nova-compute fails on the compute node with + # Error: Cirrus VGA not available + properties = [ + "--property hw_video_model=vga", + ] + else: + properties = [] + + misc.sh("openstack image create --property ownedby=teuthology " + + " ".join(properties) + " --disk-format=" + disk_format + " --container-format=bare " + - " --visibility private" + - " --file " + image + " --name " + self.image_name(name)) + " --private" + + " --file " + image + " " + self.image_name(name)) - def image(self, os_type, os_version): + def image(self, os_type, os_version, arch): """ Return the image name for the given os_type and os_version. If the image does not exist it will be created. """ - name = self.type_version(os_type, os_version) + name = self.type_version_arch(os_type, os_version, arch) if not self.image_exists(name): - self.image_create(name) + self.image_create(name, arch) return self.image_name(name) - def flavor(self, hint, select): + def get_sorted_flavors(self, arch, select): """ Return the smallest flavor that satisfies the desired size. """ @@ -378,22 +393,54 @@ class OpenStack(object): for flavor in flavors: if select and not re.match(select, flavor['Name']): continue - if (flavor['RAM'] >= hint['ram'] and - flavor['VCPUs'] >= hint['cpus'] and - flavor['Disk'] >= hint['disk']): - found.append(flavor) - if not found: - raise Exception("openstack flavor list: " + flavors_string + - " does not contain a flavor in which" + - " the desired " + str(hint) + " can fit") + found.append(flavor) def sort_flavor(a, b): return (a['VCPUs'] - b['VCPUs'] or a['RAM'] - b['RAM'] or a['Disk'] - b['Disk']) - sorted_flavor = sorted(found, cmp=sort_flavor) - log.debug("sorted flavor = " + str(sorted_flavor)) - return sorted_flavor[0]['Name'] + sorted_flavors = sorted(found, cmp=sort_flavor) + log.debug("sorted flavors = " + str(sorted_flavors)) + return sorted_flavors + + def flavor(self, hint, arch, select): + """ + Return the smallest flavor that satisfies the desired size. + """ + flavors = self.get_sorted_flavors(arch, select) + for flavor in flavors: + if (flavor['RAM'] >= hint['ram'] and + flavor['VCPUs'] >= hint['cpus'] and + flavor['Disk'] >= hint['disk']): + return flavor['Name'] + raise NoFlavorException("openstack flavor list: " + str(flavors) + + " does not contain a flavor in which" + + " the desired " + str(hint) + " can fit") + + def flavor_range(self, min, good, arch, select): + """ + Return the smallest flavor that satisfies the good hint. + If no such flavor, get the largest flavor smaller than good + and larger than min. + """ + flavors = self.get_sorted_flavors(arch, select) + low_range = [] + for flavor in flavors: + if (flavor['RAM'] >= good['ram'] and + flavor['VCPUs'] >= good['cpus'] and + flavor['Disk'] >= good['disk']): + return flavor['Name'] + else: + low_range.append(flavor) + low_range.reverse() + for flavor in low_range: + if (flavor['RAM'] >= min['ram'] and + flavor['VCPUs'] >= min['cpus'] and + flavor['Disk'] >= min['disk']): + return flavor['Name'] + raise NoFlavorException("openstack flavor list: " + str(flavors) + + " does not contain a flavor which" + + " is larger than " + str(min)) def interpret_hints(self, defaults, hints): """ @@ -508,6 +555,16 @@ class OpenStack(object): def get_ip(self, instance_id, network): return OpenStackInstance(instance_id).get_ip(network) + def get_available_arch(self): + if (self.provider == 'runabove' and + 'HZ1' in os.environ.get('OS_REGION_NAME', '')): + return ('aarch64',) + else: + return ('x86_64', 'i686') + + def get_default_arch(self): + return self.get_available_archs()[0] + class TeuthologyOpenStack(OpenStack): @@ -806,7 +863,7 @@ ssh access : ssh {identity}{username}@{ip} # logs in /usr/share/nginx/ log.exception("flavor list") raise Exception("verify openrc.sh has been sourced") - def flavor(self): + def flavor(self, arch): """ Return an OpenStack flavor fit to run the teuthology cluster. The RAM size depends on the maximum number of workers that @@ -827,7 +884,7 @@ ssh access : ssh {identity}{username}@{ip} # logs in /usr/share/nginx/ select = None if self.get_provider() == 'ovh': select = '^(vps|eg)-' - return super(TeuthologyOpenStack, self).flavor(hint, select) + return super(TeuthologyOpenStack, self).flavor(hint, arch, select) def net(self): """ @@ -983,10 +1040,11 @@ openstack security group rule create --proto udp --dst-port 16000:65535 teutholo security_group = '' else: security_group = " --security-group teuthology" + arch = self.get_default_arch() self.run( "server create " + - " --image '" + self.image('ubuntu', '14.04') + "' " + - " --flavor '" + self.flavor() + "' " + + " --image '" + self.image('ubuntu', '14.04', arch) + "' " + + " --flavor '" + self.flavor(arch) + "' " + " " + self.net() + " --key-name " + self.args.key_name + " --user-data " + user_data + diff --git a/teuthology/openstack/openstack-basic.yaml b/teuthology/openstack/openstack-basic.yaml index 2df84b57b..cf076259c 100644 --- a/teuthology/openstack/openstack-basic.yaml +++ b/teuthology/openstack/openstack-basic.yaml @@ -8,4 +8,4 @@ overrides: mon lease ack timeout: 25 s3tests: idle_timeout: 1200 -archive-on-error: true +archive-on-error: true \ No newline at end of file diff --git a/teuthology/openstack/test/openstack-integration.py b/teuthology/openstack/test/openstack-integration.py index 95f46e80b..c8032002b 100644 --- a/teuthology/openstack/test/openstack-integration.py +++ b/teuthology/openstack/test/openstack-integration.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2015 Red Hat, Inc. +# Copyright (c) 2015, 2016 Red Hat, Inc. # # Author: Loic Dachary # @@ -227,12 +227,22 @@ class TestLock(Integration): assert teuthology.lock.cli.main(args) == 0 def test_lock_unlock(self): - for image in teuthology.openstack.OpenStack.image2url.keys(): - (os_type, os_version) = image.split('-') + default_archs = teuthology.openstack.OpenStack().get_available_archs() + if 'TEST_IMAGES' in os.environ: + images = os.environ['TEST_IMAGES'].split() + else: + images = teuthology.openstack.OpenStack.image2url.keys() + for image in images: + (os_type, os_version, arch) = image.split('-') + if arch not in default_archs: + logging.info("skipping " + image + " because arch " + + " is not supported (" + str(default_archs) + ")") + continue args = scripts.lock.parse_args(self.options + ['--lock-many', '1', '--os-type', os_type, - '--os-version', os_version]) + '--os-version', os_version, + '--arch', arch]) assert teuthology.lock.cli.main(args) == 0 locks = teuthology.lock.query.list_locks(locked=True) assert len(locks) == 1 @@ -256,7 +266,7 @@ class TestNuke(Integration): def test_nuke(self): image = teuthology.openstack.OpenStack.image2url.keys()[0] - (os_type, os_version) = image.split('-') + (os_type, os_version, arch) = image.split('-') args = scripts.lock.parse_args(self.options + ['--lock-many', '1', '--os-type', os_type, diff --git a/teuthology/openstack/test/test_openstack.py b/teuthology/openstack/test/test_openstack.py index df38d63c8..20f4dbd54 100644 --- a/teuthology/openstack/test/test_openstack.py +++ b/teuthology/openstack/test/test_openstack.py @@ -34,6 +34,7 @@ import teuthology from teuthology import misc from teuthology.config import set_config_attr from teuthology.openstack import TeuthologyOpenStack, OpenStack, OpenStackInstance +from teuthology.openstack import NoFlavorException import scripts.openstack @@ -213,6 +214,344 @@ class TestOpenStackInstance(object): class TestOpenStack(object): + flavors = """[ + { + "Name": "eg-60", + "RAM": 60000, + "Ephemeral": 0, + "VCPUs": 16, + "Is Public": true, + "Disk": 1600, + "ID": "0297d7ac-fe6f-4ff1-b6e7-0b8b0908c94f" + }, + { + "Name": "win-sp-60", + "RAM": 60000, + "Ephemeral": 0, + "VCPUs": 4, + "Is Public": true, + "Disk": 400, + "ID": "0417a0e6-f68a-4b8b-a642-ca5ecb9652f7" + }, + { + "Name": "win-sp-240", + "RAM": 240000, + "Ephemeral": 0, + "VCPUs": 16, + "Is Public": true, + "Disk": 1600, + "ID": "07885848-8831-486d-8525-91484c09cc7e" + }, + { + "Name": "vps-ssd-1", + "RAM": 2000, + "Ephemeral": 0, + "VCPUs": 1, + "Is Public": true, + "Disk": 10, + "ID": "164fcc7e-7771-414f-a607-b388cb7b7aa0" + }, + { + "Name": "eg-120", + "RAM": 120000, + "Ephemeral": 0, + "VCPUs": 32, + "Is Public": true, + "Disk": 1600, + "ID": "1f1efedf-ec91-4a42-acd7-f5cf64b02d3c" + }, + { + "Name": "win-eg-7", + "RAM": 7000, + "Ephemeral": 0, + "VCPUs": 2, + "Is Public": true, + "Disk": 200, + "ID": "377ded36-491f-4ad7-9eb4-876798b2aea9" + }, + { + "Name": "eg-30", + "RAM": 30000, + "Ephemeral": 0, + "VCPUs": 8, + "Is Public": true, + "Disk": 800, + "ID": "3c1d6170-0097-4b5c-a3b3-adff1b7a86e0" + }, + { + "Name": "eg-15", + "RAM": 15000, + "Ephemeral": 0, + "VCPUs": 4, + "Is Public": true, + "Disk": 400, + "ID": "675558ea-04fe-47a2-83de-40be9b2eacd4" + }, + { + "Name": "win-eg-30", + "RAM": 30000, + "Ephemeral": 0, + "VCPUs": 8, + "Is Public": true, + "Disk": 800, + "ID": "6e12cae3-0492-483c-aa39-54a0dcaf86dd" + }, + { + "Name": "vps-ssd-2", + "RAM": 4000, + "Ephemeral": 0, + "VCPUs": 1, + "Is Public": true, + "Disk": 20, + "ID": "7939cc5c-79b1-45c0-be2d-aa935d92faa1" + }, + { + "Name": "sp-60", + "RAM": 60000, + "Ephemeral": 0, + "VCPUs": 4, + "Is Public": true, + "Disk": 400, + "ID": "80d8510a-79cc-4307-8db7-d1965c9e8ddb" + }, + { + "Name": "win-sp-30", + "RAM": 30000, + "Ephemeral": 0, + "VCPUs": 2, + "Is Public": true, + "Disk": 200, + "ID": "8be9dc29-3eca-499b-ae2d-e3c99699131a" + }, + { + "Name": "sp-120", + "RAM": 120000, + "Ephemeral": 0, + "VCPUs": 8, + "Is Public": true, + "Disk": 800, + "ID": "ac74cb45-d895-47dd-b9cf-c17778033d83" + }, + { + "Name": "win-eg-15", + "RAM": 15000, + "Ephemeral": 0, + "VCPUs": 4, + "Is Public": true, + "Disk": 400, + "ID": "ae900175-72bd-4fbc-8ab2-4673b468aa5b" + }, + { + "Name": "win-eg-120", + "RAM": 120000, + "Ephemeral": 0, + "VCPUs": 32, + "Is Public": true, + "Disk": 1600, + "ID": "b798e44e-bf71-488c-9335-f20bf5976547" + }, + { + "Name": "sp-30", + "RAM": 30000, + "Ephemeral": 0, + "VCPUs": 2, + "Is Public": true, + "Disk": 200, + "ID": "d1acf88d-6f55-4c5c-a914-4ecbdbd50d6b" + }, + { + "Name": "win-eg-60", + "RAM": 60000, + "Ephemeral": 0, + "VCPUs": 16, + "Is Public": true, + "Disk": 1600, + "ID": "def75cbd-a4b1-4f82-9152-90c65df9587b" + }, + { + "Name": "vps-ssd-3", + "RAM": 8000, + "Ephemeral": 0, + "VCPUs": 2, + "Is Public": true, + "Disk": 40, + "ID": "e43d7458-6b82-4a78-a712-3a4dc6748cf4" + }, + { + "Name": "sp-240", + "RAM": 240000, + "Ephemeral": 0, + "VCPUs": 16, + "Is Public": true, + "Disk": 1600, + "ID": "ed286e2c-769f-4c47-ac52-b8de7a4891f6" + }, + { + "Name": "win-sp-120", + "RAM": 120000, + "Ephemeral": 0, + "VCPUs": 8, + "Is Public": true, + "Disk": 800, + "ID": "f247dc56-395b-49de-9a62-93ccc4fff4ed" + }, + { + "Name": "eg-7", + "RAM": 7000, + "Ephemeral": 0, + "VCPUs": 2, + "Is Public": true, + "Disk": 200, + "ID": "fa3cc551-0358-4170-be64-56ea432b064c" + } + ]""" + + @patch('teuthology.misc.sh') + def test_sorted_flavors(self, m_sh): + o = OpenStack() + select = '^(vps|eg)-' + m_sh.return_value = TestOpenStack.flavors + flavors = o.get_sorted_flavors('arch', select) + assert ['vps-ssd-1', + 'vps-ssd-2', + 'eg-7', + 'vps-ssd-3', + 'eg-15', + 'eg-30', + 'eg-60', + 'eg-120', + ] == [ f['Name'] for f in flavors ] + m_sh.assert_called_with("openstack flavor list -f json") + + def test_flavor(self): + def get_sorted_flavors(self, arch, select): + return [ + { + 'Name': 'too_small', + 'RAM': 2048, + 'Disk': 50, + 'VCPUs': 1, + }, + ] + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + with pytest.raises(NoFlavorException): + hint = { 'ram': 1000, 'disk': 40, 'cpus': 2 } + OpenStack().flavor(hint, 'arch', None) + + flavor = 'good-flavor' + def get_sorted_flavors(self, arch, select): + return [ + { + 'Name': flavor, + 'RAM': 2048, + 'Disk': 50, + 'VCPUs': 2, + }, + ] + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + hint = { 'ram': 1000, 'disk': 40, 'cpus': 2 } + assert flavor == OpenStack().flavor(hint, 'arch', None) + + def test_flavor_range(self): + flavors = [ + { + 'Name': 'too_small', + 'RAM': 2048, + 'Disk': 50, + 'VCPUs': 1, + }, + ] + def get_sorted_flavors(self, arch, select): + return flavors + + min = { 'ram': 1000, 'disk': 40, 'cpus': 2 } + good = { 'ram': 4000, 'disk': 40, 'cpus': 2 } + + # + # there are no flavors in the required range + # + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + with pytest.raises(NoFlavorException): + OpenStack().flavor_range(min, good, 'arch', None) + + # + # there is one flavor in the required range + # + flavors.append({ + 'Name': 'min', + 'RAM': 2048, + 'Disk': 40, + 'VCPUs': 2, + }) + + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + + assert 'min' == OpenStack().flavor_range(min, good, 'arch', None) + + # + # out of the two flavors in the required range, get the bigger one + # + flavors.append({ + 'Name': 'good', + 'RAM': 3000, + 'Disk': 40, + 'VCPUs': 2, + }) + + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + + assert 'good' == OpenStack().flavor_range(min, good, 'arch', None) + + # + # there is one flavor bigger or equal to good, get this one + # + flavors.append({ + 'Name': 'best', + 'RAM': 4000, + 'Disk': 40, + 'VCPUs': 2, + }) + + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + + assert 'best' == OpenStack().flavor_range(min, good, 'arch', None) + + # + # there are two flavors bigger or equal to good, get the smallest one + # + flavors.append({ + 'Name': 'too_big', + 'RAM': 30000, + 'Disk': 400, + 'VCPUs': 20, + }) + + with patch.multiple( + OpenStack, + get_sorted_flavors=get_sorted_flavors, + ): + + assert 'best' == OpenStack().flavor_range(min, good, 'arch', None) + + def test_interpret_hints(self): defaults = { 'machine': { diff --git a/teuthology/provision/openstack.py b/teuthology/provision/openstack.py index 49adaf0fa..affb24ba0 100644 --- a/teuthology/provision/openstack.py +++ b/teuthology/provision/openstack.py @@ -109,17 +109,20 @@ class ProvisionOpenStack(OpenStack): described in resources_hint. """ log.debug('ProvisionOpenStack:create') + if arch is None: + arch = self.get_default_arch() resources_hint = self.interpret_hints({ 'machine': config['openstack']['machine'], 'volumes': config['openstack']['volumes'], }, resources_hint) self.init_user_data(os_type, os_version) - image = self.image(os_type, os_version) + image = self.image(os_type, os_version, arch) if 'network' in config['openstack']: net = "--nic net-id=" + str(self.net_id(config['openstack']['network'])) else: net = '' flavor = self.flavor(resources_hint['machine'], + arch, config['openstack'].get('flavor-select-regexp')) cmd = ("flock --close --timeout 28800 /tmp/teuthology-server-create.lock" + " openstack server create" +