Statistics
| Branch: | Tag: | Revision:

root / docs / design / resource-pool-projects.rst @ 9b94cf0f

History | View | Annotate | Download (16.6 kB)

1
Resource-pool projects
2
^^^^^^^^^^^^^^^^^^^^^^
3

    
4
This document describes the current state of the quota and projects system,
5
and proposes a new design for projects that would function as resource
6
pools. It sketches implementation details and migration concerns.
7

    
8
Current state and shortcomings
9
==============================
10

    
11
Each Synnefo user is granted quota for several resources. These quota
12
originate from two different sources: the system and projects. By default
13
a user holds so-called base quota granted by the system upon activation;
14
base quota can be customized per user. When a user joins a project,
15
resources offered by the project add up to the existing quota, increasing
16
the total amount of resources one can reserve.
17

    
18
This design fails to associate an actual (reserved) resource (e.g. VM) with
19
a particular project. There is no way to tell which project a resource
20
originates from and is thus not possible to employ any targeted policy when
21
a user leaves a project, such as reclaiming the granted resource. It is also
22
not possible to employ more advanced access control on resources, such as
23
sharing VMs among members of a project.
24

    
25
Proposed changes
26
================
27

    
28
We will alter project semantics so that a project is viewed as a pool of
29
finite resources. Each project member can reserve a portion of these
30
resources up to a specified limit. Each actual resource (e.g. VM) is
31
associated with a particular project. Admission of a user to a project will
32
no more result in increasing the user's existing overall quota, but in
33
defining new project-specific quota for the user.
34

    
35
A project defines a pair of limits for each resource that it grants (e.g.
36
cyclades.vm): project-level limit and member-level limit; The former is the
37
total amount of a resource that this project can grant; the latter is the
38
maximum amount that an individual user (project member) can reserve and
39
cannot exceed the former. A limit on the number of members allowed is still
40
enforced.
41

    
42
Projects will be the sole source of resources. Current base quota offered to
43
users by the system will be expressed in terms of special-purpose *base*
44
projects.
45

    
46
Implementation details
47
======================
48

    
49
Project-related quota holdings
50
------------------------------
51

    
52
The Quotaholder is responsible to record all resource allocations and
53
deallocations, and enforce the limits. It keeps counters of the following
54
structure:
55
 * resource: the resource name (e.g. cyclades.vm)
56
 * holder: the entity holding the resource (user or project)
57
 * source: the origin of the resource; a user-holder reserves from a
58
   project, a project is a top-level entity and reserves from nowhere (None)
59
 * limit: maximum allowed allocation (an integer)
60
 * usage: current allocation (an integer)
61

    
62
[Due to the transactional nature of the mechanism, there are actually two
63
usage fields (usage_min and usage_max). Details are beyond the scope of
64
this document.]
65

    
66
Creation of a new project triggers the creation of counters like::
67

    
68
  resource      holder              source   limit   usage
69
  ------------|-------------------|--------|-------|------
70
  cyclades.vm   project:projectID   None     50      0
71

    
72
When a user is admitted in a project, counters are created like::
73

    
74
  resource      holder          source              limit   usage
75
  ------------|---------------|-------------------|-------|------
76
  cyclades.vm   user:userUUID   project:ProjectID   5       0
