Adding 'absolute-limits' and 'rate-limits'
Change-Id: Ie1dff62f3a3dd74e96c8cad7c079b7378d25ae46
This commit is contained in:
parent
11a4ecfe44
commit
959c44ff59
@ -268,7 +268,11 @@ class Resource(object):
|
||||
|
||||
def _add_details(self, info):
|
||||
for (k, v) in info.iteritems():
|
||||
setattr(self, k, v)
|
||||
try:
|
||||
setattr(self, k, v)
|
||||
except AttributeError:
|
||||
# In this case we already defined the attribute on the class
|
||||
pass
|
||||
|
||||
def __getattr__(self, k):
|
||||
if k not in self.__dict__:
|
||||
|
@ -3,10 +3,11 @@ from novaclient.v1_1 import flavors
|
||||
from novaclient.v1_1 import floating_ips
|
||||
from novaclient.v1_1 import images
|
||||
from novaclient.v1_1 import keypairs
|
||||
from novaclient.v1_1 import limits
|
||||
from novaclient.v1_1 import quotas
|
||||
from novaclient.v1_1 import security_group_rules
|
||||
from novaclient.v1_1 import security_groups
|
||||
from novaclient.v1_1 import servers
|
||||
from novaclient.v1_1 import quotas
|
||||
from novaclient.v1_1 import volumes
|
||||
from novaclient.v1_1 import volume_snapshots
|
||||
from novaclient.v1_1 import zones
|
||||
@ -37,11 +38,12 @@ class Client(object):
|
||||
# know it's not being used as keyword argument
|
||||
password = api_key
|
||||
self.flavors = flavors.FlavorManager(self)
|
||||
self.floating_ips = floating_ips.FloatingIPManager(self)
|
||||
self.images = images.ImageManager(self)
|
||||
self.limits = limits.LimitsManager(self)
|
||||
self.servers = servers.ServerManager(self)
|
||||
|
||||
# extensions
|
||||
self.floating_ips = floating_ips.FloatingIPManager(self)
|
||||
self.volumes = volumes.VolumeManager(self)
|
||||
self.volume_snapshots = volume_snapshots.SnapshotManager(self)
|
||||
self.keypairs = keypairs.KeypairManager(self)
|
||||
|
79
novaclient/v1_1/limits.py
Normal file
79
novaclient/v1_1/limits.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
|
||||
from novaclient import base
|
||||
|
||||
|
||||
class Limits(base.Resource):
|
||||
"""A collection of RateLimit and AbsoluteLimit objects"""
|
||||
|
||||
def __repr__(self):
|
||||
return "<Limits>"
|
||||
|
||||
@property
|
||||
def absolute(self):
|
||||
for (name, value) in self._info['absolute'].items():
|
||||
yield AbsoluteLimit(name, value)
|
||||
|
||||
@property
|
||||
def rate(self):
|
||||
for group in self._info['rate']:
|
||||
uri = group['uri']
|
||||
regex = group['regex']
|
||||
for rate in group['limit']:
|
||||
yield RateLimit(rate['verb'], uri, regex, rate['value'],
|
||||
rate['remaining'], rate['unit'],
|
||||
rate['next-available'])
|
||||
|
||||
|
||||
class RateLimit(object):
|
||||
"""Data model that represents a flattened view of a single rate limit"""
|
||||
|
||||
def __init__(self, verb, uri, regex, value, remain,
|
||||
unit, next_available):
|
||||
self.verb = verb
|
||||
self.uri = uri
|
||||
self.regex = regex
|
||||
self.value = value
|
||||
self.remain = remain
|
||||
self.unit = unit
|
||||
self.next_available = next_available
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.uri == other.uri \
|
||||
and self.regex == other.regex \
|
||||
and self.value == other.value \
|
||||
and self.verb == other.verb \
|
||||
and self.remain == other.remain \
|
||||
and self.unit == other.unit \
|
||||
and self.next_available == other.next_available
|
||||
|
||||
def __repr__(self):
|
||||
return "<RateLimit: method=%s uri=%s>" % (self.method, self.uri)
|
||||
|
||||
|
||||
class AbsoluteLimit(object):
|
||||
"""Data model that represents a single absolute limit"""
|
||||
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.value == other.value and self.name == other.name
|
||||
|
||||
def __repr__(self):
|
||||
return "<AbsoluteLimit: name=%s>" % (self.name)
|
||||
|
||||
|
||||
class LimitsManager(base.Manager):
|
||||
"""Manager object used to interact with limits resource"""
|
||||
|
||||
resource_class = Limits
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
Get a specific extension.
|
||||
|
||||
:rtype: :class:`Limits`
|
||||
"""
|
||||
return self._get("/limits", "limits")
|
@ -1207,3 +1207,17 @@ def do_keypair_list(cs, args):
|
||||
keypairs = cs.keypairs.list()
|
||||
columns = ['Name', 'Fingerprint']
|
||||
utils.print_list(keypairs, columns)
|
||||
|
||||
|
||||
def do_absolute_limits(cs, args):
|
||||
"""Print a list of absolute limits for a user"""
|
||||
limits = cs.limits.get().absolute
|
||||
columns = ['Name', 'Value']
|
||||
utils.print_list(limits, 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)
|
||||
|
2
setup.py
2
setup.py
@ -28,7 +28,7 @@ def read_file(file_name):
|
||||
|
||||
setuptools.setup(
|
||||
name="python-novaclient",
|
||||
version="2.6.8",
|
||||
version="2.6.9",
|
||||
author="Rackspace, based on work by Jacob Kaplan-Moss",
|
||||
author_email="github@racklabs.com",
|
||||
description="Client library for OpenStack Nova API.",
|
||||
|
@ -55,56 +55,55 @@ class FakeHTTPClient(base_client.HTTPClient):
|
||||
return (200, {"limits": {
|
||||
"rate": [
|
||||
{
|
||||
"verb": "POST",
|
||||
"URI": "*",
|
||||
"uri": "*",
|
||||
"regex": ".*",
|
||||
"value": 10,
|
||||
"remaining": 2,
|
||||
"unit": "MINUTE",
|
||||
"resetTime": 1244425439
|
||||
"limit": [
|
||||
{
|
||||
"value": 10,
|
||||
"verb": "POST",
|
||||
"remaining": 2,
|
||||
"unit": "MINUTE",
|
||||
"next-available": "2011-12-15T22:42:45Z"
|
||||
},
|
||||
{
|
||||
"value": 10,
|
||||
"verb": "PUT",
|
||||
"remaining": 2,
|
||||
"unit": "MINUTE",
|
||||
"next-available": "2011-12-15T22:42:45Z"
|
||||
},
|
||||
{
|
||||
"value": 100,
|
||||
"verb": "DELETE",
|
||||
"remaining": 100,
|
||||
"unit": "MINUTE",
|
||||
"next-available": "2011-12-15T22:42:45Z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"verb": "POST",
|
||||
"URI": "*/servers",
|
||||
"uri": "*/servers",
|
||||
"regex": "^/servers",
|
||||
"value": 50,
|
||||
"remaining": 49,
|
||||
"unit": "DAY", "resetTime": 1244511839
|
||||
},
|
||||
{
|
||||
"verb": "PUT",
|
||||
"URI": "*",
|
||||
"regex": ".*",
|
||||
"value": 10,
|
||||
"remaining": 2,
|
||||
"unit": "MINUTE",
|
||||
"resetTime": 1244425439
|
||||
},
|
||||
{
|
||||
"verb": "GET",
|
||||
"URI": "*changes-since*",
|
||||
"regex": "changes-since",
|
||||
"value": 3,
|
||||
"remaining": 3,
|
||||
"unit": "MINUTE",
|
||||
"resetTime": 1244425439
|
||||
},
|
||||
{
|
||||
"verb": "DELETE",
|
||||
"URI": "*",
|
||||
"regex": ".*",
|
||||
"value": 100,
|
||||
"remaining": 100,
|
||||
"unit": "MINUTE",
|
||||
"resetTime": 1244425439
|
||||
"limit": [
|
||||
{
|
||||
"verb": "POST",
|
||||
"value": 25,
|
||||
"remaining": 24,
|
||||
"unit": "DAY",
|
||||
"next-available": "2011-12-15T22:42:45Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"absolute": {
|
||||
"maxTotalRAMSize": 51200,
|
||||
"maxIPGroups": 50,
|
||||
"maxIPGroupMembers": 25
|
||||
}
|
||||
}})
|
||||
"maxServerMeta": 5,
|
||||
"maxImageMeta": 5,
|
||||
"maxPersonality": 5,
|
||||
"maxPersonalitySize": 10240
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
#
|
||||
# Servers
|
||||
|
52
tests/v1_1/test_limits.py
Normal file
52
tests/v1_1/test_limits.py
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
from novaclient.v1_1 import limits
|
||||
from tests.v1_1 import fakes
|
||||
from tests import utils
|
||||
|
||||
|
||||
cs = fakes.FakeClient()
|
||||
|
||||
|
||||
class LimitsTest(utils.TestCase):
|
||||
|
||||
def test_get_limits(self):
|
||||
obj = cs.limits.get()
|
||||
cs.assert_called('GET', '/limits')
|
||||
self.assertTrue(isinstance(obj, limits.Limits))
|
||||
|
||||
def test_absolute_limits(self):
|
||||
obj = 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_rate_limits(self):
|
||||
obj = 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)
|
Loading…
Reference in New Issue
Block a user