Merge "Provide one resource for Compute v2 Limits"

This commit is contained in:
Jenkins
2015-02-20 17:00:48 +00:00
committed by Gerrit Code Review
8 changed files with 272 additions and 262 deletions

View File

@@ -14,8 +14,7 @@ from openstack.compute.v2 import extension
from openstack.compute.v2 import flavor from openstack.compute.v2 import flavor
from openstack.compute.v2 import image from openstack.compute.v2 import image
from openstack.compute.v2 import keypair from openstack.compute.v2 import keypair
from openstack.compute.v2 import limits_absolute from openstack.compute.v2 import limits
from openstack.compute.v2 import limits_rate
from openstack.compute.v2 import server from openstack.compute.v2 import server
from openstack.compute.v2 import server_interface from openstack.compute.v2 import server_interface
from openstack.compute.v2 import server_ip from openstack.compute.v2 import server_ip
@@ -86,17 +85,15 @@ class Proxy(object):
def update_keypair(self, **data): def update_keypair(self, **data):
return keypair.Keypair(data).update(self.session) return keypair.Keypair(data).update(self.session)
def find_limits_absolute(self, name_or_id): def limits(self):
return limits_absolute.LimitsAbsolute.find(self.session, name_or_id) """Retrieve limits that are applied to the project's account
def list_limits_absolute(self): :returns: A Limits object, including both
return limits_absolute.LimitsAbsolute.list(self.session) :class:`~openstack.compute.v2.limits.AbsoluteLimits` and
:class:`~openstack.compute.v2.limits.RateLimits`
def find_limits_rate(self, name_or_id): :rtype: :class:`~openstack.compute.v2.limits.Limits`
return limits_rate.LimitsRate.find(self.session, name_or_id) """
return limits.Limits().get(self.session)
def list_limits_rate(self):
return limits_rate.LimitsRate.list(self.session)
def create_server(self, **data): def create_server(self, **data):
return server.Server(data).create(self.session) return server.Server(data).create(self.session)

View File

@@ -0,0 +1,104 @@
# 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 openstack.compute import compute_service
from openstack import resource
class AbsoluteLimits(resource.Resource):
#: The maximum amount of key-value pairs to be set as image metadata.
image_meta = resource.prop("maxImageMeta")
#: The maximum number of personality contents that can be supplied.
personality = resource.prop("maxPersonality")
#: The maximum size, in bytes, of a personality.
personality_size = resource.prop("maxPersonalitySize")
#: The maximum amount of security group rules allowed.
security_group_rules = resource.prop("maxSecurityGroupRules")
#: The maximum amount of security groups allowed.
security_groups = resource.prop("maxSecurityGroups")
#: The amount of security groups currently in use.
security_groups_used = resource.prop("totalSecurityGroupsUsed")
#: The maximum amount of key-value pairs to be set as sever metadata.
server_meta = resource.prop("maxServerMeta")
#: The maximum amount of cores.
total_cores = resource.prop("maxTotalCores")
#: The amount of cores currently in use.
total_cores_used = resource.prop("totalCoresUsed")
#: The maximum amount of floating IPs.
floating_ips = resource.prop("maxTotalFloatingIps")
#: The amount of floating IPs currently in use.
floating_ips_used = resource.prop("totalFloatingIpsUsed")
#: The maximum amount of instances.
instances = resource.prop("maxTotalInstances")
#: The amount of instances currently in use.
instances_used = resource.prop("totalInstancesUsed")
#: The maximum amount of keypairs.
keypairs = resource.prop("maxTotalKeypairs")
#: The maximum RAM size in megabytes.
total_ram = resource.prop("maxTotalRAMSize")
#: The RAM size in megabytes currently in use.
total_ram_used = resource.prop("totalRAMUsed")
#: The maximum amount of server groups.
server_groups = resource.prop("maxServerGroups")
#: The amount of server groups currently in use.
server_groups_used = resource.prop("totalServerGroupsUsed")
#: The maximum number of members in a server group.
server_group_members = resource.prop("maxServerGroupMembers")
class RateLimits(resource.Resource):
#: A list of the specific limits that apply to the ``regex`` and ``uri``.
limits = resource.prop("limit", type=list)
#: A regex representing which routes this rate limit applies to.
regex = resource.prop("regex")
#: A URI representing which routes this rate limit applies to.
uri = resource.prop("uri")
class Limits(resource.Resource):
base_path = "/limits"
resource_key = "limits"
service = compute_service.ComputeService()
allow_retrieve = True
absolute = resource.prop("absolute", type=AbsoluteLimits)
rate = resource.prop("rate", type=list)
def get(self, session, include_headers=False):
"""Get the Limits resource.
:param session: The session to use for making this request.
:type session: :class:`~openstack.session.Session`
:returns: A Limits instance
:rtype: :class:`~openstack.compute.v2.limits.Limits`
"""
body = self.get_data_by_id(session, self.id, path_args=self,
include_headers=include_headers)
# Split the rates away from absolute limits. We can create
# the `absolute` property and AbsoluteLimits resource directly
# from the body. We have to iterate through the list inside `rate`
# in order to create the RateLimits instances for the `rate` property.
rate_body = body.pop("rate")
self._attrs.update(body)
rates = []
for rate in rate_body:
rates.append(RateLimits(rate))
self._attrs.update({"rate": rates})
self._loaded = True
return self

