Statistics
| Branch: | Tag: | Revision:

root / doc / manual / source / devguide.rst @ 2a36ca49

History | View | Annotate | Download (19.9 kB)

1
Development Guide
2
=================
3

    
4
The development guide includes descriptions of the APIs and extention points
5
offered by Aquarium. It also includes design and development setup information.
6

    
7
Obtaining and Compiling
8
-----------------------
9

    
10
The source code to the Aquarium project can be obtained through Git, by
11
cloning the repository `http://code.grnet.gr/git/aquarium`. This will give
12
you read-only access to the repository. You need to contact the Aquarium
13
team to obtain read-write access.
14

    
15
To compile Aquarium, you need the following software in your path:
16

    
17
- Java SDK 6. Java 7 has not been tested yet.
18
- `Maven <http://maven.apache.org>`_, version > 3
19

    
20
After you install them, you can do the following:
21

    
22
- ``mvn install``: To compile Aquarium and run the tests. This will also create 
23
  the file ``target/aquarium-<ver>-jar-with-dependencies.jar`` which can be
24
  used to start Aquarium from the command line
25
- ``mvn deploy``:  To deploy the Aquarium libraries to the remote Maven repository
26
- ``mvn release:prepare``, ``mvn release:perform``: To prepare a release,
27
  tag a new version and start the next development version
28
- ``mvn scala:cctest``: To run the Scala compiler in continuous compilation
29
  mode
30

    
31
Aquarium can also be build with the Simple Build Tool
32
(`SBT <https://github.com/harrah/xsbt/wiki>`_). Just run ``sbt`` in the directory 
33
containing the Aquarium source code.
34

    
35
Distributing
36
^^^^^^^^^^^^
37

    
38
To prepare a binary distribution of Aquarium, use the ``make-dist.sh`` script.
39
If the script is run without an argument, it will create a TAR archive from
40
the latest tagged version of Aquarium. The script also accepts a Git commit-ish,
41
in which case it will build a TAR archive out of the provided Git commit.
42

    
43
Overall architecture
44
--------------------
45

    
46
Aquarium's architectural design is mainly driven by two requirements: scaling
47
and fault tolerance. Aquarium's functionality is based on event sourcing.
48
`Event sourcing <http://en.wikipedia.org/wiki/Domain-driven_design>`_ 
49
assumes that all changes to application state are stored as a
50
sequence of events, in an immutable log. With such a log at hand, a system can
51
rebuild the current application state by replaying the events in order. The event
52
sourcing design pattern has some very interesting properties, which made it
53
particularity suitable for basing Aquarium on it:
54

    
55
- Multiple models can be used in order to process the events, concurrently. This means that Aquarium can provide a limited data view to its REST API and a more detailed one to a helpdesk frontend.
56

    
57
- It is possible to perform queries on past system states by stopping the event replay at a certain point of interest. This would prove very possible for a future debugging interface.
58

    
59
- In a carefully implemented event sourcing system, application crashes are not destructive, as long as event replay is fast enough and no state is inserted to the application without being recorded to the event log first.
60

    
61
- After event log replay, new events only cause updates in the system’s in-memory state, which can be done very fast.
62

    
63
Components
64
^^^^^^^^^^
65

    
66
.. image:: arch.png
67

    
68
An overview of the Aquarium architecture is presented in the figure above.  The
69
system is modeled as a collection of logically and functionally isolated
70
components, which communicate by message passing. Withing each component, a
71
number of actors take care of concurrently processing incoming messages through
72
a load balancer component which is the gateway to requests targeted to the
73
component. Each component is also monitored by its own supervisor; should an
74
actor fail, the supervisor will automatically restart it. The architecture
75
allows certain application paths to fail individually while the system is still
76
responsive, while also enabling future distribution of multiple components on
77
clusters of machines.
78

    
79
The system receives input mainly from two sources: a queue for resource and
80
user events and a REST API for credits and resource state queries. The queue
81
component reads messages from a configurable number of queues and persists them
82
in the application’s immutable log store. Both input components then forward
83
incoming messages to a network of dispatcher handlers which do not do any
84
processing by themselves, but know where the user actors lay. Actual processing
85
of billing events is done within the user actors. Finally, a separate network
86
of actors take care of scheduling periodic tasks, such as refiling of user
87
credits; it does so by issuing events to the appropriate queue.
88

    
89
The accounting system
90
----------------------
91

    
92
The accounting subsystem deals with charging users for services used and 
93
providing them with credits in order to be able to use the provided services.
94
As with the rest of the Aquarium, the architecture is open-ended: the accounting
95
system does not know in advance which services it supports or what resources
96
are being offered. The configuration of the accounting system is done
97
using a Domain Specific Language (DSL) described below. 
98

    
99
Data exchange with external systems is done through events, which are
100
persisted to an *immutable log*.
101

    
102
The accounting system is a generic event-processing engine that is configured by a
103
DSL. The DSL is mostly based on the
104
`YAML <http://en.wikipedia.org/wiki/Yaml>`_ 
105
format. The DSL supports limited algorithm definitions through integration of the Javascript language as defined below.
106

    
107
Glossary of Entities
108
^^^^^^^^^^^^^^^^^^^^
109

    
110
- *Credit*: A credit is the unit of currency used in Aquarium. It may or may not 
111
  correspond to real money.
