Browse Source

Strict Two-Level Limits Enforcement Model

This spec talks about that how the hierarchical unified limits
will work in Keystone and its consumers.

In rocky, we'd like to add the strict two level enforcement model
as the base one for hierarchical unified limits.

Co-Authored-By: John Garbutt <john@johngarbutt.com>
Co-Authored-By: Lance Bragstad <lbragstad@gmail.com>
Co-Authored-By: Morgan Fainberg <morgan.fainberg@gmail.com>

Change-Id: Ibfb2ba2ffb0115fa7cf81d30bf9a025652d9ba42
bp: strict-two-level-enforcement-model
wangxiyuan 1 year ago
parent
commit
d4e19f17ff
1 changed files with 715 additions and 0 deletions
  1. 715
    0
      specs/keystone/rocky/strict-two-level-enforcement-model.rst

+ 715
- 0
specs/keystone/rocky/strict-two-level-enforcement-model.rst View File

@@ -0,0 +1,715 @@
1
+..
2
+ This work is licensed under a Creative Commons Attribution 3.0 Unported
3
+ License.
4
+
5
+ http://creativecommons.org/licenses/by/3.0/legalcode
6
+
7
+=========================================
8
+Strict Two-Level Limits Enforcement Model
9
+=========================================
10
+
11
+This specification describes the behaviors and use-cases of a strict
12
+enforcement model for limits associated to resources in a hierarchical project
13
+structure.
14
+
15
+`bp strict-two-level-model  <https://blueprints.launchpad.net/keystone/+spec/strict-two-level-model>`_
16
+
17
+Problem Description
18
+===================
19
+
20
+The unified limit `specification`_ and implementation, introduced in the Queens
21
+release, ignore all details about project structure. It's only enforcement
22
+model is `flat`_. This means limits associated to any part of the tree are not
23
+validated against each other.
24
+
25
+.. _specification: http://specs.openstack.org/openstack/keystone-specs/specs/keystone/queens/limits-api.html
26
+.. _flat: https://docs.openstack.org/keystone/latest/admin/identity-unified-limits.html#flat
27
+
28
+Proposed Change
29
+===============
30
+
31
+This specification goes through the details for a strict two-level hierarchical
32
+enforcement model.
33
+
34
+Use Cases
35
+---------
36
+
37
+* As an operator, I want to be able to set the limit for a top-level project
38
+  and ensure its usage never exceeds that limit, resulting in strict usage
39
+* As a user responsible for managing limits across projects, I want to be able
40
+  to set limits across child projects in a way that is flexible enough to allow
41
+  resources to flow between projects under a top-level project
42
+
43
+These use cases were mentioned on the mailing list in an early `discussion`_
44
+about unified limits.
45
+
46
+.. _discussion: http://lists.openstack.org/pipermail/openstack-dev/2017-February/111999.html
47
+
48
+Model Behaviors
49
+---------------
50
+
51
+This model:
52
+
53
+* requires project hierarchy never exceeds a depth of two, meaning hierarchies
54
+  are limited to parent and child relationships
55
+* requires each tree have a single parent, or tree root
56
+* allows parents, or tree roots, to have any number of children
57
+* allows quota overcommit, i.e. the aggregate quota limit (not usage) may
58
+  exceed the limit of the parent. Overcommit and user-experience related to
59
+  overcommit is a leading factor for the strict two-level hierarchy.
60
+* does not directly solve sharing data across endpoints, e.g.
61
+  each nova would not be aware of the other nova's quota consumption meaning
62
+  a user could consume the full amount of quota on each endpoint.
63
+
64
+This model implements limit validation in keystone that:
65
+
66
+* allows the sum of all child limits to exceed the limit of the parent, or tree
67
+  root
68
+* disallows a child limit from exceeding the parent limit
69
+* assumes registered limits as the default for projects that are not given a
70
+  project-specific override
71
+
72
+This model is consumed by ``oslo.limit`` in a way that:
73
+
74
+* requires services responsible for resources to implement a usage callback for
75
+  ``oslo.limit`` to use to calculate usage for the project tree
76
+* requires that usage be calculated on every request
77
+
78
+The ``oslo.limit`` library will enforce the model such that the resource usage
79
+sum across the entire tree cannot exceed the resource limit set by the parent.
80
+
81
+This model is called a ``strict-two-level`` enforcement model. It is `strict`
82
+because the usage of a resource across the entire tree can never exceed the
83
+parent limit. It is considered a `two-level` model because it only assumes to
84
+work on project hierarchies of two or less.
85
+
86
+Enforcement Diagrams
87
+--------------------
88
+
89
+The following diagrams illustrate the above behaviors, using projects named
90
+``A``, ``B``, ``C``, and ``D``. Assume the resource in question is ``cores``,
91
+and the default registered limit for ``cores`` is 10.  The labels in the
92
+diagrams below use shorthand notation for `limit` and `usage` as `l` and `u`,
93
+respectively.
94
+
95
+.. blockdiag::
96
+
97
+   blockdiag {
98
+      orientation = portrait;
99
+
100
+      A -> B;
101
+      A -> C;
102
+
103
+      A [label="A (l=20, u=0)"];
104
+      B [label="B (u=0)"];
105
+      C [label="C (u=0)"];
106
+   }
107
+
108
+Technically, both ``B`` and ``C`` can use up to 10 ``cores`` each and consume
109
+the entire limit for the tree. Resulting in:
110
+
111
+.. blockdiag::
112
+
113
+   blockdiag {
114
+      orientation = portrait;
115
+
116
+      A -> B;
117
+      A -> C;
118
+
119
+      A [label="A (l=20, u=0)"];
120
+      B [label="B (u=10)", textcolor = "#00af00"];
121
+      C [label="C (u=10)", textcolor = "#00af00"];
122
+   }
123
+
124
+If ``A`` attempts to claim two ``cores``, the usage check will fail because
125
+``oslo.limit`` will fetch the hierarchy from keystone and check the usage of
126
+each project in the hierarchy by using the callback provided by the service to
127
+see that both ``B`` and ``C`` have 10 ``cores`` each:
128
+
129
+.. blockdiag::
130
+
131
+   blockdiag {
132
+      orientation = portrait;
133
+
134
+      A -> B;
135
+      A -> C;
136
+
137
+      A [label="A (l=20, u=2)", textcolor = "#FF0000"];
138
+      B [label="B (u=10)"];
139
+      C [label="C (u=10)"];
140
+   }
141
+
142
+Despite the usage of the tree being equal to the limit, we can still add
143
+children to the tree:
144
+
145
+.. blockdiag::
146
+
147
+   blockdiag {
148
+      orientation = portrait;
149
+
150
+      A -> B;
151
+      A -> C;
152
+      A -> D;
153
+
154
+      A [label="A (l=20, u=0)"];
155
+      B [label="B (u=10)"];
156
+      C [label="C (u=10)"];
157
+      D [label="D (u=0)", textcolor = "#00af00"];
158
+   }
159
+
160
+Even though the project can be created, the current usage of cores across the
161
+tree prevents ``D`` from claiming any ``cores``:
162
+
163
+.. blockdiag::
164
+
165
+   blockdiag {
166
+      orientation = portrait;
167
+
168
+      A -> B;
169
+      A -> C;
170
+      A -> D;
171
+
172
+      A [label="A (l=20, u=0)"];
173
+      B [label="B (u=10)"];
174
+      C [label="C (u=10)"];
175
+      D [label="D (u=2)", textcolor = "#FF0000"];
176
+   }
177
+
178
+Creating a grandchild of project ``A`` is forbidden because it violates the
179
+two-level hierarchy constraint. This is a fundamental contraint of this design
180
+because it provides a very clear escalation path. When a request fails because
181
+the tree limit has been exceeded, a user has all the information they need to
182
+provide meaningful context in a support ticket (e.g. their project ID and the
183
+parent project ID). An administrator of project ``A`` should be able to
184
+reshuffle usage accordingly. A system administrator should be able to do the
185
+same thing. Providing this information in tree structures with more than a
186
+depth of two is much harder, but may be implemented with a separate model.
187
+
188
+.. blockdiag::
189
+
190
+   blockdiag {
191
+      orientation = portrait;
192
+
193
+      A -> B;
194
+      A -> C;
195
+      C -> D;
196
+
197
+      A [label="A (l=20, u=0)"];
198
+      B [label="B (u=10)"];
199
+      C [label="C (u=10)"];
200
+      D [label="D (u=0)", textcolor = "#FF0000"];
201
+   }
202
+
203
+Granting ``B`` the ability to claim more cores can be done by giving ``B`` a
204
+project-specific override for ``cores``:
205
+
206
+.. blockdiag::
207
+
208
+   blockdiag {
209
+      orientation = portrait;
210
+
211
+      A -> B;
212
+      A -> C;
213
+
214
+      A [label="A (l=20, u=0)"];
215
+      B [label="B (l=12, u=10)", textcolor = "#00af00"];
216
+      C [label="C (u=10)"];
217
+   }
218
+
219
+Note that regardless of this update, any subsequent requests to claim more
220
+``cores`` in the tree will be forbidden since the usage is equal to the limit
221
+of the ``A``. If ``cores`` are released from ``C``, ``B`` can claim them:
222
+
223
+.. blockdiag::
224
+
225
+   blockdiag {
226
+      orientation = portrait;
227
+
228
+      A -> B;
229
+      A -> C;
230
+
231
+      A [label="A (l=20, u=0)"];
232
+      B [label="B (l=12, u=10)"];
233
+      C [label="C (u=8)", textcolor = "#00af00"];
234
+   }
235
+
236
+.. blockdiag::
237
+
238
+   blockdiag {
239
+      orientation = portrait;
240
+
241
+      A -> B;
242
+      A -> C;
243
+
244
+      A [label="A (l=20, u=0)"];
245
+      B [label="B (l=12, u=12)", textcolor = "#00af00"];
246
+      C [label="C (u=8)"];
247
+   }
248
+
249
+While ``C`` is still under its default allocation of 10 ``cores``, it won't be
250
+able to claim any more ``cores`` because the total usage of the tree is equal
251
+to the limit of ``A``, thus preventing ``C`` from reclaiming the ``cores`` it
252
+had:
253
+
254
+.. blockdiag::
255
+
256
+   blockdiag {
257
+      orientation = portrait;
258
+
259
+      A -> B;
260
+      A -> C;
261
+
262
+      A [label="A (l=20, u=0)"];
263
+      B [label="B (l=12, u=12)"];
264
+      C [label="C (u=10)", textcolor = "#FF0000"];
265
+   }
266
+
267
+Creating or updating a project with a limit that exceeds the limit of ``A`` is
268
+forbidden. Even though it is possible for the sum of all limits under ``A`` to
269
+exceed the limit of ``A``, the total usage is capped at ``A.limit``. Allowing
270
+children to have explicit overrides greater than the limit of the parent would
271
+result in strange user experience and be misleading since the total usage of
272
+the tree would be capped at the limit of the parent:
273
+
274
+.. blockdiag::
275
+
276
+   blockdiag {
277
+      orientation = portrait;
278
+
279
+      A -> B;
280
+      A -> C;
281
+
282
+      A [label="A (l=20, u=0)"];
283
+      B [label="B (l=30, u=0)", textcolor = "#FF0000"];
284
+      C [label="C (u=0)"];
285
+   }
286
+
287
+.. blockdiag::
288
+
289
+   blockdiag {
290
+      orientation = portrait;
291
+
292
+      A -> B;
293
+      A -> C;
294
+      A -> D;
295
+
296
+      A [label="A (l=20, u=0)"];
297
+      B [label="B (u=0)"];
298
+      C [label="C (u=0)"];
299
+      D [label="D (l=30, u=0)", textcolor = "#FF0000"];
300
+   }
301
+
302
+Finally, let's still assume the default registered limit for ``cores`` is 10,
303
+but we're going to create project ``A`` with a limit of 6.
304
+
305
+.. blockdiag::
306
+
307
+   blockdiag {
308
+      orientation = portrait;
309
+
310
+      A;
311
+
312
+      A [label="A (l=6, u=0)", textcolor = "#00af00"];
313
+   }
314
+
315
+When we create project ``B``, which is a child of project ``A``, the limit API
316
+should ensure that project ``B`` doesn't assume the default of 10. Instead, we
317
+should obey the parent's limit since no single child limit should exceed the
318
+limit of the parent:
319
+
320
+.. blockdiag::
321
+
322
+   blockdiag {
323
+      orientation = portrait;
324
+
325
+      A -> B;
326
+
327
+      A [label="A (l=6, u=0)"];
328
+      B [label="B (l=6, u=0)", textcolor = "#00af00"];
329
+   }
330
+
331
+This behavior should be consistent regardless of the number of children added
332
+under project ``A``.
333
+
334
+.. blockdiag::
335
+
336
+   blockdiag {
337
+      orientation = portrait;
338
+
339
+      A -> B;
340
+      A -> C;
341
+      A -> D;
342
+
343
+      A [label="A (l=6, u=0)"];
344
+      B [label="B (l=6, u=0)"];
345
+      C [label="C (l=6, u=0)", textcolor = "#00af00"];
346
+      D [label="D (l=6, u=0)", textcolor = "#00af00"];
347
+   }
348
+
349
+Creating limit overrides while creating projects seems counter-productive given
350
+the whole purpose of a registered default, but it also seems unlikely to
351
+throttle a parent project by specifying it's default to be less than a
352
+registered default. This behavior maintains consistency with the requirement
353
+that the sum of all child limits may exceed the parent limit, but the limit of
354
+any one child may not.
355
+
356
+Proposed Server Changes
357
+-----------------------
358
+
359
+Keystone will need to encapsulate this logic into a new enforcement model.
360
+Ideally, this enforcement model can be called from within the unified limit API
361
+to validate limits before writing them to the backend.
362
+
363
+If keystone is configured to use the ``strict-two-level`` enforcement model and
364
+current project structure within keystone violates the two-level project
365
+constraint, keystone should fail to start. To aid operators, we can develop a
366
+``keystone-manage`` command, to check the hierarchical structure of the
367
+projects in the deployment and warn operators if keystone is going to fail to
368
+start. This gives operators the ability to check and fix their project
369
+hierarchy before they deploy keystone with the new model. This clearly
370
+communicates a set project structure to operators at run time.
371
+
372
+Proposed Library Changes & Consumption
373
+--------------------------------------
374
+
375
+The ``oslo.limit`` library is going to have to know when to enforce usage based
376
+on the ``strict-two-level`` model. It can ask for the current model by querying
377
+the limit API directly:
378
+
379
+**Request:** `GET /v3/limits/model`
380
+
381
+**Response**
382
+
383
+* 200 - OK
384
+* 401 - OK
385
+
386
+**Response Body**
387
+
388
+.. code:: json
389
+
390
+   {
391
+       "model": {
392
+           "name": "strict-two-level",
393
+           "description": "Strict usage enforcement for parent/child relationships."
394
+        }
395
+   }
396
+
397
+The library should expose an object for claims and a context manager so that
398
+consuming services can make the following call from within their API business
399
+logic:
400
+
401
+.. code::
402
+
403
+   from oslo_limit import limit
404
+   LIMIT_ENFORCER = limit.Enforcer()
405
+
406
+    def create_foobar(self, context, foobar):
407
+
408
+        claim = limit.ProjectClaim('foobars', context.project_id, quantity=1)
409
+        callback = self.get_resource_usage_for_project
410
+        with limit.Enforcer(claim, callback=callback):
411
+            driver.create_foobar(foobar)
412
+
413
+
414
+In the above code example, the service builds a ``ProjectClaim`` object that
415
+describes the resource being consumed and the project. The ``claim`` is then
416
+passed to an ``oslo.limit`` context manager and supplimented with a callback
417
+method from the service. The service's callback method is responsible for
418
+calculating resource usage per project. The ``oslo.limit`` library can use the
419
+``project_id`` from the context object to get the limit information from
420
+keystone and calculate usage across the project tree with the callback. The
421
+usage check for the project hierarchy will be executed when the context manager
422
+is instantiated or executing ``__enter__``. By default, exiting the context
423
+manager will verify that the usage was not exceeded by another request,
424
+protecting from race conditions across requests. This can be disabled explicity
425
+using the following::
426
+
427
+   from oslo_limit import limit
428
+   LIMIT_ENFORCER = limit.Enforcer()
429
+
430
+    def create_foobar(self, context, foobar):
431
+
432
+        claim = limit.ProjectClaim('foobars', context.project_id, quantity=1)
433
+        callback = self.get_resource_usage_for_project
434
+        with limit.Enforcer(claim, callback=callback, verify=False):
435
+            driver.create_foobar(foobar)
436
+
437
+Fetching project hierarchy
438
+^^^^^^^^^^^^^^^^^^^^^^^^^^
439
+
440
+The (current) default policy prevents users with a member role on a project
441
+from retrieving the entire project hierarchy. The library that needs the
442
+hierarchy to calculate usage must call the API as a project administrator or
443
+use a service user token. This API is used for both *operators* and
444
+*oslo.limit*.
445
+
446
+**Request:** ``GET /limits?show_hierarchy=true``
447
+
448
+**Request filter**
449
+
450
+* ``show_hierachy`` - Whether to show the hierarchy project limit or not.
451
+
452
+**Response:**
453
+
454
+A list of the hierarchy project limits.
455
+
456
+**Response Code:**
457
+
458
+* 200 - OK
459
+* 404 - Not Found
460
+
461
+**Response Body:**
462
+
463
+.. code:: json
464
+
465
+    {
466
+        "limits":[
467
+            {
468
+                "id": "c1403b468a9443dcabf7a388234f3f68",
469
+                "service_id": "e02156d4fa704d02ac11de4ddba81044",
470
+                "region_id": null,
471
+                "resource_name": "ram_mb",
472
+                "resource_limit": 20480,
473
+                "project_id": "fba8184f0b8a454da28a80f54d80b869",
474
+                "limits": [
475
+                    {
476
+                        "id": "7842e3ff904b48d89191e9b37c2d29af",
477
+                        "project_id": "f7120b7c7efb4c2c8859441eafaa0c0f",
478
+                        "region_id": null,
479
+                        "resource_limit": 10240,
480
+                        "resource_name": "ram_mb",
481
+                        "service_id": "e02156d4fa704d02ac11de4ddba81044"
482
+                    },
483
+                    {
484
+                        "id": "d2a6ebbc5b0141178c07951a10ff547c",
485
+                        "project_id": "443aed1062884dd38cd3893089c3f109",
486
+                        "region_id": null,
487
+                        "resource_limit": 5120,
488
+                        "resource_name": "ram_mb",
489
+                        "service_id": "e02156d4fa704d02ac11de4ddba81044"
490
+                    },
491
+                    {
492
+                        "id": "f8b7f4da96854c4cafe3d985acc5110f",
493
+                        "project_id": "ca7e4b4cd7b849febb34f6cc137089d0",
494
+                        "region_id": null,
495
+                        "resource_limit": 2560,
496
+                        "resource_name": "ram_mb",
497
+                        "service_id": "e02156d4fa704d02ac11de4ddba81044"
498
+                    }
499
+                ]
500
+            }
501
+        ]
502
+    }
503
+
504
+
505
+The above is an example response given the following diagram, where the default
506
+registered limit for ``ram_mb`` is 2560, which applies to ``D``.
507
+
508
+.. blockdiag::
509
+
510
+   blockdiag {
511
+      orientation = portrait;
512
+
513
+      A -> B;
514
+      A -> C;
515
+      A -> D;
516
+
517
+      A [label="A (l=20480)"];
518
+      B [label="B (l=10240)"];
519
+      C [label="C (l=5120)"];
520
+      D [label="D (l=undefined)"];
521
+   }
522
+
523
+Alternatives
524
+------------
525
+
526
+Stick with a flat enforcement model, requiring operators to manually implement
527
+hierarchical limit knowledge.
528
+
529
+Security Impact
530
+---------------
531
+
532
+None
533
+
534
+Notifications Impact
535
+--------------------
536
+
537
+None
538
+
539
+Other End User Impact
540
+---------------------
541
+
542
+None
543
+
544
+Performance Impact
545
+------------------
546
+
547
+Performance of this model is expected to be sub-optimal in comparison to flat
548
+enforcement. The main factor contributing to expected performance loss is the
549
+calculation of usage for the tree. The ``oslo.limit`` library will need to
550
+calculate the usage for every project in the tree in order to provide an answer
551
+to the service regarding the request.
552
+
553
+Other services will be required to make additional calls to keystone to
554
+retrieve limit information in order to do quota enforcement. This will add some
555
+overhead to the overall performance of the API call.
556
+
557
+It is also worth noting that both Registered Limits and Project Limits are not
558
+expected to change frequently. This means the data is safe to cache for some
559
+period of time. Caching has already been implemented internally to keystone,
560
+similar to how keystone caches responses for other resources. Caching can also
561
+be done client-side to avoid making frequent calls to keystone for relatively
562
+static limit information.
563
+
564
+Other Deployer Impact
565
+---------------------
566
+
567
+None
568
+
569
+Developer Impact
570
+----------------
571
+
572
+The enforcement library ``oslo.limit`` should be implemented based on the
573
+enforcement model implemented in keystone.
574
+
575
+The consuming component (e.g. nova, neutron, cinder, etc..)should add the new
576
+way to fetching quota limit from keystone in the future.
577
+
578
+Implementation
579
+==============
580
+
581
+Assignee(s)
582
+-----------
583
+
584
+Primary assignee:
585
+
586
+  * wangxiyuan <wangxiyuan@huawei.com> wxy
587
+  * Lance Bragstad <lbragstad@gmail.com> lbragstad
588
+
589
+Other contributors:
590
+
591
+
592
+Work Items
593
+----------
594
+
595
+* Add the new API ``GET /limits/model``
596
+* Abstract limit validation into a model object
597
+* Implement a new limit model for ``strict-two-level``
598
+* Implement ``strict-two-level`` enforcement in ``oslo.limit``
599
+* Add the new ``show_hierachy`` parameter for limits.
600
+* Add keystone client support for limits.
601
+
602
+Future work
603
+-----------
604
+
605
+Limit and Usage Awareness Across Endpoints
606
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
607
+
608
+``oslo.limit`` and keystone server can be enhanced to utilize ``etcd`` (or
609
+other shared data store) to represent limit data and cross-endpoint
610
+quota-usage. This falls out of scope for this particular specification.  It
611
+should be noted that the model should be able to consume the data from whatever
612
+store is used, not restricted to a local-only datastore.
613
+
614
+Optimized Usage Calculation
615
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
616
+
617
+During the design of this enforcement model, various parties mentioned
618
+performance-related concerns when employing this model for trees with many
619
+projects. For example, calculating usage for ``cores`` across hundreds or
620
+thousands of projects. Consider the following tree structure:
621
+
622
+.. blockdiag::
623
+
624
+   blockdiag {
625
+      orientation = portrait;
626
+
627
+      A -> B;
628
+      A -> C;
629
+
630
+      A [label="A"];
631
+      B [label="B"];
632
+      C [label="C"];
633
+   }
634
+
635
+Consider that each project not only has the concept of ``usage`` and ``limit``,
636
+but also something called an ``aggregate``. An ``aggregate`` is the sum of a
637
+projects ``usage`` and all ``aggregrate`` counts of its children.
638
+
639
+For example, when claiming two ``cores`` on ``C``, ``C.usage=2`` and
640
+``C.aggregate=2``. The tree root, ``A``, is also updated in this case where
641
+``A.aggregate=2``. When a subsequent claim is made on ``B`` updating its usage
642
+to ``B.usage=2``, the usage calculation only needs to check the ``aggregate``
643
+usage property of the parent project, or the project tree.
644
+
645
+This simplifies the usage calculation process by only having to query the
646
+parent, or tree root, for it's aggregate usage. As opposed to querying each
647
+project for it's usage and sum the result of each aggregate stored for the
648
+parent.
649
+
650
+The following illustrates a more extreme example:
651
+
652
+.. blockdiag::
653
+
654
+   blockdiag {
655
+      orientation = portrait;
656
+
657
+      A -> B;
658
+      A -> C;
659
+      B -> D;
660
+      B -> E;
661
+
662
+      A [label="A"];
663
+      B [label="B"];
664
+      C [label="C"];
665
+      D [label="D"];
666
+      E [label="E"];
667
+   }
668
+
669
+Let's assume each project has ``usage=0`` and ``limit=10``. The following might
670
+be a possible scenario: When claiming
671
+resources on ``D.usage=4``
672
+
673
+* SET ``D.usage=4 AND D.aggregate=4``
674
+* SET ``B.aggregate=4``, since ``B.usage=0`` currently
675
+* SET ``A.aggregate=4``, since ``A.usage=0`` currently
676
+* SET ``C.usage=6 AND C.aggregate=6``
677
+* SET ``A.aggregate=10``, since ``A.usage=0`` still
678
+* SET ``E.usage=2`` fails
679
+
680
+The last step in the flow fails because the entire tree is already at limit
681
+capacity for ``cores`` once ``C`` finalizes its claim. The advantage is that we
682
+only need to ask for ``A.aggregate`` in order to calculate usage when ``E``
683
+attempts to make its claim, since finalized claims "bubble up" the tree.
684
+
685
+Note that this requires services to track usage and aggregate usage, raising
686
+the bar for adoption if this is a desired path forward.
687
+
688
+Dependencies
689
+============
690
+
691
+* Requires API to expose configured limit model (see `bug 1765193`_)
692
+* Abstract model into it's own area of keystone to keep limit CRUD isolated
693
+  from enforcement model
694
+
695
+.. _bug 1765193: https://launchpad.net/bugs/1765193
696
+
697
+Documentation Impact
698
+====================
699
+
700
+* The supported limit model and the new enforcement step must be documented.
701
+
702
+References
703
+==========
704
+
705
+* Queens Unified Limit `specification`_
706
+* High-level `description`_ of unified limits
707
+* Rocky PTG design session `etherpad`_
708
+* Early `review`_ containing model context
709
+* Adam's `blog`_ about quota
710
+
711
+.. _specification: http://specs.openstack.org/openstack/keystone-specs/specs/keystone/queens/limits-api.html
712
+.. _description: http://specs.openstack.org/openstack/keystone-specs/specs/keystone/ongoing/unified-limits.html
713
+.. _etherpad: https://etherpad.openstack.org/p/unified-limits-rocky-ptg
714
+.. _review: https://review.openstack.org/#/c/441203/
715
+.. _blog: https://adam.younglogic.com/2018/05/tracking-quota/

Loading…
Cancel
Save