View File

@@ -1,38 +0,0 @@
# 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.
import six
from openstack.compute import compute_service
from openstack import resource
class LimitsAbsolute(resource.Resource):
resource_key = 'limits_absolute'
resources_key = 'limits_absolutes'
base_path = '/limits'
service = compute_service.ComputeService()
# capabilities
allow_list = True
# Properties
name = resource.prop('name')
value = resource.prop('value')
@classmethod
def list(cls, session, path_args=None, **params):
url = cls.base_path
resp = session.get(url, service=cls.service, params=params).body
resp = resp['limits']['absolute']
return [cls.existing(name=key, value=value)
for key, value in six.iteritems(resp)]

View File

@@ -1,36 +0,0 @@
# 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 openstack.compute import compute_service
from openstack import resource
class LimitsRate(resource.Resource):
resource_key = 'limits_rate'
resources_key = 'limits_rates'
base_path = '/limits'
service = compute_service.ComputeService()
# capabilities
allow_list = True
# Properties
limit = resource.prop('limit')
regex = resource.prop('regex')
uri = resource.prop('uri')
@classmethod
def list(cls, session, path_args=None, **params):
url = cls.base_path
resp = session.get(url, service=cls.service, params=params).body
resp = resp['limits']['rate']
return [cls.existing(**data) for data in resp]

View File