112
- *Resource*: A resource represents an entity that can be charged for its usage. The 
113
  currently charged resources are: Time of VM usage, bytes uploaded and downloaded and bytes used for storage
114
- *Resource Event*: A resource event is generated from an external source and are permanently appended in an immutable event log. A raw event carries information about changes in an external system that could affect the status of a user's wallet (See more about `Resource Events`_).
115
- *AccountingEntry*: An accounting entry is the result of processing a resource event and is what gets stored to the user's wallet.
116
- *Price List*: A price list contains information of the cost of a resource. 
117
  A pricelist is only applied within a specified time frame.
118
- *Algorithm*: An algorithm specifies the way the charging calculation is done. It can be vary  depending on resource usage, time of raw event or other information.
119
- *Credit Plan*: Defines a periodic operation of refiling a user's wallet with a
120
  configurable amount of credits.
121
- *Agreement*: An agreement associates pricelists with algorithms and credit
122
  plans. An agreement is assigned to one or more users/credit holders.
123
- *Billing Period*: A billing period defines a recurring timeslot at the end
124
  of which the accumulated resource usage is accounted for and reset.
125

    
126
Overall Schema
127
^^^^^^^^^^^^^^
128

    
129
The Aquarium policy DSL allows the hierarchical definition of agreements, by
130
means of compositing ingredients and specifying validity periods for individual
131
components or for the policies themselves. The DSL also allows overriding
132
between items of the same class (i.e. an algorithm definition can override
133
certain fields of another algorithm definition, while both definitions can 
134
be referenced individually). 
135

    
136
The top-level schema for the DSL is as follows.
137

    
138
.. code-block:: yaml
139

    
140
  aquariumpolicy:
141
    resources:
142
      - resource:
143
        ... [see Resources]
144

    
145
    algorithms:
146
      - algorithm:
147
        ... [see Algorithms]
148

    
149
    pricelists:
150
      - pricelist:
151
        ... [see Pricelists]
152

    
153
    creditplans:
154
      - creditplan:
155
        ... [see Creditplans]
156

    
157
    agreements:
158
      - agreement:
159
        ... [see Agreements]
160

    
161

    
162
Time frames
163
^^^^^^^^^^^
164

    
165
Time frames allow the specification of applicability periods for algorithms,
166
pricelists and agreements. A timeframe is by default continuous and has a
167
starting point; if there is no ending point, the timeframe is considered open
168
and its ending point is the time at the time of evaluation. 
169

    
170
A time frame definition can contain repeating time ranges that dissect it and
171
consequently constrain the applicability of the time frame to the defined
172
ranges only. A range always has a start and end point. A range is repeated
173
within a timeframe, until the timeframe end point is reached. In case a
174
repeating range ends later than the containing timeframe, the ending time is
175
adjusted to match that of the timeframe.
176

    
177
The definition of the starting and ending point of a time range is done in a 
178
syntax reminisent of the `cron <http://en.wikipedia.org/wiki/Cron>`_ format. 
179

    
180
.. code-block:: yaml
181

    
182
  effective:
183
    from: %d                         # Milliseconds since the epoch
184
    to:  %d                          # [opt] Milliseconds since the epoch
185
    repeat:                          # [opt] Defines a repetion list
186
      - every:                       # [opt] A repetion entry 
187
        start: "min hr dom moy dow"  # 5-elem cron string
188
        end:   "min hr dom moy dow"  # 5-elem cron string 
189

    
190

    
191
The following declaration defines a timeframe starting at the designated
192
timestamp and ending at the time of evaluation.
193

    
194
.. code-block:: yaml
195

    
196
  effective:
197
    from: 1293703200  #(30/12/2010 10:00)
198

    
199
The following declaration defines a timeframe of one year, within which the
200
applicability of the specified policy, agreement or pricelist is constrained to
201
time ranges from 12:00 Mon to 14:00 Fri  (first ``every`` definition)
202
and 15:00 Sat to 15:00 Sun.
203

    
204
.. code-block:: yaml
205

    
206
  effective:
207
    from: 1293703200  #(30/12/2010 10:00)
208
    to:   1325239200  #(30/12/2011 10:00)
209
    repeat:
210
      - every:
211
        start: "00 12 * * Mon"
212
        end:   "00 14 * * Fri"
213
      - every:
214
        start: "00 15 * * Sat"
215
        end:   "00 15 * * Sun"
216

    
217
Resources
218
^^^^^^^^^
219

    
220
A resource represents an entity that can be charged for. Aquarium does not
221
assume a fixed set of resource types and is extensible to any number of
222
resources. A resource has a ``name`` and a ``unit``; both are free form
223
strings. The resource name is used to uniquely identify the resource both inside
224
Aquarium and among external systems.
225

    
226
A resource definition also has a two fields that define how a resource is
227
charged and whether a user can be assigned more instances of a resource.
228
Specifically, the ``costpolicy`` field can have the following values:
229

    
230
- `continuous:` For ``continuous`` resources, the charging algorithm calculates the
231
  total amount of resource usage over time, per billing period. Each new
232
  resource event modifies the resource usage counter and forces Aquarium
233
  to calculate a new cost for the previous amount of resource usage. A typical
234
  example  of a continuous resource is disk space.
235
- `onoff:` ``onoff`` resources are a category of continuous resources where the
236
  resource can only be in two states, on or off. In such cases, maintaining a usage
237
  counter is not necessary; the charging algorithm uses time as the unit of
238
  calculation. Virtual machine time is a typical example.
239
- `discrete:` ``discrete`` resources are charged for instantly for the
240
  reported resource value. Examples are bandwidth and every resource whose usage
241
  is not a function of time (books, hits to an API etc). 
242

    
243
Regarding resource complexity, a resource can either be labeled complex 
244
or not. In the former case, a resource can have more than one instances per
245
user, and resource usage is tracked individually per instance. The 
246
``instance-id`` field in the resource event message (See `Resource Events`_) 
247
helps Aquarium separate resource instances at charge time. 
248

    
249
The following resource definition defines the `bandwidthup` 
250
resource. 
251

    
252
.. code-block:: yaml
253

    
254
  resource:
255
    name: bandwidthup
256
    unit: MB/hr
257
    complex: false
258
    costpolicy: discrete
259

    
260
Algorithms
261
^^^^^^^^^^
262

    
263
An algorithm specifies the algorithm used to perform the cost calculation, by
264
combining the reported resource usage with the applicable pricelist. As opposed
265
to price lists, algorithms define behaviours, which have certain
266
validity periods. 
267

    
268
.. code-block:: yaml
269

    
270
  algorithm:
271
    name: default
272
    bandwidthup:   {price} times {volume} 
273
    bandwidthdown: {price} times {volume}
274
    vmtime: {price} times {volume}
275
    diskspace: {price} times {volume}
276
    effective: 
277
      [see Time frames]
278

    
279
Price lists
280
^^^^^^^^^^^
281

    
282
A price list defines the prices applicable for a resource within a validity
283
period. Prices are attached to resource types and denote the policies that
284
should be deducted from an entity's wallet in response to the entity's resource
285
usage within a given charging period (currently, a month). The format is the
286
following:
287

    
288
.. code-block:: yaml
289

    
290
  pricelist:                  # Pricelist structure definition  
