Adding 'absolute-limits' and 'rate-limits'

Change-Id: Ie1dff62f3a3dd74e96c8cad7c079b7378d25ae46
This commit is contained in:
Brian Waldon 2011-12-06 12:11:50 -05:00
parent 11a4ecfe44
commit 959c44ff59
7 changed files with 196 additions and 46 deletions

View File

@ -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__:

View File

@ -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
View 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")

View File

@ -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)

View File

@ -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.",

View File

@ -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
View 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)