@@ -0,0 +1,155 @@
# 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.
import mock
import testtools
from openstack.compute.v2 import limits
ABSOLUTE_LIMITS = {
"maxImageMeta": 128,
"maxPersonality": 5,
"maxPersonalitySize": 10240,
"maxSecurityGroupRules": 20,
"maxSecurityGroups": 10,
"maxServerMeta": 128,
"maxTotalCores": 20,
"maxTotalFloatingIps": 10,
"maxTotalInstances": 10,
"maxTotalKeypairs": 100,
"maxTotalRAMSize": 51200,
"maxServerGroups": 10,
"maxServerGroupMembers": 10,
"totalFloatingIpsUsed": 1,
"totalSecurityGroupsUsed": 2,
"totalRAMUsed": 4,
"totalInstancesUsed": 5,
"totalServerGroupsUsed": 6,
"totalCoresUsed": 7
}
RATE_LIMIT = {
"limit": [
{
"next-available": "2012-11-27T17:22:18Z",
"remaining": 120,
"unit": "MINUTE",
"value": 120,
"verb": "POST"
},
],
"regex": ".*",
"uri": "*"
}
LIMITS_BODY = {
"limits": {
"absolute": ABSOLUTE_LIMITS,
"rate": [RATE_LIMIT]
}
}
class TestAbsoluteLimits(testtools.TestCase):
def test_basic(self):
sot = limits.AbsoluteLimits()
self.assertIsNone(sot.resource_key)
self.assertIsNone(sot.resources_key)
self.assertEqual("", sot.base_path)
self.assertIsNone(sot.service)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_retrieve)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertFalse(sot.allow_list)
def test_make_it(self):
sot = limits.AbsoluteLimits(ABSOLUTE_LIMITS)
self.assertEqual(ABSOLUTE_LIMITS["maxImageMeta"], sot.image_meta)
self.assertEqual(ABSOLUTE_LIMITS["maxPersonality"], sot.personality)
self.assertEqual(ABSOLUTE_LIMITS["maxPersonalitySize"],
sot.personality_size)
self.assertEqual(ABSOLUTE_LIMITS["maxSecurityGroupRules"],
sot.security_group_rules)
self.assertEqual(ABSOLUTE_LIMITS["maxSecurityGroups"],
sot.security_groups)
self.assertEqual(ABSOLUTE_LIMITS["maxServerMeta"], sot.server_meta)
self.assertEqual(ABSOLUTE_LIMITS["maxTotalCores"], sot.total_cores)
self.assertEqual(ABSOLUTE_LIMITS["maxTotalFloatingIps"],
sot.floating_ips)
self.assertEqual(ABSOLUTE_LIMITS["maxTotalInstances"],
sot.instances)
self.assertEqual(ABSOLUTE_LIMITS["maxTotalKeypairs"],
sot.keypairs)
self.assertEqual(ABSOLUTE_LIMITS["maxTotalRAMSize"],
sot.total_ram)
self.assertEqual(ABSOLUTE_LIMITS["maxServerGroups"], sot.server_groups)
self.assertEqual(ABSOLUTE_LIMITS["maxServerGroupMembers"],
sot.server_group_members)
self.assertEqual(ABSOLUTE_LIMITS["totalFloatingIpsUsed"],
sot.floating_ips_used)
self.assertEqual(ABSOLUTE_LIMITS["totalSecurityGroupsUsed"],
sot.security_groups_used)
self.assertEqual(ABSOLUTE_LIMITS["totalRAMUsed"], sot.total_ram_used)
self.assertEqual(ABSOLUTE_LIMITS["totalInstancesUsed"],
sot.instances_used)
self.assertEqual(ABSOLUTE_LIMITS["totalServerGroupsUsed"],
sot.server_groups_used)
self.assertEqual(ABSOLUTE_LIMITS["totalCoresUsed"],
sot.total_cores_used)
class TestRateLimits(testtools.TestCase):
def test_basic(self):
sot = limits.RateLimits()
self.assertIsNone(sot.resource_key)
self.assertIsNone(sot.resources_key)
self.assertEqual("", sot.base_path)
self.assertIsNone(sot.service)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_retrieve)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertFalse(sot.allow_list)
def test_make_it(self):
sot = limits.RateLimits(RATE_LIMIT)
self.assertEqual(RATE_LIMIT["regex"], sot.regex)
self.assertEqual(RATE_LIMIT["uri"], sot.uri)
self.assertEqual(RATE_LIMIT["limit"], sot.limits)
class TestLimits(testtools.TestCase):
def test_basic(self):
sot = limits.Limits()
self.assertEqual("limits", sot.resource_key)
self.assertEqual("/limits", sot.base_path)
self.assertEqual("compute", sot.service.service_type)
self.assertTrue(sot.allow_retrieve)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertFalse(sot.allow_list)
@mock.patch("openstack.resource.Resource.get_data_by_id")
def test_get(self, mock_get):
# Only return values under the limits key since that's our
# resource_key, which would be filtered out in get_data_by_id.
mock_get.return_value = LIMITS_BODY["limits"]
sot = limits.Limits().get("fake session")
self.assertEqual(sot.absolute, limits.AbsoluteLimits(ABSOLUTE_LIMITS))
self.assertEqual(sot.rate, [limits.RateLimits(RATE_LIMIT)])

View File

