Browse Source

Adds first part of quotas support for Nova V3 API

Adds support and tests for the os-quotas extension
for the Nova V3 API. Note that compared to the V2
version this removes the ability to set quotas
which are not relevant to the V3 API (eg injected
file quotas are not relevant because the
os-personalities extension has been removed)

Partially implements blueprint v3-api

Change-Id: Ifa1c77428424bedf7fb88ef6d7b3843376799d24
tags/2.16.0
Chris Yeoh 5 years ago
parent
commit
cfd38a7ef6

+ 24
- 20
novaclient/tests/v1_1/test_quotas.py View File

@@ -16,54 +16,58 @@
16 16
 from novaclient.tests import utils
17 17
 from novaclient.tests.v1_1 import fakes
18 18
 
19
-cs = fakes.FakeClient()
20
-
21 19
 
22 20
 class QuotaSetsTest(utils.TestCase):
21
+    def setUp(self):
22
+        super(QuotaSetsTest, self).setUp()
23
+        self.cs = self._get_fake_client()
24
+
25
+    def _get_fake_client(self):
26
+        return fakes.FakeClient()
23 27
 
24 28
     def test_tenant_quotas_get(self):
25 29
         tenant_id = 'test'
26
-        cs.quotas.get(tenant_id)
27
-        cs.assert_called('GET', '/os-quota-sets/%s' % tenant_id)
30
+        self.cs.quotas.get(tenant_id)
31
+        self.cs.assert_called('GET', '/os-quota-sets/%s' % tenant_id)
28 32
 
29 33
     def test_user_quotas_get(self):
30 34
         tenant_id = 'test'
31 35
         user_id = 'fake_user'
32
-        cs.quotas.get(tenant_id, user_id=user_id)
36
+        self.cs.quotas.get(tenant_id, user_id=user_id)
33 37
         url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id)
34
-        cs.assert_called('GET', url)
38
+        self.cs.assert_called('GET', url)
35 39
 
36 40
     def test_tenant_quotas_defaults(self):
37 41
         tenant_id = '97f4c221bff44578b0300df4ef119353'
38
-        cs.quotas.defaults(tenant_id)
39
-        cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id)
42
+        self.cs.quotas.defaults(tenant_id)
43
+        self.cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id)
40 44
 
41 45
     def test_update_quota(self):
42
-        q = cs.quotas.get('97f4c221bff44578b0300df4ef119353')
46
+        q = self.cs.quotas.get('97f4c221bff44578b0300df4ef119353')
43 47
         q.update(volumes=2)
44
-        cs.assert_called('PUT',
48
+        self.cs.assert_called('PUT',
45 49
                    '/os-quota-sets/97f4c221bff44578b0300df4ef119353')
46 50
 
47 51
     def test_update_user_quota(self):
48 52
         tenant_id = '97f4c221bff44578b0300df4ef119353'
49 53
         user_id = 'fake_user'
50
-        q = cs.quotas.get(tenant_id)
54
+        q = self.cs.quotas.get(tenant_id)
51 55
         q.update(volumes=2, user_id=user_id)
52 56
         url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id)
53
-        cs.assert_called('PUT', url)
57
+        self.cs.assert_called('PUT', url)
54 58
 
55 59
     def test_force_update_quota(self):
56
-        q = cs.quotas.get('97f4c221bff44578b0300df4ef119353')
60
+        q = self.cs.quotas.get('97f4c221bff44578b0300df4ef119353')
57 61
         q.update(cores=2, force=True)