291
    name: apricelist          # Name for the price list, no spaces, must be unique
292
    [extends: anotherpl]      # [Optional] Inheritance operation: all optional fields  
293
                              # are inherited from the named pricelist
294
    bandwidthup:              # Price for used upstream bandwidth per MB 
295
    bandwidthdown:            # Price for used downstream bandwidth per MB
296
    vmtime:                   # Price for time 
297
    diskspace:                # Price for used diskspace, per MB
298
    effective:
299
      [see Timeframe format]
300

    
301
Credit Plans
302
^^^^^^^^^^^^
303

    
304
Credit plans define how user accounts are refilled with credits.  Apart from
305
the usual ``name`` and ``effective`` attributes, a credit plan has an ``at``
306
attribute (a five-field Cron string) which defines how offen the refilling
307
operation will run and a ``credits`` attribute which defines the number of
308
credits to add to the user's wallet.
309

    
310
.. code-block:: yaml
311

    
312
  creditplan:
313
    name: default
314
    credits: 100
315
    at: "00 00 1 * *"
316
    effective:
317
      from: 0
318

    
319
Agreements
320
^^^^^^^^^^
321

    
322
An agreement is the result of combining an with algorithm with a pricelist
323
and a creditplan. As the
324
accounting DSL's main purpose is to facilitate the construction of agreements
325
(which are then associated to users), the agreement is the centerpiece of
326
the language. An agreement is defined in full using the following template:
327

    
328
.. code-block:: yaml
329

    
330
  agreement:
331
    name: someuniqname        # Unique name for 
332
    extends: other            # [opt] name of inhereted agreement 
333
    pricelist: plname         # Name of declared pricelist
334
      resourse: value         # [opt] Overiding of price for resource
335
    algorithm: polname           # Name of declared policy
336
      resourse: value         # [opt] Overiding of algorithm for resourse
337

    
338
An agreement definition can either reuse the pricelists, algorithms and creditplans 
339
defined above (referenced by name) or define the effective algorithm or pricelist
340
in place.
341
If a ``pricelist`` or ``algorithm`` name has not been defined explicitely (and
342
therefore referenced by name), all prices or algorithms for the declared
343
resources must be defined in either the  ``agreement`` or one of its parents.
344

    
345
As with all DSL resources, agreements can be overriden by other agreements.
346

    
347
Examples
348
^^^^^^^^^
349
.. toctree::
350

    
351
  unicase 
352

    
353

    
354
Events
355
------
356

    
357
Aquarium communicates with external systems through events published on an `AMQP <http://en.wikipedia.org/wiki/AMQP>`_ queue. Aquarium only understands events in the
358
`JSON <http://www.json.org/>`_ format.
359

    
360
Aquarium events share a common base format consisting of the following fields:
361

    
362
.. code-block:: javascript
363

    
364
  {
365
    id: "SHA-1",
366
    occurredMillis: 12345,
367
    receivedMillis: 12346 
368
  }
369

    
370
- *id:* [``string``] A per message unique string. Should be able to identify messages of the same type uniquely across Aquarium clients. Preferably a SHA-1.
371
-  *occurredMillis:* [``long``] The timestamp at the event creation time. In milliseconds since the epoch.
372
- *receivedMillis:* [``long``] For Aquarium internal use. Clients should not set a value. If a value is set, it will be overwritten upon receipt.
373

    
374
In the following sections, we describe the exact format of each one of the concrete messages that Aquarium can process.
375

    
376
Resource Events
377
^^^^^^^^^^^^^^^
378

    
379
A resource event is sent by Aquarium clients to signify a change in a resource's
380
state. This change is processed by Aquarium's accounting system according to 
381
the provisions of the configured policy in order to create entries to the user's
382
wallet.
383

    
384
.. code-block:: javascript
385

    
386
  {
387
    id: "<SHA-1>",
388
    occurredMillis: 1321020852,
389
    receivedMillis: 1321020852,
390
    clientID: "platform-wide-unique-ID",
391
    userID: "administrator@admin.grnet.gr",
392
    resource: "vmtime",
393
    instanceId: "vmtime-01.02.123X.Z",
394
    eventVersion: "1.0", 
395
    value: 0.3,
396
    details: {
397
      keyA: "value1",
398
      keyB: "value2",
399
    }
400
  }
