summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Riedemann <mriedem.os@gmail.com>2017-07-13 17:13:46 -0400
committerMatt Riedemann <mriedem.os@gmail.com>2017-07-15 12:54:48 -0400
commit8ab54527f8bfd62049dcfc3c77ba8f28c99ee322 (patch)
tree6fa1f0dc04a33f18e5f4462ad2165b9b566c9b49
parent77f940c5345d662fd7adef410ea0989e35fa2664 (diff)
downloadpython-novaclient-8ab54527f8bfd62049dcfc3c77ba8f28c99ee322.tar.gz
Add functional test for resize-confirm plus quota validation
With the upcoming counting quotas changes in Nova, and the fact the novaclient functional tests are run in serial with the same tenant, it would be useful to validate that "nova resize-confirm" works as expected and that the quota usage before, during and after the resize is confirmed is as expected, that is, when resizing we expect the quota usage to change. Change-Id: Id5be8edfde446b9e714460a606b446a2daf64007
-rw-r--r--novaclient/tests/functional/base.py15
-rw-r--r--novaclient/tests/functional/v2/test_resize.py104
2 files changed, 119 insertions, 0 deletions
diff --git a/novaclient/tests/functional/base.py b/novaclient/tests/functional/base.py
index a374601f..637ae52b 100644
--- a/novaclient/tests/functional/base.py
+++ b/novaclient/tests/functional/base.py
@@ -484,6 +484,11 @@ class ClientTestBase(testtools.TestCase):
'building', ['active'])
return server
+ def _wait_for_state_change(self, server_id, status):
+ novaclient.v2.shell._poll_for_status(
+ self.client.servers.get, server_id, None, [status],
+ show_progress=False, poll_period=1, silent=True)
+
def _get_project_id(self, name):
"""Obtain project id by project name."""
if self.keystone.version == "v3":
@@ -497,6 +502,16 @@ class ClientTestBase(testtools.TestCase):
self.client.servers.delete(server_id)
self.wait_for_resource_delete(server_id, self.client.servers)
+ def _get_absolute_limits(self):
+ """Returns the absolute limits (quota usage) including reserved quota
+ usage for the given tenant running the test.
+
+ :return: A dict where the key is the limit (or usage) and value.
+ """
+ # The absolute limits are returned in a generator so convert to a dict.
+ return {limit.name: limit.value
+ for limit in self.client.limits.get(reserved=True).absolute}
+
class TenantTestBase(ClientTestBase):
"""Base test class for additional tenant and user creation which
diff --git a/novaclient/tests/functional/v2/test_resize.py b/novaclient/tests/functional/v2/test_resize.py
new file mode 100644
index 00000000..6884e4ba
--- /dev/null
+++ b/novaclient/tests/functional/v2/test_resize.py
@@ -0,0 +1,104 @@
+# Copyright 2017 Huawei Technologies Co.,LTD.
+#
+# 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 novaclient.tests.functional import base
+
+
+class TestServersResize(base.ClientTestBase):
+ """Servers resize functional tests."""
+
+ COMPUTE_API_VERSION = '2.1'
+
+ def _create_server(self, name, flavor):
+ """Boots a server with the given name and flavor and waits for it to
+ be ACTIVE.
+ """
+ params = (
+ "%(name)s --flavor %(flavor)s --image %(image)s --poll " % {
+ "name": self.name_generate(name),
+ "flavor": flavor,
+ "image": self.image.id})
+ # check to see if we have to pass in a network id
+ if self.multiple_networks:
+ params += ' --nic net-id=%s' % self.network.id
+ server_info = self.nova("boot", params=params)
+ server_id = self._get_value_from_the_table(server_info, "id")
+ self.addCleanup(self._cleanup_server, server_id)
+ return server_id
+
+ def _pick_alternate_flavor(self):
+ """Given the flavor picked in the base class setup, this finds the
+ opposite flavor to use for a resize test. For example, if m1.nano is
+ the flavor, then use m1.micro, but those are only available if Tempest
+ is configured. If m1.tiny, then use m1.small.
+ """
+ flavor_name = self.flavor.name
+ if flavor_name == 'm1.nano':
+ # This is an upsize test.
+ return 'm1.micro'
+ if flavor_name == 'm1.micro':
+ # This is a downsize test.
+ return 'm1.nano'
+ if flavor_name == 'm1.tiny':
+ # This is an upsize test.
+ return 'm1.small'
+ if flavor_name == 'm1.small':
+ # This is a downsize test.
+ return 'm1.tiny'
+ self.fail('Unable to find alternate for flavor: %s' % flavor_name)
+
+ def _compare_quota_usage(self, old_usage, new_usage, expect_diff=True):
+ """Compares the quota usage in the provided AbsoluteLimits."""
+ # For a resize, instance usage shouldn't change.
+ self.assertEqual(old_usage['totalInstancesUsed'],
+ new_usage['totalInstancesUsed'],
+ 'totalInstancesUsed does not match')
+ # For the resize we're doing, those flavors have the same vcpus so we
+ # don't expect any quota change.
+ self.assertEqual(old_usage['totalCoresUsed'],
+ new_usage['totalCoresUsed'],
+ 'totalCoresUsed does not match')
+ # RAM is the only thing that will change for these flavors in a resize.
+ if expect_diff:
+ self.assertNotEqual(old_usage['totalRAMUsed'],
+ new_usage['totalRAMUsed'],
+ 'totalRAMUsed should have changed')
+ else:
+ self.assertEqual(old_usage['totalRAMUsed'],
+ new_usage['totalRAMUsed'],
+ 'totalRAMUsed does not match')
+
+ def test_resize_up_confirm(self):
+ """Tests creating a server and resizes up and confirms the resize.
+ Compares quota before, during and after the resize.
+ """
+ server_id = self._create_server('resize-up-confirm', self.flavor.name)
+ # get the starting quota now that we've created a server
+ starting_usage = self._get_absolute_limits()
+ # now resize up
+ alternate_flavor = self._pick_alternate_flavor()
+ self.nova('resize',
+ params='%s %s --poll' % (server_id, alternate_flavor))
+ resize_usage = self._get_absolute_limits()
+ # compare the starting usage against the resize usage
+ self._compare_quota_usage(starting_usage, resize_usage)
+ # now confirm the resize
+ self.nova('resize-confirm', params='%s' % server_id)
+ # we have to wait for the server to be ACTIVE before we can check quota
+ self._wait_for_state_change(server_id, 'active')
+ # get the final quota usage which should be the same as the resize
+ # usage before confirm
+ confirm_usage = self._get_absolute_limits()
+ self._compare_quota_usage(
+ resize_usage, confirm_usage, expect_diff=False)