File: pyscripts.rst

package info (click to toggle)
cloudkitty 23.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,528 kB
  • sloc: python: 21,803; sh: 528; makefile: 226; pascal: 54
file content (138 lines) | stat: -rw-r--r-- 7,417 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
=======================
PyScripts rating module
=======================

The PyScripts module allows you to create your own rating module.
A script is supposed to process the given data and to set the
different prices.

CAUTION: If you add several PyScripts, the order in which they will be executed
is not guaranteed.

Custom module example
=====================

Price definitions
-----------------

.. code-block:: python

    import decimal


    # Price for each flavor. These are equivalent to hashmap field mappings.
    flavors = {
        'm1.micro': decimal.Decimal(0.65),
        'm1.nano': decimal.Decimal(0.35),
        'm1.large': decimal.Decimal(2.67)
    }

    # Price per MB / GB for images and volumes. These are equivalent to
    # hashmap service mappings.
    image_mb_price = decimal.Decimal(0.002)
    volume_gb_price = decimal.Decimal(0.35)


Price calculation functions
---------------------------

.. code-block:: python

    # These functions return the price of a service usage on a collect period.
    # The price is always equivalent to the price per unit multiplied by
    # the quantity.
    def get_instance_price(item):
        if not item['metadata']['flavor_name'] in flavors:
            return 0
        else:
            return (decimal.Decimal(item['vol']['qty'])
                   * flavors[item['metadata']['flavor_name']])

    def get_image_price(item):
        if not item['vol']['qty']:
            return 0
        else:
            return decimal.Decimal(item['vol']['qty']) * image_mb_price


    def get_volume_price(item):
        if not item['vol']['qty']:
            return 0
        else:
            return decimal.Decimal(item['vol']['qty']) * volume_gb_price

    # Mapping each service to its price calculation function
    services = {
        'instance': get_instance_price,
        'volume': get_volume_price,
        'image': get_image_price
    }

Processing the data
-------------------

.. code-block:: python

    def process(data):
        # The 'data' is a dictionary with the usage entries for each service
        # in a given period.
        usage_data = data['usage']

        for service_name, service_data in usage_data.items():
            # Do not calculate the price if the service has no
            # price calculation function
            if service_name in services.keys():
                # A service can have several items. For example,
                # each running instance is an item of the compute service
                for item in service_data:
                    item['rating'] = {'price': services[service_name](item)}
        return data


    # 'data' is passed as a global variable. The script is supposed to set the
    # 'rating' element of each item in each service
    data = process(data)


Using your Script for rating
============================

Enabling the PyScripts module
-----------------------------

To use your script for rating, you will need to enable the pyscripts module

.. code-block:: console

    $ cloudkitty module enable pyscripts
    +-----------+---------+----------+
    | Module    | Enabled | Priority |
    +-----------+---------+----------+
    | pyscripts | True    |        1 |
    +-----------+---------+----------+

Adding the script to CloudKitty
-------------------------------

Create the script and specify its name, description, start and end dates.
If the ``start`` and ``end`` are not given, the ``start`` will be set as the
creation date and the ``end`` as ``None``. The script is valid from the
``start`` time until the ``end`` time, if the ``end`` time is ``None``, the
script is endless.

.. code-block:: console

    $ cloudkitty pyscript create my_awesome_script script.py
    +-------------------+--------------------------------------+---------------------+---------------------+------+-------------+---------+----------------------------------+------------+------------+------------------------------------------+---------------------------------------+
    | Name              | Script ID                            | Created At          | Start               | End  | Description | Deleted | Created By                       | Updated By | Deleted By | Checksum                                 | Data                                  |
    +-------------------+--------------------------------------+---------------------+---------------------+------+-------------+---------+----------------------------------+------------+------------+------------------------------------------+---------------------------------------+
    | my_awesome_script | 78e1955a-4e7e-47e3-843c-524d8e6ad4c4 | 2023-01-01T10:00:00 | 2023-01-01T10:00:00 | None | None        | None    | 7977999e2e2511e6a8b2df30b233ffcb | None       | None       | 49e889018eb86b2035437ebb69093c0b6379f18c | from __future__ import print_function |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          | from cloudkitty import rating         |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          |                                       |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          | import decimal                        |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          |                                       |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          |         {...}                         |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          |                                       |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          | data = process(data)                  |
    |                   |                                      |                     |                     |      |             |         |                                  |            |            |                                          |                                       |
    +-------------------+--------------------------------------+---------------------+---------------------+------+-------------+---------+----------------------------------+------------+------------+------------------------------------------+---------------------------------------+