Merge "Allow to specify min flavor memory and disk size"
This commit is contained in:
commit
fa359b84c3
@ -27,6 +27,11 @@ DEFAULT_IMAGE = ("http://download.cirros-cloud.net/0.3.5/"
|
||||
"cirros-0.3.5-x86_64-disk.img")
|
||||
DEFAULT_IMAGE_FORMAT = 'qcow2'
|
||||
|
||||
DEFAULT_FLAVOR_RAM = 64
|
||||
DEFAULT_FLAVOR_RAM_ALT = 128
|
||||
DEFAULT_FLAVOR_DISK = 1
|
||||
DEFAULT_FLAVOR_VCPUS = 1
|
||||
|
||||
# The dict holds the credentials, which are not supposed to be printed
|
||||
# to a tempest.conf when --test-accounts CLI parameter is used.
|
||||
ALL_CREDENTIALS_KEYS = {
|
||||
|
@ -15,11 +15,12 @@
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
from config_tempest.constants import LOG
|
||||
from config_tempest import constants as C
|
||||
|
||||
|
||||
class Flavors(object):
|
||||
def __init__(self, client, allow_creation, conf, no_rng=False):
|
||||
def __init__(self, client, allow_creation, conf, min_memory, min_disk,
|
||||
no_rng=False):
|
||||
"""Init.
|
||||
|
||||
:type client: FlavorsClient object from tempest lib
|
||||
@ -29,22 +30,31 @@ class Flavors(object):
|
||||
self.client = client
|
||||
self.allow_creation = allow_creation
|
||||
self._conf = conf
|
||||
self.no_rng = no_rng
|
||||
self.flavor_list = self.client.list_flavors()['flavors']
|
||||
min_memory_alt = C.DEFAULT_FLAVOR_RAM_ALT
|
||||
name = 'm1.nano'
|
||||
name_alt = 'm1.micro'
|
||||
if min_memory != C.DEFAULT_FLAVOR_RAM:
|
||||
min_memory_alt = min_memory + 1
|
||||
name = 'custom'
|
||||
name_alt = 'custom_alt'
|
||||
self._conf.set('volume', 'volume_size', str(min_disk))
|
||||
self.prefs = [
|
||||
{'key': 'flavor_ref', 'name': name, 'ram': min_memory,
|
||||
'disk': min_disk, 'no_rng': no_rng},
|
||||
{'key': 'flavor_ref_alt', 'name': name_alt,
|
||||
'ram': min_memory_alt, 'disk': min_disk, 'no_rng': no_rng}
|
||||
]
|
||||
|
||||
def create_tempest_flavors(self):
|
||||
"""Find or create flavors and set them in conf.
|
||||
|
||||
If 'flavor_ref' and 'flavor_ref_alt' are specified in conf, it will
|
||||
try to find them, if not found, it raises an Exception.
|
||||
Otherwise it will try finding or creating 'm1.nano' and 'm1.micro'
|
||||
flavors and set their ids in conf.
|
||||
Otherwise it will try finding or creating the required base flavors
|
||||
(m1.nano and m1.micro by default) and set their ids in conf.
|
||||
"""
|
||||
prefs = [
|
||||
{'key': 'flavor_ref', 'name': 'm1.nano', 'ram': 64},
|
||||
{'key': 'flavor_ref_alt', 'name': 'm1.micro', 'ram': 128}
|
||||
]
|
||||
for pref in prefs:
|
||||
for pref in self.prefs:
|
||||
flavor_id = None
|
||||
if self._conf.has_option('compute', pref['key']):
|
||||
flavor_id = self._conf.get('compute', pref['key'])
|
||||
@ -53,13 +63,13 @@ class Flavors(object):
|
||||
raise Exception("%s id '%s' specified by user doesn't"
|
||||
" exist", pref['key'], flavor_id)
|
||||
else:
|
||||
# create m1.nano/m1.micro flavor
|
||||
flavor_id = self.create_flavor(pref['name'], ram=pref['ram'],
|
||||
no_rng=self.no_rng)
|
||||
flavor_id = self.create_flavor(pref['name'], pref['ram'],
|
||||
C.DEFAULT_FLAVOR_VCPUS,
|
||||
pref['disk'],
|
||||
no_rng=pref['no_rng'])
|
||||
self._conf.set('compute', pref['key'], flavor_id)
|
||||
|
||||
def create_flavor(self, flavor_name, ram=64, vcpus=1,
|
||||
disk=1, no_rng=False):
|
||||
def create_flavor(self, flavor_name, ram, vcpus, disk, no_rng=False):
|
||||
"""Create flavors or try to discover two smallest ones available.
|
||||
|
||||
:param flavor_name: flavor name to be created (usually m1.nano or
|
||||
@ -71,10 +81,10 @@ class Flavors(object):
|
||||
"""
|
||||
flavor_id = self.find_flavor_by_name(flavor_name)
|
||||
if flavor_id is not None:
|
||||
LOG.info("(no change) Found flavor '%s'", flavor_name)
|
||||
C.LOG.info("(no change) Found flavor '%s'", flavor_name)
|
||||
return flavor_id
|
||||
elif self.allow_creation:
|
||||
LOG.info("Creating flavor '%s'", flavor_name)
|
||||
C.LOG.info("Creating flavor '%s'", flavor_name)
|
||||
resp = self.client.create_flavor(name=flavor_name,
|
||||
ram=ram, vcpus=vcpus,
|
||||
disk=disk, id=None)
|
||||
@ -101,8 +111,8 @@ class Flavors(object):
|
||||
"""
|
||||
found = [f for f in self.flavor_list if f['id'] == flavor_id]
|
||||
if found:
|
||||
LOG.info("Found flavor '%s' by it's id '%s'",
|
||||
found[0]['name'], flavor_id)
|
||||
C.LOG.info("Found flavor '%s' by it's id '%s'",
|
||||
found[0]['name'], flavor_id)
|
||||
# return flavor's id
|
||||
return found[0]['id']
|
||||
return None
|
||||
@ -127,9 +137,9 @@ class Flavors(object):
|
||||
smallest flavor found.
|
||||
:param flavor_name: [m1.nano, m1.micro]
|
||||
"""
|
||||
LOG.warning("Flavor '%s' not found and creation is not allowed. "
|
||||
"Trying to autodetect the smallest flavor available.",
|
||||
flavor_name)
|
||||
C.LOG.warning("Flavor '%s' not found and creation is not allowed. "
|
||||
"Trying to autodetect the smallest flavor available.",
|
||||
flavor_name)
|
||||
flavors = []
|
||||
for flavor in self.flavor_list:
|
||||
f = self.client.show_flavor(flavor['id'])['flavor']
|
||||
@ -145,7 +155,7 @@ class Flavors(object):
|
||||
f = flavors[1]
|
||||
else:
|
||||
f = flavors[0]
|
||||
LOG.warning("Found '%s' flavor (id: '%s', ram: '%s', disk: '%s', "
|
||||
"vcpus: '%s') ", f[0], f[1], f[2], f[3], f[4])
|
||||
C.LOG.warning("Found '%s' flavor (id: '%s', ram: '%s', disk: '%s', "
|
||||
"vcpus: '%s') ", f[0], f[1], f[2], f[3], f[4])
|
||||
# return flavor's id
|
||||
return f[1]
|
||||
|
@ -306,6 +306,12 @@ def get_arg_parser():
|
||||
glance if it's not already there. The name of
|
||||
the image is the leaf name of the path. Default
|
||||
is '%s'""" % C.DEFAULT_IMAGE)
|
||||
parser.add_argument('--flavor-min-mem', default=C.DEFAULT_FLAVOR_RAM,
|
||||
type=int, help="""Specify minimum memory for new
|
||||
flavours, default is '%s'.""" % C.DEFAULT_FLAVOR_RAM)
|
||||
parser.add_argument('--flavor-min-disk', default=C.DEFAULT_FLAVOR_DISK,
|
||||
type=int, help="""Specify minimum disk size for new
|
||||
flavours, default is '%s'.""" % C.DEFAULT_FLAVOR_DISK)
|
||||
parser.add_argument('--network-id',
|
||||
help="""Specify which network with external connectivity
|
||||
should be used by the tests.""")
|
||||
@ -513,6 +519,8 @@ def config_tempest(**kwargs):
|
||||
users = Users(clients.projects, clients.roles, clients.users, conf)
|
||||
users.create_tempest_users(services.is_service('orchestration'))
|
||||
flavors = Flavors(clients.flavors, kwargs.get('create', False), conf,
|
||||
kwargs.get('flavor_min_mem', C.DEFAULT_FLAVOR_RAM),
|
||||
kwargs.get('flavor_min_disk', C.DEFAULT_FLAVOR_DISK),
|
||||
no_rng=kwargs.get('no_rng', False))
|
||||
flavors.create_tempest_flavors()
|
||||
|
||||
@ -569,6 +577,8 @@ def main():
|
||||
create_accounts_file=args.create_accounts_file,
|
||||
debug=args.debug,
|
||||
deployer_input=args.deployer_input,
|
||||
flavor_min_mem=args.flavor_min_mem,
|
||||
flavor_min_disk=args.flavor_min_disk,
|
||||
image_disk_format=args.image_disk_format,
|
||||
image_path=args.image,
|
||||
network_id=args.network_id,
|
||||
|
@ -17,6 +17,7 @@ from fixtures import MonkeyPatch
|
||||
import logging
|
||||
import mock
|
||||
|
||||
from config_tempest import constants as C
|
||||
from config_tempest.flavors import Flavors
|
||||
from config_tempest.tests.base import BaseConfigTempestTest
|
||||
|
||||
@ -44,7 +45,7 @@ class TestFlavors(BaseConfigTempestTest):
|
||||
mock_function = mock.Mock(return_value=return_value)
|
||||
self.useFixture(MonkeyPatch(self.CLIENT_MOCK + '.list_flavors',
|
||||
mock_function))
|
||||
self.Service = Flavors(self.client, True, self.conf)
|
||||
self.Service = Flavors(self.client, True, self.conf, 64, 1)
|
||||
|
||||
def test_create_tempest_flavors(self):
|
||||
self.Service.flavor_list = []
|
||||
@ -54,8 +55,8 @@ class TestFlavors(BaseConfigTempestTest):
|
||||
self.Service.create_tempest_flavors()
|
||||
self.assertEqual(self.conf.get('compute', 'flavor_ref'), "FakeID")
|
||||
self.assertEqual(self.conf.get('compute', 'flavor_ref_alt'), "FakeID")
|
||||
calls = [mock.call('m1.nano', ram=64, no_rng=False),
|
||||
mock.call('m1.micro', ram=128, no_rng=False)]
|
||||
calls = [mock.call('m1.nano', 64, 1, 1, no_rng=False),
|
||||
mock.call('m1.micro', 128, 1, 1, no_rng=False)]
|
||||
mock_function.assert_has_calls(calls, any_order=True)
|
||||
|
||||
def check_call_of_discover_smallest_flavor(self):
|
||||
@ -65,7 +66,9 @@ class TestFlavors(BaseConfigTempestTest):
|
||||
func2mock = 'config_tempest.flavors.Flavors.discover_smallest_flavor'
|
||||
mock_function = mock.Mock()
|
||||
self.useFixture(MonkeyPatch(func2mock, mock_function))
|
||||
self.Service.create_flavor('nano')
|
||||
self.Service.create_flavor('nano', C.DEFAULT_FLAVOR_RAM,
|
||||
C.DEFAULT_FLAVOR_VCPUS,
|
||||
C.DEFAULT_FLAVOR_DISK)
|
||||
calls = [mock.call('nano')]
|
||||
mock_function.assert_has_calls(calls, any_order=True)
|
||||
|
||||
@ -95,7 +98,9 @@ class TestFlavors(BaseConfigTempestTest):
|
||||
self.Service.allow_creation = False
|
||||
self.Service.flavor_list = []
|
||||
try:
|
||||
self.Service.create_flavor('name')
|
||||
self.Service.create_flavor('name', C.DEFAULT_FLAVOR_RAM,
|
||||
C.DEFAULT_FLAVOR_VCPUS,
|
||||
C.DEFAULT_FLAVOR_DISK)
|
||||
except Exception:
|
||||
return
|
||||
# it should have ended in the except block above
|
||||
@ -104,7 +109,9 @@ class TestFlavors(BaseConfigTempestTest):
|
||||
# not enough flavors found
|
||||
self.Service.flavor_list = [{'id': 'FAKE', 'name': 'fake_name'}]
|
||||
try:
|
||||
self.Service.create_flavor('name')
|
||||
self.Service.create_flavor('name', C.DEFAULT_FLAVOR_RAM,
|
||||
C.DEFAULT_FLAVOR_VCPUS,
|
||||
C.DEFAULT_FLAVOR_DISK)
|
||||
except Exception:
|
||||
return
|
||||
# it should have ended in the except block above
|
||||
@ -119,7 +126,10 @@ class TestFlavors(BaseConfigTempestTest):
|
||||
mock_function = mock.Mock(return_value={})
|
||||
self.useFixture(MonkeyPatch(client + '.set_flavor_extra_spec',
|
||||
mock_function))
|
||||
resp = self.Service.create_flavor(flavor_name="MyID", no_rng=no_rng)
|
||||
resp = self.Service.create_flavor("MyID", C.DEFAULT_FLAVOR_RAM,
|
||||
C.DEFAULT_FLAVOR_VCPUS,
|
||||
C.DEFAULT_FLAVOR_DISK,
|
||||
no_rng=no_rng)
|
||||
self.assertEqual(resp, return_value['flavor']['id'])
|
||||
return mock_function
|
||||
|
||||
|
@ -39,6 +39,21 @@ resources (`Flavors`_ and `Users`_) if they don't exist already:
|
||||
--os-cloud devstack-admin \
|
||||
--create
|
||||
|
||||
If a user wants to use a custom image (instead of the default cirros one),
|
||||
a minimum memory and disk size for new flavors can be defined by
|
||||
``--flavor-min-mem`` and ``--flavor-min-disk`` arguments.
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
$ discover-tempest-config \
|
||||
--image <path/url to custom image> \
|
||||
--flavor-min-mem 1024 \
|
||||
--flavor-min-disk 10
|
||||
|
||||
In the example above ``python-tempestconf`` will create *custom* flavor with
|
||||
1024 MB of RAM and 10 GB of disk size and *custom_alt** flavor with 1024 + 1 MB
|
||||
of RAM and 10 GB of disk size.
|
||||
|
||||
|
||||
``python-tempestconf`` can also create a minimal accounts file when
|
||||
``--create-accounts-file`` is used. It can be useful when a user doesn't have
|
||||
|
@ -14,7 +14,7 @@ of the following:
|
||||
* use ``clouds.yaml`` file and take advantage of ``os-client-config`` support
|
||||
and use a named cloud, see `Examples of usage with a named cloud`_
|
||||
|
||||
If a user doesn't use ``--create``, no resources, which requires admin
|
||||
If a user doesn't use ``--create``, no resources, which require admin
|
||||
credentials, are created. See `Resources`_ section.
|
||||
|
||||
|
||||
@ -66,8 +66,8 @@ generated ``tempest.conf`` from one of the two following reasons:
|
||||
* ``python-tempestconf`` is able to discover it, but a user wants to set it
|
||||
differently
|
||||
|
||||
Values specified as overrides will be set to tempest.conf no matter what if
|
||||
they were discovered or not. If a section or a key don't exist, they will be
|
||||
Values specified as overrides will be set to tempest.conf no matter if they
|
||||
were discovered or not. If a section or a key don't exist, they will be
|
||||
created.
|
||||
|
||||
In the following example we make the tool to print debugging information, we
|
||||
@ -110,7 +110,7 @@ A user can define key-value pairs which are not wanted to be written to the
|
||||
generated ``tempest.conf``. This can be useful in case when
|
||||
``python-tempestconf`` discovers something which is not wanted by a user to
|
||||
have in ``tempest.conf``. If the option is used, ``python-tempestconf`` will
|
||||
make sure, that the defined values are not written to tempest.conf no matter
|
||||
make sure that the defined values are not written to tempest.conf no matter
|
||||
if they were discovered or not.
|
||||
|
||||
.. code-block:: shell-session
|
||||
@ -120,9 +120,9 @@ if they were discovered or not.
|
||||
--remove section2.key2=value \
|
||||
--remove section3.key3=value1,value2
|
||||
|
||||
In the following case **all** api_extensions will be removed and tempest.conf
|
||||
will **not contain** the api_extensions key under compute-feature-enabled
|
||||
section.
|
||||
In the following case **all** api_extensions will be removed and
|
||||
``tempest.conf`` will **not contain** the api_extensions key under
|
||||
compute-feature-enabled section.
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
@ -190,7 +190,7 @@ links:
|
||||
* `how to generate it? <https://docs.openstack.org/tempest/latest/account_generator.html>`_
|
||||
|
||||
When ``--test-accounts`` argument is used, ``python-tempestconf`` will not
|
||||
write any credentials to generated tempest.conf file, it will add a
|
||||
write any credentials to generated ``tempest.conf`` file, it will add a
|
||||
**test_accounts_file** key to **auth** section with value equal to the path
|
||||
provided by the ``--test-accounts`` argument. Also **use_dynamic_credentials**
|
||||
under **auth** section will be set to False as
|
||||
@ -210,7 +210,7 @@ If you already have the file created, you can run
|
||||
--out etc/tempest.conf \
|
||||
--test-accounts /path/to/my/accounts.yaml
|
||||
|
||||
The generated tempest.conf will look like:
|
||||
The generated ``tempest.conf`` will look like:
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
@ -272,8 +272,8 @@ Then if you use ``--os-cloud`` argument you can run
|
||||
:command:`discover-tempest-config` **without** setting any OS_* environment
|
||||
variable (for example by sourcing any OpenStack RC file).
|
||||
|
||||
``--os-cloud`` defines specifies one of the cloud names located in the
|
||||
``clouds.yaml`` file.
|
||||
``--os-cloud`` specifies one of the cloud names located in the ``clouds.yaml``
|
||||
file.
|
||||
|
||||
.. code-block:: shell-session
|
||||
:emphasize-lines: 3
|
||||
@ -308,7 +308,7 @@ look like:
|
||||
Resources
|
||||
---------
|
||||
|
||||
Without specifying ``--create`` argument, no resources which requires admin
|
||||
Without specifying ``--create`` argument, no resources which require admin
|
||||
credentials are crated during the ``python-tempestconf`` execution. For the
|
||||
documentation on how to use ``--create`` argument see `Admin User Guide`_
|
||||
|
||||
@ -405,10 +405,25 @@ image.
|
||||
Flavors
|
||||
+++++++
|
||||
|
||||
``python-tempestconf`` looks for these two flavors:
|
||||
``python-tempestconf`` looks by default for these two flavors:
|
||||
|
||||
* m1.nano with 64 MB of RAM, which will be set as **compute.flavor_ref**
|
||||
* m1.micro with 128 MB of RAM, which will be set as **compute.flavor_alt_ref**
|
||||
* *m1.nano* with 64 MB of RAM, which will be set as **compute.flavor_ref**
|
||||
* *m1.micro* with 128 MB of RAM, which will be set as
|
||||
**compute.flavor_alt_ref**
|
||||
|
||||
If a user used ``--flavor-min-mem`` argument, ``python-tempestconf`` will look
|
||||
for these two flavors:
|
||||
|
||||
* *custom*
|
||||
* *custom_alt*
|
||||
|
||||
.. note::
|
||||
|
||||
``python-tempestconf`` looks for flavors by name, so if a user has had
|
||||
a flavor with name *custom*/*custom_alt* already created, those flavors'
|
||||
IDs will be set as **compute.flavor_ref**/**compute.flavor_ref_alt**
|
||||
without checking if theirs RAM size is equal to the one specified by
|
||||
``--flavor-min-mem``.
|
||||
|
||||
If they are not found and ``--create`` argument is not used, the tool will try
|
||||
to auto discover two smallest flavors available in the system. If at least two
|
||||
@ -435,7 +450,7 @@ The generated tempest.conf will look like:
|
||||
flavor_alt_ref = <ID_2>
|
||||
<omitted some content>
|
||||
|
||||
In the following example, a `override`_ option specifies **compute.flavor_ref**
|
||||
In the following example, an `override`_ option specifies **compute.flavor_ref**
|
||||
ID, which if it's found, the tool continues with looking for a **m1.micro**
|
||||
flavor to be set as **compute.flavor_alt_ref** as was explained above.
|
||||
|
||||
@ -447,4 +462,4 @@ flavor to be set as **compute.flavor_alt_ref** as was explained above.
|
||||
|
||||
.. note::
|
||||
If the **compute.flavor_ref** ID is not found, the tool ends with an
|
||||
exception.
|
||||
exception.
|
||||
|
Loading…
x
Reference in New Issue
Block a user