Fix limits v3 follow API v3 rules
* Add expected_errors decorator. * Remove 'absolute_limit' from response, that already return by extension quota_sets. And update api samples. Partially implements bp nova-v3-api Change-Id: Iea3ff494b8abed77fdc4b9e5e552784ed3733c34
This commit is contained in:
		@@ -1,18 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "limits": {
 | 
			
		||||
        "absolute": {
 | 
			
		||||
            "maxImageMeta": 128,
 | 
			
		||||
            "maxPersonality": 5,
 | 
			
		||||
            "maxPersonalitySize": 10240,
 | 
			
		||||
            "maxSecurityGroupRules": 20,
 | 
			
		||||
            "maxSecurityGroups": 10,
 | 
			
		||||
            "maxServerMeta": 128,
 | 
			
		||||
            "maxTotalCores": 20,
 | 
			
		||||
            "maxTotalFloatingIps": 10,
 | 
			
		||||
            "maxTotalInstances": 10,
 | 
			
		||||
            "maxTotalKeypairs": 100,
 | 
			
		||||
            "maxTotalRAMSize": 51200
 | 
			
		||||
        },
 | 
			
		||||
        "rate": [
 | 
			
		||||
            {
 | 
			
		||||
                "limit": [
 | 
			
		||||
 
 | 
			
		||||
@@ -13,17 +13,4 @@
 | 
			
		||||
      <limit next-available="2013-09-09T13:37:32Z" unit="MINUTE" verb="GET" remaining="3" value="3"/>
 | 
			
		||||
    </rate>
 | 
			
		||||
  </rates>
 | 
			
		||||
  <absolute>
 | 
			
		||||
    <limit name="maxServerMeta" value="128"/>
 | 
			
		||||
    <limit name="maxPersonality" value="5"/>
 | 
			
		||||
    <limit name="maxImageMeta" value="128"/>
 | 
			
		||||
    <limit name="maxPersonalitySize" value="10240"/>
 | 
			
		||||
    <limit name="maxSecurityGroupRules" value="20"/>
 | 
			
		||||
    <limit name="maxTotalKeypairs" value="100"/>
 | 
			
		||||
    <limit name="maxSecurityGroups" value="10"/>
 | 
			
		||||
    <limit name="maxTotalCores" value="20"/>
 | 
			
		||||
    <limit name="maxTotalFloatingIps" value="10"/>
 | 
			
		||||
    <limit name="maxTotalInstances" value="10"/>
 | 
			
		||||
    <limit name="maxTotalRAMSize" value="51200"/>
 | 
			
		||||
  </absolute>
 | 
			
		||||
</limits>
 | 
			
		||||
@@ -61,53 +61,21 @@ class LimitsTemplate(xmlutil.TemplateBuilder):
 | 
			
		||||
        limit.set('unit', 'unit')
 | 
			
		||||
        limit.set('next-available', 'next-available')
 | 
			
		||||
 | 
			
		||||
        absolute = xmlutil.SubTemplateElement(root, 'absolute',
 | 
			
		||||
                                              selector='absolute')
 | 
			
		||||
        limit = xmlutil.SubTemplateElement(absolute, 'limit',
 | 
			
		||||
                                           selector=xmlutil.get_items)
 | 
			
		||||
        limit.set('name', 0)
 | 
			
		||||
        limit.set('value', 1)
 | 
			
		||||
 | 
			
		||||
        return xmlutil.MasterTemplate(root, 1, nsmap=limits_nsmap)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LimitsController(wsgi.Controller):
 | 
			
		||||
    """Controller for accessing limits in the OpenStack API."""
 | 
			
		||||
 | 
			
		||||
    @extensions.expected_errors(())
 | 
			
		||||
    @wsgi.serializers(xml=LimitsTemplate)
 | 
			
		||||
    def index(self, req):
 | 
			
		||||
        """Return all global and rate limit information."""
 | 
			
		||||
        context = req.environ['nova.context']
 | 
			
		||||
        quotas = QUOTAS.get_project_quotas(context, context.project_id,
 | 
			
		||||
                                           usages=False)
 | 
			
		||||
        abs_limits = dict((k, v['limit']) for k, v in quotas.items())
 | 
			
		||||
        rate_limits = req.environ.get("nova.limits", [])
 | 
			
		||||
 | 
			
		||||
        builder = self._get_view_builder(req)
 | 
			
		||||
        return builder.build(rate_limits, abs_limits)
 | 
			
		||||
 | 
			
		||||
    def create(self, req, body):
 | 
			
		||||
        """Create a new limit."""
 | 
			
		||||
        raise webob.exc.HTTPNotImplemented()
 | 
			
		||||
 | 
			
		||||
    def delete(self, req, id):
 | 
			
		||||
        """Delete the limit."""
 | 
			
		||||
        raise webob.exc.HTTPNotImplemented()
 | 
			
		||||
 | 
			
		||||
    def detail(self, req):
 | 
			
		||||
        """Return limit details."""
 | 
			
		||||
        raise webob.exc.HTTPNotImplemented()
 | 
			
		||||
 | 
			
		||||
    def show(self, req, id):
 | 
			
		||||
        """Show limit information."""
 | 
			
		||||
        raise webob.exc.HTTPNotImplemented()
 | 
			
		||||
 | 
			
		||||
    def update(self, req, id, body):
 | 
			
		||||
        """Update existing limit."""
 | 
			
		||||
        raise webob.exc.HTTPNotImplemented()
 | 
			
		||||
 | 
			
		||||
    def _get_view_builder(self, req):
 | 
			
		||||
        return limits_views.ViewBuilder()
 | 
			
		||||
        builder = limits_views.ViewBuilderV3()
 | 
			
		||||
        return builder.build(rate_limits)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Limit(object):
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								nova/api/openstack/compute/schemas/v3/limits.rng
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								nova/api/openstack/compute/schemas/v3/limits.rng
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
<element name="limits" ns="http://docs.openstack.org/common/api/v1.0"
 | 
			
		||||
  xmlns="http://relaxng.org/ns/structure/1.0">
 | 
			
		||||
  <element name="rates">
 | 
			
		||||
    <zeroOrMore>
 | 
			
		||||
      <element name="rate">
 | 
			
		||||
        <attribute name="uri"> <text/> </attribute>
 | 
			
		||||
        <attribute name="regex"> <text/> </attribute>
 | 
			
		||||
        <zeroOrMore>
 | 
			
		||||
          <element name="limit">
 | 
			
		||||
            <attribute name="value"> <text/> </attribute>
 | 
			
		||||
            <attribute name="verb"> <text/> </attribute>
 | 
			
		||||
            <attribute name="remaining"> <text/> </attribute>
 | 
			
		||||
            <attribute name="unit"> <text/> </attribute>
 | 
			
		||||
            <attribute name="next-available"> <text/> </attribute>
 | 
			
		||||
          </element>
 | 
			
		||||
        </zeroOrMore>
 | 
			
		||||
      </element>
 | 
			
		||||
    </zeroOrMore>
 | 
			
		||||
  </element>
 | 
			
		||||
</element>
 | 
			
		||||
@@ -98,3 +98,10 @@ class ViewBuilder(object):
 | 
			
		||||
            "unit": rate_limit["unit"],
 | 
			
		||||
            "next-available": timeutils.isotime(at=next_avail),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ViewBuilderV3(ViewBuilder):
 | 
			
		||||
 | 
			
		||||
    def build(self, rate_limits):
 | 
			
		||||
        rate_limits = self._build_rate_limits(rate_limits)
 | 
			
		||||
        return {"limits": {"rate": rate_limits}}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,6 @@ from nova.api.openstack import xmlutil
 | 
			
		||||
import nova.context
 | 
			
		||||
from nova.openstack.common import jsonutils
 | 
			
		||||
from nova import test
 | 
			
		||||
from nova.tests.api.openstack import fakes
 | 
			
		||||
from nova.tests import matchers
 | 
			
		||||
from nova import utils
 | 
			
		||||
 | 
			
		||||
@@ -58,14 +57,6 @@ class BaseLimitTestSuite(test.NoDBTestCase):
 | 
			
		||||
        super(BaseLimitTestSuite, self).setUp()
 | 
			
		||||
        self.time = 0.0
 | 
			
		||||
        self.stubs.Set(limits.Limit, "_get_time", self._get_time)
 | 
			
		||||
        self.absolute_limits = {}
 | 
			
		||||
 | 
			
		||||
        def stub_get_project_quotas(context, project_id, usages=True):
 | 
			
		||||
            return dict((k, dict(limit=v))
 | 
			
		||||
                        for k, v in self.absolute_limits.items())
 | 
			
		||||
 | 
			
		||||
        self.stubs.Set(nova.quota.QUOTAS, "get_project_quotas",
 | 
			
		||||
                       stub_get_project_quotas)
 | 
			
		||||
 | 
			
		||||
    def _get_time(self):
 | 
			
		||||
        """Return the "time" according to this test suite."""
 | 
			
		||||
@@ -111,8 +102,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
 | 
			
		||||
        body = self.controller.index(request)
 | 
			
		||||
        expected = {
 | 
			
		||||
            "limits": {
 | 
			
		||||
                "rate": [],
 | 
			
		||||
                "absolute": {},
 | 
			
		||||
                "rate": []
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        self.assertEqual(expected, body)
 | 
			
		||||
@@ -121,15 +111,6 @@ class LimitsControllerTest(BaseLimitTestSuite):
 | 
			
		||||
        # Test getting limit details in JSON.
 | 
			
		||||
        request = self._get_index_request()
 | 
			
		||||
        request = self._populate_limits(request)
 | 
			
		||||
        self.absolute_limits = {
 | 
			
		||||
            'ram': 512,
 | 
			
		||||
            'instances': 5,
 | 
			
		||||
            'cores': 21,
 | 
			
		||||
            'key_pairs': 10,
 | 
			
		||||
            'floating_ips': 10,
 | 
			
		||||
            'security_groups': 10,
 | 
			
		||||
            'security_group_rules': 20,
 | 
			
		||||
        }
 | 
			
		||||
        body = self.controller.index(request)
 | 
			
		||||
        expected = {
 | 
			
		||||
            "limits": {
 | 
			
		||||
@@ -168,16 +149,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
 | 
			
		||||
                        ],
 | 
			
		||||
                    },
 | 
			
		||||
 | 
			
		||||
                ],
 | 
			
		||||
                "absolute": {
 | 
			
		||||
                    "maxTotalRAMSize": 512,
 | 
			
		||||
                    "maxTotalInstances": 5,
 | 
			
		||||
                    "maxTotalCores": 21,
 | 
			
		||||
                    "maxTotalKeypairs": 10,
 | 
			
		||||
                    "maxTotalFloatingIps": 10,
 | 
			
		||||
                    "maxSecurityGroups": 10,
 | 
			
		||||
                    "maxSecurityGroupRules": 20,
 | 
			
		||||
                    },
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        self.assertEqual(expected, body)
 | 
			
		||||
@@ -226,90 +198,11 @@ class LimitsControllerTest(BaseLimitTestSuite):
 | 
			
		||||
                        ],
 | 
			
		||||
                    },
 | 
			
		||||
 | 
			
		||||
                ],
 | 
			
		||||
                "absolute": {},
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        self.assertEqual(expected, body)
 | 
			
		||||
 | 
			
		||||
    def _test_index_absolute_limits_json(self, expected):
 | 
			
		||||
        request = self._get_index_request()
 | 
			
		||||
        body = self.controller.index(request)
 | 
			
		||||
        self.assertEqual(expected, body['limits']['absolute'])
 | 
			
		||||
 | 
			
		||||
    def test_index_ignores_extra_absolute_limits_json(self):
 | 
			
		||||
        self.absolute_limits = {'unknown_limit': 9001}
 | 
			
		||||
        self._test_index_absolute_limits_json({})
 | 
			
		||||
 | 
			
		||||
    def test_index_absolute_ram_json(self):
 | 
			
		||||
        self.absolute_limits = {'ram': 1024}
 | 
			
		||||
        self._test_index_absolute_limits_json({'maxTotalRAMSize': 1024})
 | 
			
		||||
 | 
			
		||||
    def test_index_absolute_cores_json(self):
 | 
			
		||||
        self.absolute_limits = {'cores': 17}
 | 
			
		||||
        self._test_index_absolute_limits_json({'maxTotalCores': 17})
 | 
			
		||||
 | 
			
		||||
    def test_index_absolute_instances_json(self):
 | 
			
		||||
        self.absolute_limits = {'instances': 19}
 | 
			
		||||
        self._test_index_absolute_limits_json({'maxTotalInstances': 19})
 | 
			
		||||
 | 
			
		||||
    def test_index_absolute_metadata_json(self):
 | 
			
		||||
        # NOTE: both server metadata and image metadata are overloaded
 | 
			
		||||
        # into metadata_items
 | 
			
		||||
        self.absolute_limits = {'metadata_items': 23}
 | 
			
		||||
        expected = {
 | 
			
		||||
            'maxServerMeta': 23,
 | 
			
		||||
            'maxImageMeta': 23,
 | 
			
		||||
        }
 | 
			
		||||
        self._test_index_absolute_limits_json(expected)
 | 
			
		||||
 | 
			
		||||
    def test_index_absolute_injected_files(self):
 | 
			
		||||
        self.absolute_limits = {
 | 
			
		||||
            'injected_files': 17,
 | 
			
		||||
            'injected_file_content_bytes': 86753,
 | 
			
		||||
        }
 | 
			
		||||
        expected = {
 | 
			
		||||
            'maxPersonality': 17,
 | 
			
		||||
            'maxPersonalitySize': 86753,
 | 
			
		||||
        }
 | 
			
		||||
        self._test_index_absolute_limits_json(expected)
 | 
			
		||||
 | 
			
		||||
    def test_index_absolute_security_groups(self):
 | 
			
		||||
        self.absolute_limits = {
 | 
			
		||||
            'security_groups': 8,
 | 
			
		||||
            'security_group_rules': 16,
 | 
			
		||||
        }
 | 
			
		||||
        expected = {
 | 
			
		||||
            'maxSecurityGroups': 8,
 | 
			
		||||
            'maxSecurityGroupRules': 16,
 | 
			
		||||
        }
 | 
			
		||||
        self._test_index_absolute_limits_json(expected)
 | 
			
		||||
 | 
			
		||||
    def test_limit_create(self):
 | 
			
		||||
        req = fakes.HTTPRequestV3.blank('/limits')
 | 
			
		||||
        self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.create,
 | 
			
		||||
                          req, {})
 | 
			
		||||
 | 
			
		||||
    def test_limit_delete(self):
 | 
			
		||||
        req = fakes.HTTPRequestV3.blank('/limits')
 | 
			
		||||
        self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.delete,
 | 
			
		||||
                          req, 1)
 | 
			
		||||
 | 
			
		||||
    def test_limit_detail(self):
 | 
			
		||||
        req = fakes.HTTPRequestV3.blank('/limits')
 | 
			
		||||
        self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.detail,
 | 
			
		||||
                          req)
 | 
			
		||||
 | 
			
		||||
    def test_limit_show(self):
 | 
			
		||||
        req = fakes.HTTPRequestV3.blank('/limits')
 | 
			
		||||
        self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.show,
 | 
			
		||||
                          req, 1)
 | 
			
		||||
 | 
			
		||||
    def test_limit_update(self):
 | 
			
		||||
        req = fakes.HTTPRequestV3.blank('/limits')
 | 
			
		||||
        self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.update,
 | 
			
		||||
                          req, 1, {})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MockLimiter(limits.Limiter):
 | 
			
		||||
    pass
 | 
			
		||||