77

    
78
Note that the two types of holders (and sources) are made distinguishable with
79
a prefix: ``user:`` or ``project:``.
80

    
81
When a user leaves a project, the latter limit is set to zero. This results
82
in the project-specific user quota being over limit and prohibits any
83
further allocation that would increase this counter. When a project
84
is deactivated, the limit of both types of counters is set to zero.
85
No user can perform any allocation related to this project. However, the
86
holdings cannot be deleted as long as a non-zero usage is recorded.
87
Deallocation is always allowed as long as usage does not fall below zero.
88
Counters with zero usage and limit could by garbage collected by Astakos, if
89
needed.
90

    
91
Base projects
92
-------------
93

    
94
For reasons of uniformity, we replace the base quota mechanism with projects.
95
In a similar vein to OpenStack tenants, we define new user-specific *base*
96
projects to account for the base quota for each user. These projects should
97
be clearly associated with a single user, restrict join/leave actions and
98
specify the quota granted by the system. When a new user is created,
99
their base project will be automatically created and linked back to the user.
100
User activation will trigger project activation, granting the default resource
101
quota. Base projects will have no owner, marked thusly as `system' projects.
102
The administrator can, following the usual project logic, alter quota by
103
modifying the project. Users cannot apply for modification of their base
104
projects.
105

    
106
Projects will, from now on, be identified by a UUID. Base projects will
107
receive the same UUID as the user itself. ProjectID, which appears above in
108
the Quotaholder entries, refers to the project UUID.
109

    
110
Base quota will be expressed both in terms of a project-level and a
111
member-level limit. This will result in two operationally equivalent
112
Quotaholder counters, as in the following example. In the future, we could
113
admit third-party users to a user's base project; in that case, those
114
counters would differ.
115

    
116
::
117

    
118
  resource      holder         source         limit   usage
119
  ------------|--------------|--------------|-------|------
120
  cyclades.vm   project:uuid   None           5       1
121
  cyclades.vm   user:uuid      project:uuid   5       1
122

    
123
System default base quota
124
-------------------------
125

    
126
Each resource registered in the system is assigned a default quota limit.
127
A newly-activated user is given these limits as their base quota. Up to now,
128
a change in a default quota limit propagates to all users' base quota
129
(except if they have been customized). Since all users' base quota will be
130
controlled through their base projects, the default behavior of
131
``resource-modify`` will change to affect only future users (i.e.
132
construction of new base projects). However, new option
133
``--update-existing-base-projects`` will allow setting the limits to
134
existing base projects, too. This is useful, for example, when setting a
135
newly registered resource.
136

    
137
Private projects
138
----------------
139

    
140
Since the introduction of base projects will explode the number of total
141
projects, we will need to control their visibility. We add a new flag
142
*private* in project definitions. A private project can only be accessed by
143
its owner and members and not be advertised in the UI. Base projects are
144
marked as private.
145

    
146
Allocation of a new resource
147
----------------------------
148

    
149
When a service allocates a new resource, it should associate it both with a
150
user and a project. The commission issued to the Quotaholder should attempt
151
to update all related counters. For example, it should include the following
152
provisions::
153

    
154
  "provisions": [
155
          {
156
              "holder": "user:user-uuid",
157
              "source": "project:project-uuid",
158
              "resource": "cyclades.vm",
159
              "quantity": 1
160
          },
161
          {
162
              "holder": "project:project-uuid",
163
              "source": None,
164
              "resource": "cyclades.vm",
165
              "quantity": 1
166
          },
167
          {
168
              "holder": "user:user-uuid",
169
              "source": "project:project-uuid",
170
              "resource": "cyclades.cpu",
171
              "quantity": 2
172
          },
173
          {
174
              "holder": "project:project-uuid",
175
              "source": None,
176
              "resource": "cyclades.cpu",
177
              "quantity": 2
178
          }
179
  ]
180

    
181
If any of these provisions fails, i.e. either on the project-level limits or
182
the user-level ones, the whole commission fails.
183

    
184
The astakosclient call ``issue_one_commission`` will be adapted to abstract
185
away the need to write both the user-level and the project-level provisions.
186
The previous commission will be issued with::
187

    
188
  issue_one_commission(holder="user-uuid", source="project-uuid",
189
                       provisions={"cyclades.vm": 1, "cyclades.cpu": 2})
190

    
191
The service is responsible to record this resource-to-project association.
192
In Cyclades, each VM, floating IP, or other distinct resource should be
193
linked to a project. Pithos should link containers to projects.
194

    
195
Astakos will handle its own resource ``astakos.pending_app`` in a special
196
way: it will always be charged at the user's base project. This resource
197
is marked with ``allow_in_projects = False`` in its definition. Since quota
198
is now project-based, this flag will now be interpreted as forbidding usage
199
in non-base projects.
200

    
201
Resource reassignment
202
---------------------
203

    
204
The system will support reassigning a resource to a new project. One needs
205
to specify all related resource values. Astakosclient will provide a
206
convenience function ``issue_resource_reassignment`` to construct all needed
207
provisions. For instance, reassigning a VM with two CPUs can be done with::
208

    
209
  issue_resource_reassignment(holder="user-uuid",
210
                              from_source="from-uuid", to_source="to-uuid",
211
                              provisions={"cyclades.vm": 1, "cyclades.cpu": 2})
212

    
213
This will issue the following provisions to the Quotaholder::
214

    
215
  "provisions": [
216
          {
217
              "holder": "user:user-uuid",
218
              "source": "project:from-uuid",
219
              "resource": "cyclades.vm",
220
              "quantity": -1
221
          },
222
          {
223
              "holder": "project:from-uuid",
224
              "source": None,
225
              "resource": "cyclades.vm",
226
              "quantity": -1
227
          },
228
          {
229
              "holder": "user:user-uuid",
230
              "source": "project:from-uuid",
231
              "resource": "cyclades.cpu",
232
              "quantity": -2
233
          },
234
          {
235
              "holder": "project:from-uuid",
236
              "source": None,
237
              "resource": "cyclades.cpu",
238
              "quantity": -2
239
          },
240
          {
241
              "holder": "user:user-uuid",
242
              "source": "project:to-uuid",
243
              "resource": "cyclades.vm",
244
              "quantity": 1
245
          },
246
          {
247
              "holder": "project:to-uuid",
248
              "source": None,
249
              "resource": "cyclades.vm",
250
              "quantity": 1
251
          }
252
          {
253
              "holder": "user:user-uuid",
254
              "source": "project:to-uuid",
255
              "resource": "cyclades.cpu",
256
              "quantity": 2
257
          },
258
          {
259
              "holder": "project:to-uuid",
260
              "source": None,
261
              "resource": "cyclades.cpu",
262
              "quantity": 2
263
          }
264
  ]
265

    
266
API extensions
267
--------------
268

    
269
API call ``GET /quotas`` is extended to incorporate project-level quota. The
270
response contains entries for all projects for which a user/project pair
271
exists in the quotaholder::
272

    
273
  {
274
      "project1-uuid": {
275
          "cyclades.ram": {
276
              "usage": 2147483648,
277
              "limit": 2147483648,
278
              "pending": 0,
279
              "project_usage": ...,
280
              "project_limit": ...,
281
              "project_pending": ...
282
          },
283
          "cyclades.vm": {
284
              ...
285
          }
286
      }
287
      "project2-uuid": {
288
          ...
289
      }
290
  }
291

    
292
An extra or differentiated call may be needed to retrieve the project quota
293
regardless of user::
294

    
295
  GET /quotas?mode=projects
296

    
297
  {
298
      "project-uuid": {
299
          "cyclades.ram": {
300
              "project_usage": 2147483648,
301
              "project_limit": 2147483648,
302
              "project_pending": 0
303
          }
304
          "cyclades.vm": {
305
              ...
306
          }
307
      }
308
  }
309

    
310
All service API calls that create resources can specify the project where
311
they will be attributed.
312

    
313
In cyclades, ``POST /servers`` (likewise for networks and floating IPs) will
314
receive an extra argument ``project``. If it is missing, the user's base
315
project will be assumed. In calls detailing a resource (e.g., ``GET
316
/servers/<server_id>``), the field ``tenant_id`` will contain the
317
project id.
318

    
319
Moreover, extra calls will be needed for resource reassignment,
320
e.g::
321

    
322
  POST /servers/<server-id>/action
323

    
324
  {
325
      "reassign": {"project": <project-id>}
326
  }
327

    
328
In pithos, ``PUT`` and ``POST`` calls at the container level will accept an
329
extra optional policy ``project``. The former call assigns a newly created
330
container to a given project, the latter reassigns an existing container.
331
Field ``x-container-policy-project`` will be retrieved by a ``HEAD`` call at
332
the container level.
333

    
334
User interface
335
--------------
336

    
337
User quota will be presented per project, including the aggregate activity
338
of other project members: the Resource Usage page will include a drop-down
339
menu with all relevant projects. By default, user's base project will
340
be assumed. When choosing a project, usage for all resources will be
341
presented for the given project in the following style::
342

    
343
                        limit
344
    used                ^                    taken by others
345
  |::::::|..............|...........|::::::::::::::::::::::::::::::::::|
346
         ^              ^                                              ^
347
         usage          effective                                      project
348
                        limit                                          limit
349

    
350

    
351
                        limit
352
    used                ^          taken by others
353
  |::::::|........|:::::|::::::::::::::::::::::::::::::::::::::::::::::|
354
         ^        ^                                                    ^
355
         usage    effective                                            project
356
                  limit                                                limit
357

    
358
Text accompanying the bar could mention usage based on the effective limit,
359
e.g.: `usage` out of `effective limit` Virtual Machines. Likewise the shaded
360
`used` part of the bar could express the same ratio in percentage terms.
361

    
362
Given the above-mentioned response of the ``/quotas`` call, the effective
363
limit can be computed by::
364

    
365
  taken_by_others = project_usage - usage
366
  effective_limit = min(limit, project_limit - taken_by_others)
367

    
368
Projects show up in a number of service-specific user interactions, too.
369
When creating a Cyclades VM, the flavor-choosing window should first ask
370
for the project where the VM will be charged before showing the
371
available resource combinations. Likewise, creating a new container in
372
Pithos will prompt for picking a project to associate with.
373

    
374
Resource presentation (e.g. Cyclades VMs) will also mention the associated
375
project and provide an action to reassign the resource to a different
376
project.
377

    
378
Command-line interface
379
----------------------
380

    
381
Quota can be queried per user or project::
382

    
383
  # snf-manage user-show <id> --quota
384

    
385
  project  resource    limit  effective_limit usage
386
  -------------------------------------------------
387
  uuid     cyclades.vm 10     9               5
388

    
389
  # snf-manage project-show <id> --quota
390

    
391
  resource    limit  usage
392
  ------------------------
393
  cyclades.vm 100    50
394

    
395
``snf-manage quota`` will be removed; checking the integrity of the
396
Quotaholder will be provided by a new command ``reconcile-quota``.
397

    
398
A new command ``snf-manage project-modify`` will automate the process of
399
applying/approving applications in order to modify some project settings,
400
such as the quota limits.
401

    
402
Currently, the administrator can change the user base quota with:
403
``snf-manage user-modify <id> --set-base-quota <resource> <capacity>``.
404
This will be removed in favor of the ``project-modify`` command, so that all
405
quota are handled in a uniform way.
406

    
407
Migration steps
408
===============
409

    
410
Project conversion
411
------------------
412

    
413
Existing projects need to be converted to resource-pool ones. The following
414
steps must be taken in Astakos:
415
  * compute project-level limits for each resource as
416
    max_members * member-level limit
417
  * create base projects based on base quota for each user
418
  * make Quotaholder entries for projects and user/project pairs
419
  * assign all current usage to the base projects (both project
420
    and user/project entries)
421
  * set usage for all other entries to zero
422

    
423
Cyclades and Pithos should initialize their project attribute on each resource
424
with the user's base project, that is, the same UUID as the resource owner.
425

    
426
Initial resource reassignment
427
-----------------------------
428

    
429
Once migration has finished, users will be off-quota on their base project,
430
if they had used additional quota from projects. To alleviate this
431
situation, each service can attempt to reassign resources to other projects,
432
following this strategy:
433
  * consult Astakos for projects and quota for a given user
434
  * select resources that can fit in another project
435
  * issue a commission to decrease usage of the base project and likewise
436
    increase usage of the available project
437
  * record the new ProjectUUID for the reassigned resources