58
-        cs.assert_called(
62
+        self.cs.assert_called(
59 63
             'PUT', '/os-quota-sets/97f4c221bff44578b0300df4ef119353',
60 64
             {'quota_set': {'force': True,
61 65
                            'cores': 2,
62 66
                            'tenant_id': '97f4c221bff44578b0300df4ef119353'}})
63 67
 
64 68
     def test_refresh_quota(self):
65
-        q = cs.quotas.get('test')
66
-        q2 = cs.quotas.get('test')
69
+        q = self.cs.quotas.get('test')
70
+        q2 = self.cs.quotas.get('test')
67 71
         self.assertEqual(q.volumes, q2.volumes)
68 72
         q2.volumes = 0
69 73
         self.assertNotEqual(q.volumes, q2.volumes)
@@ -72,12 +76,12 @@ class QuotaSetsTest(utils.TestCase):
72 76
 
73 77
     def test_quotas_delete(self):
74 78
         tenant_id = 'test'
75
-        cs.quotas.delete(tenant_id)
76
-        cs.assert_called('DELETE', '/os-quota-sets/%s' % tenant_id)
79
+        self.cs.quotas.delete(tenant_id)
80
+        self.cs.assert_called('DELETE', '/os-quota-sets/%s' % tenant_id)
77 81
 
78 82
     def test_user_quotas_delete(self):
79 83
         tenant_id = 'test'
80 84
         user_id = 'fake_user'
81
-        cs.quotas.delete(tenant_id, user_id=user_id)
85
+        self.cs.quotas.delete(tenant_id, user_id=user_id)
82 86
         url = '/os-quota-sets/%s?user_id=%s' % (tenant_id, user_id)
83
-        cs.assert_called('DELETE', url)
87
+        self.cs.assert_called('DELETE', url)

+ 21
- 0
novaclient/tests/v3/fakes.py View File

@@ -271,3 +271,24 @@ class FakeHTTPClient(fakes_v1_1.FakeHTTPClient):
271 271
                               {"zone_name": "zone-2",
272 272
                                "zone_state": {"available": False},
273 273
                                "hosts": None}]})
274
+
275
+    #
276
+    # Quotas
277
+    #
278
+    def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw):
279
+        assert list(body) == ['quota_set']
280
+        return (200, {}, {'quota_set': {
281
+                      'tenant_id': '97f4c221bff44578b0300df4ef119353',
282
+                      'metadata_items': [],
283
+                      'injected_file_content_bytes': 1,
284
+                      'injected_file_path_bytes': 1,
285
+                      'volumes': 2,
286
+                      'gigabytes': 1,
287
+                      'ram': 1,
288
+                      'floating_ips': 1,
289
+                      'instances': 1,
290
+                      'injected_files': 1,
291
+                      'cores': 1,
292
+                      'keypairs': 1,
293
+                      'security_groups': 1,
294
+                      'security_group_rules': 1}})

+ 33
- 0
novaclient/tests/v3/test_quotas.py View File

@@ -0,0 +1,33 @@
1
+# Copyright IBM Corp. 2013
2
+#
3
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+#    not use this file except in compliance with the License. You may obtain
5
+#    a copy of the License at
6
+#
7
+#         http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+#    Unless required by applicable law or agreed to in writing, software
10
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+#    License for the specific language governing permissions and limitations
13
+#    under the License.
14
+
15
+from novaclient.tests.v1_1 import test_quotas
16
+from novaclient.tests.v3 import fakes
17
+
18
+
19
+class QuotaSetsTest(test_quotas.QuotaSetsTest):
20
+    def setUp(self):
21
+        super(QuotaSetsTest, self).setUp()
22
+        self.cs = self._get_fake_client()
23
+
24
+    def _get_fake_client(self):
25
+        return fakes.FakeClient()
26
+
27
+    def test_force_update_quota(self):
28
+        q = self.cs.quotas.get('97f4c221bff44578b0300df4ef119353')
29
+        q.update(cores=2, force=True)
30
+        self.cs.assert_called(
31
+            'PUT', '/os-quota-sets/97f4c221bff44578b0300df4ef119353',
32
+            {'quota_set': {'force': True,
33
+                           'cores': 2}})

+ 7
- 24
novaclient/v1_1/quotas.py View File

@@ -41,31 +41,14 @@ class QuotaSetManager(base.Manager):
41 41
             url = '/os-quota-sets/%s' % tenant_id