@@ -1,79 +0,0 @@
# 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.
import mock
import six
import testtools
from openstack.compute.v2 import limits_absolute
IDENTIFIER = 'IDENTIFIER'
EXAMPLE = {
'name': 'maxImageMeta',
'value': '2',
}
FAKE_RESPONSES = {
"limits": {
"absolute": {
"maxImageMeta": 128,
"maxPersonality": 5,
"maxPersonalitySize": 10240,
"maxSecurityGroupRules": 20,
"maxSecurityGroups": 10,
"maxServerMeta": 128,
"maxTotalCores": 20,
"maxTotalFloatingIps": 10,
"maxTotalInstances": 10,
"maxTotalKeypairs": 100,
"maxTotalRAMSize": 51200,
}
}
}
class TestLimitsAbsolute(testtools.TestCase):
def test_basic(self):
sot = limits_absolute.LimitsAbsolute()
self.assertEqual('limits_absolute', sot.resource_key)
self.assertEqual('limits_absolutes', sot.resources_key)
self.assertEqual('/limits', sot.base_path)
self.assertEqual('compute', sot.service.service_type)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_retrieve)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_make_it(self):
sot = limits_absolute.LimitsAbsolute(EXAMPLE)
self.assertEqual(EXAMPLE['name'], sot.name)
self.assertEqual(EXAMPLE['value'], sot.value)
def test_list(self):
resp = mock.Mock()
resp.body = FAKE_RESPONSES
sess = mock.Mock()
sess.get = mock.MagicMock()
sess.get.return_value = resp
sot = limits_absolute.LimitsAbsolute()
resp = sot.list(sess)
url = '/limits'
sess.get.assert_called_with(url, service=sot.service, params={})
absolute = FAKE_RESPONSES['limits']['absolute']
cnt = 0
for key, value in six.iteritems(absolute):
self.assertEqual(key, resp[cnt].name)
self.assertEqual(value, resp[cnt].value)
cnt = cnt + 1

View File

@@ -1,80 +0,0 @@
# 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.
import mock
import testtools
from openstack.compute.v2 import limits_rate
IDENTIFIER = 'IDENTIFIER'
EXAMPLE = {
'limit': '1',
'regex': '2',
'uri': '3',
}
FAKE_RESPONSES = {
"limits": {
"rate": [
{
"limit": "1",
"regex": ".*",
"uri": "*"
},
{
"limit": "2",
"regex": "^/servers",
"uri": "*/servers"
},
]
}
}
class TestLimitsRate(testtools.TestCase):
def test_basic(self):
sot = limits_rate.LimitsRate()
self.assertEqual('limits_rate', sot.resource_key)
self.assertEqual('limits_rates', sot.resources_key)
self.assertEqual('/limits', sot.base_path)
self.assertEqual('compute', sot.service.service_type)
self.assertFalse(sot.allow_create)
self.assertFalse(sot.allow_retrieve)
self.assertFalse(sot.allow_update)
self.assertFalse(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_make_it(self):
sot = limits_rate.LimitsRate(EXAMPLE)
self.assertEqual(EXAMPLE['limit'], sot.limit)
self.assertEqual(EXAMPLE['regex'], sot.regex)
self.assertEqual(EXAMPLE['uri'], sot.uri)
def test_list(self):
resp = mock.Mock()
resp.body = FAKE_RESPONSES
sess = mock.Mock()
sess.get = mock.MagicMock()
sess.get.return_value = resp
sot = limits_rate.LimitsRate()
resp = sot.list(sess)
url = '/limits'
sess.get.assert_called_with(url, service=sot.service, params={})
rate = FAKE_RESPONSES['limits']['rate']
cnt = 0
for value in rate:
self.assertEqual(value['limit'], resp[cnt].limit)
self.assertEqual(value['regex'], resp[cnt].regex)
self.assertEqual(value['uri'], resp[cnt].uri)
cnt = cnt + 1

View File

@@ -99,23 +99,10 @@ class TestComputeProxy(test_proxy_base.TestProxyBase):
self.verify_update('openstack.compute.v2.keypair.Keypair.update', self.verify_update('openstack.compute.v2.keypair.Keypair.update',
self.proxy.update_keypair) self.proxy.update_keypair)
def test_limits_absolute_find(self): def test_limits(self):
self.verify_find( self.verify_get(
'openstack.compute.v2.limits_absolute.LimitsAbsolute.find', 'openstack.compute.v2.limits.Limits.get',
self.proxy.find_limits_absolute) self.proxy.limits)
def test_limits_absolute_list(self):
self.verify_list(
'openstack.compute.v2.limits_absolute.LimitsAbsolute.list',
self.proxy.list_limits_absolute)
def test_limits_rate_find(self):
self.verify_find('openstack.compute.v2.limits_rate.LimitsRate.find',
self.proxy.find_limits_rate)
def test_limits_rate_list(self):
self.verify_list('openstack.compute.v2.limits_rate.LimitsRate.list',
self.proxy.list_limits_rate)
def test_server_interface_create(self): def test_server_interface_create(self):
self.verify_create( self.verify_create(