@@ -862,7 +755,7 @@ class WsgiLimiterProxyTest(BaseLimitTestSuite):
 | 
			
		||||
class LimitsViewBuilderTest(test.NoDBTestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(LimitsViewBuilderTest, self).setUp()
 | 
			
		||||
        self.view_builder = views.limits.ViewBuilder()
 | 
			
		||||
        self.view_builder = views.limits.ViewBuilderV3()
 | 
			
		||||
        self.rate_limits = [{"URI": "*",
 | 
			
		||||
                             "regex": ".*",
 | 
			
		||||
                             "value": 10,
 | 
			
		||||
@@ -877,9 +770,6 @@ class LimitsViewBuilderTest(test.NoDBTestCase):
 | 
			
		||||
                             "remaining": 10,
 | 
			
		||||
                             "unit": "DAY",
 | 
			
		||||
                             "resetTime": 1311272226}]
 | 
			
		||||
        self.absolute_limits = {"metadata_items": 1,
 | 
			
		||||
                                "injected_files": 5,
 | 
			
		||||
                                "injected_file_content_bytes": 5}
 | 
			
		||||
 | 
			
		||||
    def test_build_limits(self):
 | 
			
		||||
        expected_limits = {"limits": {
 | 
			
		||||
@@ -897,23 +787,17 @@ class LimitsViewBuilderTest(test.NoDBTestCase):
 | 
			
		||||
                               "verb": "POST",
 | 
			
		||||
                               "remaining": 10,
 | 
			
		||||
                               "unit": "DAY",
 | 
			
		||||
                               "next-available": "2011-07-21T18:17:06Z"}]}],
 | 
			
		||||
                "absolute": {"maxServerMeta": 1,
 | 
			
		||||
                             "maxImageMeta": 1,
 | 
			
		||||
                             "maxPersonality": 5,
 | 
			
		||||
                             "maxPersonalitySize": 5}}}
 | 
			
		||||
                               "next-available": "2011-07-21T18:17:06Z"}]}]}}
 | 
			
		||||
 | 
			
		||||
        output = self.view_builder.build(self.rate_limits,
 | 
			
		||||
                                         self.absolute_limits)
 | 
			
		||||
        output = self.view_builder.build(self.rate_limits)
 | 
			
		||||
        self.assertThat(output, matchers.DictMatches(expected_limits))
 | 
			
		||||
 | 
			
		||||
    def test_build_limits_empty_limits(self):
 | 
			
		||||
        expected_limits = {"limits": {"rate": [],
 | 
			
		||||
                           "absolute": {}}}
 | 
			
		||||
        expected_limits = {"limits": {"rate": []}}
 | 
			
		||||
 | 
			
		||||
        abs_limits = {}
 | 
			
		||||
        rate_limits = []
 | 
			
		||||
        output = self.view_builder.build(rate_limits, abs_limits)
 | 
			
		||||
        output = self.view_builder.build(rate_limits)
 | 
			
		||||
        self.assertThat(output, matchers.DictMatches(expected_limits))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -922,8 +806,7 @@ class LimitsXMLSerializationTest(test.NoDBTestCase):
 | 
			
		||||
        serializer = limits.LimitsTemplate()
 | 
			
		||||
 | 
			
		||||
        fixture = {"limits": {
 | 
			
		||||
                   "rate": [],
 | 
			
		||||
                   "absolute": {}}}
 | 
			
		||||
                   "rate": []}}
 | 
			
		||||
 | 
			
		||||
        output = serializer.serialize(fixture)
 | 
			
		||||
        has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
 | 
			
		||||