42 42
         return self._get(url, "quota_set")
43 43
 
44
-    def update(self, tenant_id, metadata_items=None,
45
-               injected_file_content_bytes=None, injected_file_path_bytes=None,
46
-               volumes=None, gigabytes=None,
47
-               ram=None, floating_ips=None, fixed_ips=None, instances=None,
48
-               injected_files=None, cores=None, key_pairs=None,
49
-               security_groups=None, security_group_rules=None, force=None,
50
-               user_id=None):
44
+    def _update_body(self, tenant_id, **kwargs):
45
+        kwargs['tenant_id'] = tenant_id
46
+        return {'quota_set': kwargs}
51 47
 
52
-        body = {'quota_set': {
53
-                'tenant_id': tenant_id,
54
-                'metadata_items': metadata_items,
55
-                'key_pairs': key_pairs,
56
-                'injected_file_content_bytes': injected_file_content_bytes,
57
-                'injected_file_path_bytes': injected_file_path_bytes,
58
-                'volumes': volumes,
59
-                'gigabytes': gigabytes,
60
-                'ram': ram,
61
-                'floating_ips': floating_ips,
62
-                'fixed_ips': fixed_ips,
63
-                'instances': instances,
64
-                'injected_files': injected_files,
65
-                'cores': cores,
66
-                'security_groups': security_groups,
67
-                'security_group_rules': security_group_rules,
68
-                'force': force}}
48
+    def update(self, tenant_id, **kwargs):
49
+
50
+        user_id = kwargs.pop('user_id', None)
51
+        body = self._update_body(tenant_id, **kwargs)
69 52
 
70 53
         for key in list(body['quota_set']):
71 54
             if body['quota_set'][key] is None:

+ 2
- 0
novaclient/v3/client.py View File

@@ -21,6 +21,7 @@ from novaclient.v3 import flavor_access
21 21
 from novaclient.v3 import flavors
22 22
 from novaclient.v3 import hosts
23 23
 from novaclient.v3 import images
24
+from novaclient.v3 import quotas
24 25
 from novaclient.v3 import servers
25 26
 
26 27
 
@@ -63,6 +64,7 @@ class Client(object):
63 64
         self.flavors = flavors.FlavorManager(self)
64 65
         self.flavor_access = flavor_access.FlavorAccessManager(self)
65 66
         self.images = images.ImageManager(self)
67
+        self.quotas = quotas.QuotaSetManager(self)
66 68
         self.servers = servers.ServerManager(self)
67 69
 
68 70
         # Add in any extensions...

+ 27
- 0
novaclient/v3/quotas.py View File

@@ -0,0 +1,27 @@
1
+# Copyright 2011 OpenStack Foundation
2
+# All Rights Reserved.
3
+#
4
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+#    not use this file except in compliance with the License. You may obtain
6
+#    a copy of the License at
7
+#
8
+#         http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+#    Unless required by applicable law or agreed to in writing, software
11
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+#    License for the specific language governing permissions and limitations
14
+#    under the License.
15
+
16
+from novaclient.v1_1 import quotas
17
+
18
+
19
+class QuotaSet(quotas.QuotaSet):
20
+    pass
21
+
22
+
23
+class QuotaSetManager(quotas.QuotaSetManager):
24
+    resource_class = QuotaSet
25
+
26
+    def _update_body(self, tenant_id, **kwargs):
27
+        return {'quota_set': kwargs}

+ 2
- 49
novaclient/v3/shell.py View File

@@ -32,7 +32,6 @@ from novaclient.openstack.common import strutils
32 32
 from novaclient.openstack.common import timeutils
33 33
 from novaclient.openstack.common import uuidutils
34 34
 from novaclient import utils
35
-from novaclient.v1_1 import quotas
36 35
 from novaclient.v3 import availability_zones
37 36
 from novaclient.v3 import servers
38 37
 