401

    
402
The meaning of the fields is as follows:
403

    
404
- *id:* As above.
405
-  *occurredMillis:* As above.
406
- *receivedMillis:* As above. 
407
- *clientID:* ``string`` A unique name for each message producer.
408
- *userID:* ``string`` The ID of the user that will be charged for the resource usage details reported in the resource event. 
409
- *resource* ``string`` The name of the resource as declared in the Aquarium DSL. See `Resources`_ for more. 
410
- *instanceId* ``string`` If the resource is complex, then this field is set to a unique identifier for the specific instance of the resource. In case of a non-complex resource, Aquarium does not examine this value.
411
- *eventVersion* ``string`` The event version. Currently fixed to "1". 
412
- *value*: ``double`` The value of resource usage. Depends on the cost policy defined for the resource as follows:
413
   + For ``continuous`` resources, the value indicates the amount of resource usage since the last resource event for the specific resource.
414
   + For ``onoff`` resources, it is set to 1 when the resource is actively used and to 0 when the resource usage has stopped.
415
   + For ``discrete`` resources, the field indicates the amount of resource usage at the time of the event.
416
- *details*: ``map[string, string]`` A map/dictionary indicating extra metadata for this resource event. Aquarium does not process this metadata. The field must always be present, even if it is empty.
417

    
418
User Event
419
^^^^^^^^^^
420

    
421
A user event is sent by an external identity provider system to signify
422
changes in user states. The message format is the following:
423

    
424
.. code-block:: javascript
425

    
426
   {
427
    id: "<SHA-1>",
428
    occurredMillis: 1321020852,
429
    receivedMillis: 1321020852,
430
    clientID: "platform-wide-unique-ID",
431
    userID: "administrator@admin.grnet.gr",
432
    isActive: "true",
433
    role: "STUDENT",
434
    eventVersion: "1", 
435
    eventType: "ACTIVE",
436
    details: { }
437
  }
438

    
439
The meaning of the fields is as follows:
440

    
441
- *id:* As above.
442
-  *occurredMillis:* As above.
443
- *receivedMillis:* As above. 
444
- *clientID:* ``string`` A unique name for each message producer.
445
- *userID:* ``string`` The ID of the user whom this event concerns 
446
- *isActive* ``boolean`` Whether the user is active or not (allowed values are
447
  ``true`` or ``false``)
448
- *eventVersion* ``string`` The event version. Currently fixed to "1". 
449
- *role* ``string`` The role of the user. If different than the role currently
450
  stored, the role will be changed.
451
- *eventType* ``string (ACTIVE/SUSPENDED)`` The requested change to the user
452
  profile. 
453
- *details*: ``map[string, string]`` A map/dictionary indicating extra metadata for this resource event. Aquarium does not process this metadata. The field must always be present, even if it is empty.
454

    
455

    
456
The charging algorithm
457
----------------------
458

    
459

    
460
The Aquarium REST API
461
---------------------
462

    
463
The Aquarium REST API is used to query a 
464

    
465
As Aquarium is a backend system, clients are trusted and therefore no
466
authentication is required for accessing Aquarium's API.
467

    
468
Get User Balance
469
^^^^^^^^^^^^^^^^
470

    
471
**GET** /user/*id*/balance
472

    
473
**Normal Response Code**: 200
474

    
475
**Error Response Codes**: itemNotFound (404), timeout (500) 
476

    
477
The operation returns the current balance for a user. 
478

    
479
**Example get balance response**
480

    
481
.. code-block:: javascript
482

    
483
  {
484
    userId: "1234"
485
    balance: "321,32"
486
  }
487

    
488

    
489
Document Revisions
490
------------------
491

    
492
==================    ================================
493
Revision              Description
494
==================    ================================
495
0.1 (Nov 2, 2011)     Initial release. Credit and debit policy descriptions 
496
0.2 (Feb 23, 2012)    Update definitions, remove company use case
497
0.3 (Feb 28, 2012)    Event and resource descriptions
498
==================    ================================
499

    
500