@@ -949,23 +832,11 @@ class LimitsXMLSerializationTest(test.NoDBTestCase):
 | 
			
		||||
                              "verb": "POST",
 | 
			
		||||
                              "remaining": 10,
 | 
			
		||||
                              "unit": "DAY",
 | 
			
		||||
                              "next-available": "2011-12-15T22:42:45Z"}]}],
 | 
			
		||||
                    "absolute": {"maxServerMeta": 1,
 | 
			
		||||
                                 "maxImageMeta": 1,
 | 
			
		||||
                                 "maxPersonality": 5,
 | 
			
		||||
                                 "maxPersonalitySize": 10240}}}
 | 
			
		||||
                              "next-available": "2011-12-15T22:42:45Z"}]}]}}
 | 
			
		||||
 | 
			
		||||
        output = serializer.serialize(fixture)
 | 
			
		||||
        root = etree.XML(output)
 | 
			
		||||
        xmlutil.validate_schema(root, 'limits')
 | 
			
		||||
 | 
			
		||||
        #verify absolute limits
 | 
			
		||||
        absolutes = root.xpath('ns:absolute/ns:limit', namespaces=NS)
 | 
			
		||||
        self.assertEqual(len(absolutes), 4)
 | 
			
		||||
        for limit in absolutes:
 | 
			
		||||
            name = limit.get('name')
 | 
			
		||||
            value = limit.get('value')
 | 
			
		||||
            self.assertEqual(value, str(fixture['limits']['absolute'][name]))
 | 
			
		||||
        xmlutil.validate_schema(root, 'limits', version='v3')
 | 
			
		||||
 | 
			
		||||
        #verify rate limits
 | 
			
		||||
        rates = root.xpath('ns:rates/ns:rate', namespaces=NS)
 | 
			
		||||