@@ -2829,10 +2828,7 @@ def do_ssh(cs, args):
2829 2828
 
2830 2829
 
2831 2830
 _quota_resources = ['instances', 'cores', 'ram', 'volumes', 'gigabytes',
2832
-                    'floating_ips', 'fixed_ips', 'metadata_items',
2833
-                    'injected_files', 'key_pairs',
2834
-                    'injected_file_content_bytes', 'injected_file_path_bytes',
2835
-                    'security_groups', 'security_group_rules']
2831
+                    'fixed_ips', 'metadata_items', 'key_pairs']
2836 2832
 
2837 2833
 
2838 2834
 def _quota_show(quotas):
@@ -2855,11 +2851,7 @@ def _quota_update(manager, identifier, args):
2855 2851
     if updates:
2856 2852
         # default value of force is None to make sure this client
2857 2853
         # will be compatibile with old nova server
2858
-        force_update = getattr(args, 'force', None)
2859
-        if isinstance(manager, quotas.QuotaSetManager):
2860
-            manager.update(identifier, force=force_update, **updates)
2861
-        else:
2862
-            manager.update(identifier, **updates)
2854
+        manager.update(identifier, **updates)
2863 2855
 
2864 2856
 
2865 2857
 @utils.arg('--tenant',
@@ -2911,14 +2903,6 @@ def do_quota_defaults(cs, args):
2911 2903
            metavar='<gigabytes>',
2912 2904
            type=int, default=None,
2913 2905
            help='New value for the "gigabytes" quota.')
2914
-@utils.arg('--floating-ips',
2915
-    metavar='<floating-ips>',
2916
-    type=int,
2917
-    default=None,
2918
-    help='New value for the "floating-ips" quota.')
2919
-@utils.arg('--floating_ips',
2920
-    type=int,
2921
-    help=argparse.SUPPRESS)
2922 2906
 @utils.arg('--fixed-ips',
2923 2907
     metavar='<fixed-ips>',
2924 2908
     type=int,
@@ -2932,42 +2916,11 @@ def do_quota_defaults(cs, args):
2932 2916
 @utils.arg('--metadata_items',
2933 2917
     type=int,
2934 2918
     help=argparse.SUPPRESS)
2935
-@utils.arg('--injected-files',
2936
-    metavar='<injected-files>',
2937
-    type=int,
2938
-    default=None,
2939
-    help='New value for the "injected-files" quota.')
2940
-@utils.arg('--injected_files',
2941
-    type=int,
2942
-    help=argparse.SUPPRESS)
2943
-@utils.arg('--injected-file-content-bytes',
2944
-    metavar='<injected-file-content-bytes>',
2945
-    type=int,
2946
-    default=None,
2947
-    help='New value for the "injected-file-content-bytes" quota.')
2948
-@utils.arg('--injected_file_content_bytes',
2949
-    type=int,
2950
-    help=argparse.SUPPRESS)
2951
-@utils.arg('--injected-file-path-bytes',
2952
-    metavar='<injected-file-path-bytes>',
2953
-    type=int,
2954
-    default=None,
2955
-    help='New value for the "injected-file-path-bytes" quota.')
2956 2919
 @utils.arg('--key-pairs',
2957 2920
     metavar='<key-pairs>',
2958 2921
     type=int,
2959 2922
     default=None,
2960 2923
     help='New value for the "key-pairs" quota.')
2961
-@utils.arg('--security-groups',
2962
-    metavar='<security-groups>',
2963
-    type=int,
2964
-    default=None,
2965
-    help='New value for the "security-groups" quota.')
2966
-@utils.arg('--security-group-rules',
2967
-    metavar='<security-group-rules>',
2968
-    type=int,
2969
-    default=None,
2970
-    help='New value for the "security-group-rules" quota.')
2971 2924
 @utils.arg('--force',
2972 2925
     dest='force',
2973 2926
     action="store_true",

Loading…
Cancel
Save