Add limits to V3 and improve limits formatting in shell
Adds support for the limits API to the v3 client. Also improve the formatting of absolute-limits from +-------------------------+-------+ | Name | Value | +-------------------------+-------+ | maxServerMeta | 128 | | maxPersonality | 5 | | maxImageMeta | 128 | | maxPersonalitySize | 10240 | | maxTotalRAMSize | 51200 | | maxSecurityGroupRules | 20 | | maxTotalKeypairs | 100 | | totalRAMUsed | 512 | | maxSecurityGroups | 10 | | totalFloatingIpsUsed | 0 | | totalInstancesUsed | 1 | | totalSecurityGroupsUsed | 1 | | maxTotalFloatingIps | 10 | | maxTotalInstances | 2 | | totalCoresUsed | 1 | | maxTotalCores | 20 | +-------------------------+-------+ to +--------------------+------+-------+ | Name | Used | Max | +--------------------+------+-------+ | Cores | 1 | 20 | | FloatingIps | 0 | 10 | | ImageMeta | - | 128 | | Instances | 1 | 2 | | Keypairs | - | 100 | | Personality | - | 5 | | PersonalitySize | - | 10240 | | RAM | 512 | 51200 | | SecurityGroupRules | - | 20 | | SecurityGroups | 1 | 10 | | ServerMeta | - | 128 | +--------------------+------+-------+ Change-Id: I93a456b402aeba8e39480567edb090cbb1898d16
This commit is contained in:
parent
4dbf1323cc
commit
ae8eadc451
|
@ -0,0 +1,88 @@
|
|||
#
|
||||
# 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.fixture_data import client
|
||||
from novaclient.tests.fixture_data import limits as data
|
||||
from novaclient.tests import utils
|
||||
from novaclient.v3 import limits
|
||||
|
||||
|
||||
class LimitsTest(utils.FixturedTestCase):
|
||||
|
||||
client_fixture_class = client.V3
|
||||
data_fixture_class = data.Fixture
|
||||
|
||||
def test_get_limits(self):
|
||||
obj = self.cs.limits.get()
|
||||
self.assert_called('GET', '/limits')
|
||||
self.assertIsInstance(obj, limits.Limits)
|
||||
|
||||
def test_get_limits_for_a_tenant(self):
|
||||
obj = self.cs.limits.get(tenant_id=1234)
|
||||
self.assert_called('GET', '/limits?tenant_id=1234')
|
||||
self.assertIsInstance(obj, limits.Limits)
|
||||
|
||||
def test_absolute_limits(self):
|
||||
obj = self.cs.limits.get()
|
||||
|
||||
expected = (
|
||||
limits.AbsoluteLimit("maxTotalRAMSize", 51200),
|
||||
limits.AbsoluteLimit("maxServerMeta", 5),
|
||||
limits.AbsoluteLimit("maxImageMeta", 5),
|
||||
limits.AbsoluteLimit("maxPersonality", 5),
|
||||
limits.AbsoluteLimit("maxPersonalitySize", 10240),
|
||||
)
|
||||
|
||||
abs_limits = list(obj.absolute)
|
||||
self.assertEqual(len(abs_limits), len(expected))
|
||||
|
||||
for limit in abs_limits:
|
||||
self.assertTrue(limit in expected)
|
||||
|
||||
def test_absolute_limits_reserved(self):
|
||||
obj = self.cs.limits.get(reserved=True)
|
||||
|
||||
expected = (
|
||||
limits.AbsoluteLimit("maxTotalRAMSize", 51200),
|
||||
limits.AbsoluteLimit("maxServerMeta", 5),
|
||||
limits.AbsoluteLimit("maxImageMeta", 5),
|
||||
limits.AbsoluteLimit("maxPersonality", 5),
|
||||
limits.AbsoluteLimit("maxPersonalitySize", 10240),
|
||||
)
|
||||
|
||||
self.assert_called('GET', '/limits?reserved=1')
|
||||
abs_limits = list(obj.absolute)
|
||||
self.assertEqual(len(abs_limits), len(expected))
|
||||
|
||||
for limit in abs_limits:
|
||||
self.assertTrue(limit in expected)
|
||||
|
||||
def test_rate_limits(self):
|
||||
obj = self.cs.limits.get()
|
||||
|
||||
expected = (
|
||||
limits.RateLimit('POST', '*', '.*', 10, 2, 'MINUTE',
|
||||
'2011-12-15T22:42:45Z'),
|
||||
limits.RateLimit('PUT', '*', '.*', 10, 2, 'MINUTE',
|
||||
'2011-12-15T22:42:45Z'),
|
||||
limits.RateLimit('DELETE', '*', '.*', 100, 100, 'MINUTE',
|
||||
'2011-12-15T22:42:45Z'),
|
||||
limits.RateLimit('POST', '*/servers', '^/servers', 25, 24, 'DAY',
|
||||
'2011-12-15T22:42:45Z'),
|
||||
)
|
||||
|
||||
rate_limits = list(obj.rate)
|
||||
self.assertEqual(len(rate_limits), len(expected))
|
||||
|
||||
for limit in rate_limits:
|
||||
self.assertTrue(limit in expected)
|
|
@ -2616,8 +2616,65 @@ def _find_keypair(cs, keypair):
|
|||
def do_absolute_limits(cs, args):
|
||||
"""Print a list of absolute limits for a user"""
|
||||
limits = cs.limits.get(args.reserved, args.tenant).absolute
|
||||
columns = ['Name', 'Value']
|
||||
utils.print_list(limits, columns)
|
||||
|
||||
class Limit(object):
|
||||
def __init__(self, name, used, max, other):
|
||||
self.name = name
|
||||
self.used = used
|
||||
self.max = max
|
||||
self.other = other
|
||||
|
||||
limit_map = {
|
||||
'maxServerMeta': {'name': 'Server Meta', 'type': 'max'},
|
||||
'maxPersonality': {'name': 'Personality', 'type': 'max'},
|
||||
'maxPersonalitySize': {'name': 'Personality Size', 'type': 'max'},
|
||||
'maxImageMeta': {'name': 'ImageMeta', 'type': 'max'},
|
||||
'maxTotalKeypairs': {'name': 'Keypairs', 'type': 'max'},
|
||||
'totalCoresUsed': {'name': 'Cores', 'type': 'used'},
|
||||
'maxTotalCores': {'name': 'Cores', 'type': 'max'},
|
||||
'totalRAMUsed': {'name': 'RAM', 'type': 'used'},
|
||||
'maxTotalRAMSize': {'name': 'RAM', 'type': 'max'},
|
||||
'totalInstancesUsed': {'name': 'Instances', 'type': 'used'},
|
||||
'maxTotalInstances': {'name': 'Instances', 'type': 'max'},
|
||||
'totalFloatingIpsUsed': {'name': 'FloatingIps', 'type': 'used'},
|
||||
'maxTotalFloatingIps': {'name': 'FloatingIps', 'type': 'max'},
|
||||
'totalSecurityGroupsUsed': {'name': 'SecurityGroups', 'type': 'used'},
|
||||
'maxSecurityGroups': {'name': 'SecurityGroups', 'type': 'max'},
|
||||
'maxSecurityGroupRules': {'name': 'SecurityGroupRules', 'type': 'max'},
|
||||
'maxServerGroups': {'name': 'ServerGroups', 'type': 'max'},
|
||||
'totalServerGroupsUsed': {'name': 'ServerGroups', 'type': 'used'},
|
||||
'maxServerGroupMembers': {'name': 'ServerGroupMembers', 'type': 'max'},
|
||||
}
|
||||
|
||||
max = {}
|
||||
used = {}
|
||||
other = {}
|
||||
limit_names = []
|
||||
columns = ['Name', 'Used', 'Max']
|
||||
for l in limits:
|
||||
map = limit_map.get(l.name, {'name': l.name, 'type': 'other'})
|
||||
name = map['name']
|
||||
if map['type'] == 'max':
|
||||
max[name] = l.value
|
||||
elif map['type'] == 'used':
|
||||
used[name] = l.value
|
||||
else:
|
||||
other[name] = l.value
|
||||
columns.append('Other')
|
||||
if name not in limit_names:
|
||||
limit_names.append(name)
|
||||
|
||||
limit_names.sort()
|
||||
|
||||
limit_list = []
|
||||
for name in limit_names:
|
||||
l = Limit(name,
|
||||
used.get(name, "-"),
|
||||
max.get(name, "-"),
|
||||
other.get(name, "-"))
|
||||
limit_list.append(l)
|
||||
|
||||
utils.print_list(limit_list, columns)
|
||||
|
||||
|
||||
def do_rate_limits(cs, args):
|
||||
|
|
|
@ -24,6 +24,7 @@ from novaclient.v3 import hosts
|
|||
from novaclient.v3 import hypervisors
|
||||
from novaclient.v3 import images
|
||||
from novaclient.v3 import keypairs
|
||||
from novaclient.v3 import limits
|
||||
from novaclient.v3 import list_extensions
|
||||
from novaclient.v3 import quotas
|
||||
from novaclient.v3 import servers
|
||||
|
@ -110,6 +111,7 @@ class Client(object):
|
|||
self.hypervisors = hypervisors.HypervisorManager(self)
|
||||
self.images = images.ImageManager(self)
|
||||
self.keypairs = keypairs.KeypairManager(self)
|
||||
self.limits = limits.LimitsManager(self)
|
||||
self.quotas = quotas.QuotaSetManager(self)
|
||||
self.servers = servers.ServerManager(self)
|
||||
self.services = services.ServiceManager(self)
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
# Copyright 2011 OpenStack Foundation
|
||||
#
|
||||
# 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 six.moves.urllib import parse
|
||||
|
||||
from novaclient.v1_1 import limits
|
||||
|
||||
|
||||
class Limits(limits.Limits):
|
||||
pass
|
||||
|
||||
|
||||
class RateLimit(limits.RateLimit):
|
||||
pass
|
||||
|
||||
|
||||
class AbsoluteLimit(limits.AbsoluteLimit):
|
||||
pass
|
||||
|
||||
|
||||
class LimitsManager(limits.LimitsManager):
|
||||
"""Manager object used to interact with limits resource."""
|
||||
|
||||
resource_class = Limits
|
||||
|
||||
def get(self, reserved=False, tenant_id=None):
|
||||
"""
|
||||
Get a specific extension.
|
||||
|
||||
:rtype: :class:`Limits`
|
||||
"""
|
||||
opts = {}
|
||||
if reserved:
|
||||
opts['reserved'] = 1
|
||||
if tenant_id:
|
||||
opts['tenant_id'] = tenant_id
|
||||
query_string = "?%s" % parse.urlencode(opts) if opts else ""
|
||||
|
||||
return self._get("/limits%s" % query_string, "limits")
|
|
@ -3066,3 +3066,85 @@ def do_availability_zone_list(cs, _args):
|
|||
_translate_availability_zone_keys(result)
|
||||
utils.print_list(result, ['Name', 'Status'],
|
||||
sortby_index=None)
|
||||
|
||||
|
||||
@utils.arg('--tenant',
|
||||
# nova db searches by project_id
|
||||
dest='tenant',
|
||||
metavar='<tenant>',
|
||||
nargs='?',
|
||||
help=_('Display information from single tenant (Admin only).'))
|
||||
@utils.arg('--reserved',
|
||||
dest='reserved',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help=_('Include reservations count.'))
|
||||
def do_absolute_limits(cs, args):
|
||||
"""Print a list of absolute limits for a user"""
|
||||
limits = cs.limits.get(args.reserved, args.tenant).absolute
|
||||
|
||||
class Limit(object):
|
||||
def __init__(self, name, used, max, other):
|
||||
self.name = name
|
||||
self.used = used
|
||||
self.max = max
|
||||
self.other = other
|
||||
|
||||
limit_map = {
|
||||
'maxServerMeta': {'name': 'Server Meta', 'type': 'max'},
|
||||
'maxPersonality': {'name': 'Personality', 'type': 'max'},
|
||||
'maxPersonalitySize': {'name': 'Personality Size', 'type': 'max'},
|
||||
'maxImageMeta': {'name': 'ImageMeta', 'type': 'max'},
|
||||
'maxTotalKeypairs': {'name': 'Keypairs', 'type': 'max'},
|
||||
'totalCoresUsed': {'name': 'Cores', 'type': 'used'},
|
||||
'maxTotalCores': {'name': 'Cores', 'type': 'max'},
|
||||
'totalRAMUsed': {'name': 'RAM', 'type': 'used'},
|
||||
'maxTotalRAMSize': {'name': 'RAM', 'type': 'max'},
|
||||
'totalInstancesUsed': {'name': 'Instances', 'type': 'used'},
|
||||
'maxTotalInstances': {'name': 'Instances', 'type': 'max'},
|
||||
'totalFloatingIpsUsed': {'name': 'FloatingIps', 'type': 'used'},
|
||||
'maxTotalFloatingIps': {'name': 'FloatingIps', 'type': 'max'},
|
||||
'totalSecurityGroupsUsed': {'name': 'SecurityGroups', 'type': 'used'},
|
||||
'maxSecurityGroups': {'name': 'SecurityGroups', 'type': 'max'},
|
||||
'maxSecurityGroupRules': {'name': 'SecurityGroupRules', 'type': 'max'},
|
||||
'maxServerGroups': {'name': 'ServerGroups', 'type': 'max'},
|
||||
'totalServerGroupsUsed': {'name': 'ServerGroups', 'type': 'used'},
|
||||
'maxServerGroupMembers': {'name': 'ServerGroupMembers', 'type': 'max'},
|
||||
}
|
||||
|
||||
max = {}
|
||||
used = {}
|
||||
other = {}
|
||||
limit_names = []
|
||||
columns = ['Name', 'Used', 'Max']
|
||||
for l in limits:
|
||||
map = limit_map.get(l.name, {'name': l.name, 'type': 'other'})
|
||||
name = map['name']
|
||||
if map['type'] == 'max':
|
||||
max[name] = l.value
|
||||
elif map['type'] == 'used':
|
||||
used[name] = l.value
|
||||
else:
|
||||
other[name] = l.value
|
||||
columns.append('Other')
|
||||
if name not in limit_names:
|
||||
limit_names.append(name)
|
||||
|
||||
limit_names.sort()
|
||||
|
||||
limit_list = []
|
||||
for name in limit_names:
|
||||
l = Limit(name,
|
||||
used.get(name, "-"),
|
||||
max.get(name, "-"),
|
||||
other.get(name, "-"))
|
||||
limit_list.append(l)
|
||||
|
||||
utils.print_list(limit_list, columns)
|
||||
|
||||
|
||||
def do_rate_limits(cs, args):
|
||||
"""Print a list of rate limits for a user"""
|
||||
limits = cs.limits.get().rate
|
||||
columns = ['Verb', 'URI', 'Value', 'Remain', 'Unit', 'Next_Available']
|
||||
utils.print_list(limits, columns)
|
||||
|
|
Loading…
Reference in New Issue