@@ -985,17 +856,11 @@ class LimitsXMLSerializationTest(test.NoDBTestCase):
 | 
			
		||||
    def test_index_no_limits(self):
 | 
			
		||||
        serializer = limits.LimitsTemplate()
 | 
			
		||||
 | 
			
		||||
        fixture = {"limits": {
 | 
			
		||||
                   "rate": [],
 | 
			
		||||
                   "absolute": {}}}
 | 
			
		||||
        fixture = {"limits": {"rate": []}}
 | 
			
		||||
 | 
			
		||||
        output = serializer.serialize(fixture)
 | 
			
		||||
        root = etree.XML(output)
 | 
			
		||||
        xmlutil.validate_schema(root, 'limits')
 | 
			
		||||
 | 
			
		||||
        #verify absolute limits
 | 
			
		||||
        absolutes = root.xpath('ns:absolute/ns:limit', namespaces=NS)
 | 
			
		||||
        self.assertEqual(len(absolutes), 0)
 | 
			
		||||
        xmlutil.validate_schema(root, 'limits', version='v3')
 | 
			
		||||
 | 
			
		||||
        #verify rate limits
 | 
			
		||||
        rates = root.xpath('ns:rates/ns:rate', namespaces=NS)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "limits": {
 | 
			
		||||
        "absolute": {
 | 
			
		||||
            "maxImageMeta": 128,
 | 
			
		||||
            "maxPersonality": 5,
 | 
			
		||||
            "maxPersonalitySize": 10240,
 | 
			
		||||
            "maxSecurityGroupRules": 20,
 | 
			
		||||
            "maxSecurityGroups": 10,
 | 
			
		||||
            "maxServerMeta": 128,
 | 
			
		||||
            "maxTotalCores": 20,
 | 
			
		||||
            "maxTotalFloatingIps": 10,
 | 
			
		||||
            "maxTotalInstances": 10,
 | 
			
		||||
            "maxTotalKeypairs": 100,
 | 
			
		||||
            "maxTotalRAMSize": 51200
 | 
			
		||||
        },
 | 
			
		||||
        "rate": [
 | 
			
		||||
            {
 | 
			
		||||
                "limit": [
 | 
			
		||||
 
 | 
			
		||||
@@ -13,17 +13,4 @@
 | 
			
		||||
      <limit next-available="%(timestamp)s" unit="MINUTE" verb="GET" remaining="3" value="3"/>
 | 
			
		||||
    </rate>
 | 
			
		||||
  </rates>
 | 
			
		||||
  <absolute>
 | 
			
		||||
    <limit name="maxServerMeta" value="128"/>
 | 
			
		||||
    <limit name="maxPersonality" value="5"/>
 | 
			
		||||
    <limit name="maxImageMeta" value="128"/>
 | 
			
		||||
    <limit name="maxPersonalitySize" value="10240"/>
 | 
			
		||||
    <limit name="maxSecurityGroupRules" value="20"/>
 | 
			
		||||
    <limit name="maxTotalKeypairs" value="100"/>
 | 
			
		||||
    <limit name="maxSecurityGroups" value="10"/>
 | 
			
		||||
    <limit name="maxTotalCores" value="20"/>
 | 
			
		||||
    <limit name="maxTotalFloatingIps" value="10"/>
 | 
			
		||||
    <limit name="maxTotalInstances" value="10"/>
 | 
			
		||||
    <limit name="maxTotalRAMSize" value="51200"/>
 | 
			
		||||
  </absolute>
 | 
			
		||||
</limits>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user