diff --git a/doc/source/man/nova-manage.rst b/doc/source/man/nova-manage.rst index 49fd3abb2f71..39e5ac2ec0fc 100644 --- a/doc/source/man/nova-manage.rst +++ b/doc/source/man/nova-manage.rst @@ -105,6 +105,24 @@ Nova Shell Runs the named script from the specified path with flags set. +Nova Project +~~~~~~~~~~~~ + +``nova-manage project quota [--user ] [--key ] [--value ]`` + + Create, update or display quotas for project/user. If a key is + not specified then the current usages are displayed. + +``nova-manage project quota_usage_refresh [--user ] [--key ]`` + + Refresh the quota usages for the project/user so that the + usage record matches the actual used. If a key is not specified + then all quota usages relevant to the project/user are refreshed. + +``nova-manage project scrub `` + + Deletes data associated with project. + Nova VPN ~~~~~~~~ diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index f86954286676..eae5ae565876 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -292,6 +292,30 @@ class ProjectCommands(object): print(print_format % (key, value['limit'], value['in_use'], value['reserved'])) + @args('--project', dest='project_id', metavar='', + help='Project Id', required=True) + @args('--user', dest='user_id', metavar='', + help='User Id') + @args('--key', metavar='', help='Key') + def quota_usage_refresh(self, project_id, user_id=None, key=None): + """Refresh the quotas for project/user + + If no quota key is provided, all the quota usages will be refreshed. + If a valid quota key is provided and it does not exist, + it will be created. Otherwise, it will be refreshed. + """ + ctxt = context.get_admin_context() + + keys = None + if key: + keys = [key] + + try: + QUOTAS.usage_refresh(ctxt, project_id, user_id, keys) + except exception.QuotaUsageRefreshNotAllowed as e: + print(e.format_message()) + return 2 + @args('--project', dest='project_id', metavar='', help='Project name') def scrub(self, project_id): diff --git a/nova/tests/unit/test_nova_manage.py b/nova/tests/unit/test_nova_manage.py index 6f04e1a3d432..812d24694522 100644 --- a/nova/tests/unit/test_nova_manage.py +++ b/nova/tests/unit/test_nova_manage.py @@ -391,6 +391,33 @@ class ProjectCommandsTestCase(test.TestCase): def test_quota_update_invalid_key(self): self.assertEqual(2, self.commands.quota('admin', 'volumes1', '10')) + def test_quota_usage_refresh_all_user_keys(self): + self.assertIsNone(self.commands.quota_usage_refresh( + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab')) + + def test_quota_usage_refresh_all_project_keys(self): + self.assertIsNone(self.commands.quota_usage_refresh( + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa')) + + def test_quota_usage_refresh_with_keys(self): + self.assertIsNone(self.commands.quota_usage_refresh( + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', + 'ram')) + + def test_quota_usage_refresh_invalid_user_key(self): + self.assertEqual(2, self.commands.quota_usage_refresh( + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', + 'fixed_ip')) + + def test_quota_usage_refresh_invalid_project_key(self): + self.assertEqual(2, self.commands.quota_usage_refresh( + 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', + None, + 'ram')) + class VmCommandsTestCase(test.NoDBTestCase): def setUp(self): diff --git a/releasenotes/notes/refresh-quotas-usage-362b239171c75f5f.yaml b/releasenotes/notes/refresh-quotas-usage-362b239171c75f5f.yaml new file mode 100644 index 000000000000..1fed26985c48 --- /dev/null +++ b/releasenotes/notes/refresh-quotas-usage-362b239171c75f5f.yaml @@ -0,0 +1,11 @@ +--- +features: + - Add a nova-manage command to refresh the quota + usages for a project or user. This can be used + when the usages in the quota-usages database table + are out-of-sync with the actual usages. For example, + if a resource usage is at the limit in the quota_usages + table, but the actual usage is less, then nova will + not allow VMs to be created for that project or user. + The nova-manage command can be used to re-sync + the quota_usages table with the actual usage.