root / snf-pithos-app / pithos / api / management / commands / pithos-usage.py @ 8108c68c
History | View | Annotate | Download (7.9 kB)
1 | 4c03c942 | Sofia Papagiannaki | # Copyright 2012 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 4c03c942 | Sofia Papagiannaki | #
|
3 | 4c03c942 | Sofia Papagiannaki | # Redistribution and use in source and binary forms, with or
|
4 | 4c03c942 | Sofia Papagiannaki | # without modification, are permitted provided that the following
|
5 | 4c03c942 | Sofia Papagiannaki | # conditions are met:
|
6 | 4c03c942 | Sofia Papagiannaki | #
|
7 | 4c03c942 | Sofia Papagiannaki | # 1. Redistributions of source code must retain the above
|
8 | 4c03c942 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
9 | 4c03c942 | Sofia Papagiannaki | # disclaimer.
|
10 | 4c03c942 | Sofia Papagiannaki | #
|
11 | 4c03c942 | Sofia Papagiannaki | # 2. Redistributions in binary form must reproduce the above
|
12 | 4c03c942 | Sofia Papagiannaki | # copyright notice, this list of conditions and the following
|
13 | 4c03c942 | Sofia Papagiannaki | # disclaimer in the documentation and/or other materials
|
14 | 4c03c942 | Sofia Papagiannaki | # provided with the distribution.
|
15 | 4c03c942 | Sofia Papagiannaki | #
|
16 | 4c03c942 | Sofia Papagiannaki | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 4c03c942 | Sofia Papagiannaki | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 4c03c942 | Sofia Papagiannaki | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 4c03c942 | Sofia Papagiannaki | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 4c03c942 | Sofia Papagiannaki | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 4c03c942 | Sofia Papagiannaki | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 4c03c942 | Sofia Papagiannaki | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 4c03c942 | Sofia Papagiannaki | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 4c03c942 | Sofia Papagiannaki | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 4c03c942 | Sofia Papagiannaki | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 4c03c942 | Sofia Papagiannaki | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 4c03c942 | Sofia Papagiannaki | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 4c03c942 | Sofia Papagiannaki | #
|
29 | 4c03c942 | Sofia Papagiannaki | # The views and conclusions contained in the software and
|
30 | 4c03c942 | Sofia Papagiannaki | # documentation are those of the authors and should not be
|
31 | 4c03c942 | Sofia Papagiannaki | # interpreted as representing official policies, either expressed
|
32 | 4c03c942 | Sofia Papagiannaki | # or implied, of GRNET S.A.
|
33 | 4c03c942 | Sofia Papagiannaki | |
34 | 4c03c942 | Sofia Papagiannaki | from django.core.management.base import NoArgsCommand, CommandError |
35 | 4c03c942 | Sofia Papagiannaki | |
36 | 4c03c942 | Sofia Papagiannaki | from collections import namedtuple |
37 | 384dee7e | Sofia Papagiannaki | from optparse import make_option |
38 | 4c03c942 | Sofia Papagiannaki | from sqlalchemy import func |
39 | 4c03c942 | Sofia Papagiannaki | from sqlalchemy.sql import select, and_, or_ |
40 | 4c03c942 | Sofia Papagiannaki | |
41 | 4c03c942 | Sofia Papagiannaki | from pithos.api.util import get_backend |
42 | 4c03c942 | Sofia Papagiannaki | from pithos.backends.modular import ( |
43 | 4c03c942 | Sofia Papagiannaki | CLUSTER_NORMAL, CLUSTER_HISTORY, CLUSTER_DELETED |
44 | 4c03c942 | Sofia Papagiannaki | ) |
45 | 4c03c942 | Sofia Papagiannaki | clusters = (CLUSTER_NORMAL, CLUSTER_HISTORY, CLUSTER_DELETED) |
46 | 4c03c942 | Sofia Papagiannaki | |
47 | 989576a6 | Sofia Papagiannaki | Usage = namedtuple('Usage', ('node', 'path', 'size', 'cluster')) |
48 | 989576a6 | Sofia Papagiannaki | GetQuota = namedtuple('GetQuota', ('entity', 'resource', 'key')) |
49 | 4c03c942 | Sofia Papagiannaki | |
50 | 3e1b20d6 | Sofia Papagiannaki | class ResetHoldingPayload(namedtuple('ResetHoldingPayload', ( |
51 | 3e1b20d6 | Sofia Papagiannaki | 'entity', 'resource', 'key', 'imported', 'exported', 'returned', 'released' |
52 | 3e1b20d6 | Sofia Papagiannaki | ))): |
53 | 3e1b20d6 | Sofia Papagiannaki | __slots__ = () |
54 | 3e1b20d6 | Sofia Papagiannaki | |
55 | 3e1b20d6 | Sofia Papagiannaki | def __str__(self): |
56 | 3e1b20d6 | Sofia Papagiannaki | return '%s: %s' % (self.entity, self.imported) |
57 | 3e1b20d6 | Sofia Papagiannaki | |
58 | 3e1b20d6 | Sofia Papagiannaki | |
59 | 09e69b8a | Georgios D. Tsoukalas | ENTITY_KEY = '1'
|
60 | 4c03c942 | Sofia Papagiannaki | |
61 | 4c03c942 | Sofia Papagiannaki | backend = get_backend() |
62 | 4c03c942 | Sofia Papagiannaki | table = {} |
63 | 4c03c942 | Sofia Papagiannaki | table['nodes'] = backend.node.nodes
|
64 | 4c03c942 | Sofia Papagiannaki | table['versions'] = backend.node.versions
|
65 | 6c997921 | Sofia Papagiannaki | table['policy'] = backend.node.policy
|
66 | 4c03c942 | Sofia Papagiannaki | conn = backend.node.conn |
67 | 4c03c942 | Sofia Papagiannaki | |
68 | 3e1b20d6 | Sofia Papagiannaki | def _retrieve_user_nodes(users=()): |
69 | 3e1b20d6 | Sofia Papagiannaki | s = select([table['nodes'].c.path, table['nodes'].c.node]) |
70 | 3e1b20d6 | Sofia Papagiannaki | s = s.where(and_(table['nodes'].c.node != 0, |
71 | 3e1b20d6 | Sofia Papagiannaki | table['nodes'].c.parent == 0)) |
72 | 3e1b20d6 | Sofia Papagiannaki | if users:
|
73 | 3e1b20d6 | Sofia Papagiannaki | s = s.where(table['nodes'].c.path.in_(users))
|
74 | 3e1b20d6 | Sofia Papagiannaki | return conn.execute(s).fetchall()
|
75 | 09e69b8a | Georgios D. Tsoukalas | |
76 | 989576a6 | Sofia Papagiannaki | def _compute_usage(nodes): |
77 | 989576a6 | Sofia Papagiannaki | usage = [] |
78 | 989576a6 | Sofia Papagiannaki | append = usage.append |
79 | 4c03c942 | Sofia Papagiannaki | for path, node in nodes: |
80 | 4c03c942 | Sofia Papagiannaki | select_children = select( |
81 | 09e69b8a | Georgios D. Tsoukalas | [table['nodes'].c.node]).where(table['nodes'].c.parent == node) |
82 | 4c03c942 | Sofia Papagiannaki | select_descendants = select([table['nodes'].c.node]).where(
|
83 | 4c03c942 | Sofia Papagiannaki | or_(table['nodes'].c.parent.in_(select_children),
|
84 | 4c03c942 | Sofia Papagiannaki | table['nodes'].c.node.in_(select_children)))
|
85 | 4c03c942 | Sofia Papagiannaki | s = select([table['versions'].c.cluster,
|
86 | 4c03c942 | Sofia Papagiannaki | func.sum(table['versions'].c.size)])
|
87 | 4c03c942 | Sofia Papagiannaki | s = s.group_by(table['versions'].c.cluster)
|
88 | 4c03c942 | Sofia Papagiannaki | s = s.where(table['nodes'].c.node == table['versions'].c.node) |
89 | 4c03c942 | Sofia Papagiannaki | s = s.where(table['nodes'].c.node.in_(select_descendants))
|
90 | 9c0c8aa9 | Sofia Papagiannaki | s = s.where(table['versions'].c.cluster == CLUSTER_NORMAL)
|
91 | 4c03c942 | Sofia Papagiannaki | d2 = dict(conn.execute(s).fetchall())
|
92 | d776b3c3 | Sofia Papagiannaki | |
93 | 9c0c8aa9 | Sofia Papagiannaki | try:
|
94 | 9c0c8aa9 | Sofia Papagiannaki | size = d2[CLUSTER_NORMAL] |
95 | 9c0c8aa9 | Sofia Papagiannaki | except KeyError: |
96 | 9c0c8aa9 | Sofia Papagiannaki | size = 0
|
97 | 989576a6 | Sofia Papagiannaki | append(Usage( |
98 | 9c0c8aa9 | Sofia Papagiannaki | node=node, |
99 | 9c0c8aa9 | Sofia Papagiannaki | path=path, |
100 | 9c0c8aa9 | Sofia Papagiannaki | size=size, |
101 | 9c0c8aa9 | Sofia Papagiannaki | cluster=CLUSTER_NORMAL)) |
102 | 989576a6 | Sofia Papagiannaki | return usage
|
103 | 989576a6 | Sofia Papagiannaki | |
104 | 989576a6 | Sofia Papagiannaki | def _get_quotaholder_usage(usage): |
105 | 989576a6 | Sofia Papagiannaki | payload = [] |
106 | 989576a6 | Sofia Papagiannaki | append = payload.append |
107 | 989576a6 | Sofia Papagiannaki | [append(GetQuota( |
108 | 989576a6 | Sofia Papagiannaki | entity=item.path, |
109 | 989576a6 | Sofia Papagiannaki | resource='pithos+.diskspace',
|
110 | 989576a6 | Sofia Papagiannaki | key=ENTITY_KEY |
111 | 989576a6 | Sofia Papagiannaki | )) for item in usage] |
112 | 989576a6 | Sofia Papagiannaki | |
113 | 989576a6 | Sofia Papagiannaki | result = backend.quotaholder.get_quota( |
114 | 989576a6 | Sofia Papagiannaki | context={}, clientkey='pithos', get_quota=payload
|
115 | 989576a6 | Sofia Papagiannaki | ) |
116 | 989576a6 | Sofia Papagiannaki | return dict((entity, imported - exported + returned - released) for ( |
117 | 989576a6 | Sofia Papagiannaki | entity, resource, quantity, capacity, import_limit, export_limit, |
118 | 989576a6 | Sofia Papagiannaki | imported, exported, returned, released, flags |
119 | 989576a6 | Sofia Papagiannaki | ) in result)
|
120 | 989576a6 | Sofia Papagiannaki | |
121 | 989576a6 | Sofia Papagiannaki | |
122 | 989576a6 | Sofia Papagiannaki | def _prepare_reset_holding(usage, only_diverging=False): |
123 | 989576a6 | Sofia Papagiannaki | """Verify usage and set quotaholder user usage"""
|
124 | a7447c76 | Sofia Papagiannaki | reset_holding = [] |
125 | a7447c76 | Sofia Papagiannaki | append = reset_holding.append |
126 | 989576a6 | Sofia Papagiannaki | |
127 | 989576a6 | Sofia Papagiannaki | quotaholder_usage = {} |
128 | 989576a6 | Sofia Papagiannaki | if only_diverging:
|
129 | 989576a6 | Sofia Papagiannaki | quotaholder_usage = _get_quotaholder_usage(usage) |
130 | 989576a6 | Sofia Papagiannaki | |
131 | 989576a6 | Sofia Papagiannaki | for item in(usage): |
132 | 989576a6 | Sofia Papagiannaki | if only_diverging and quotaholder_usage.get(item.path) == item.size: |
133 | 989576a6 | Sofia Papagiannaki | continue
|
134 | 989576a6 | Sofia Papagiannaki | |
135 | 6674f31d | Sofia Papagiannaki | if item.cluster == CLUSTER_NORMAL:
|
136 | 6674f31d | Sofia Papagiannaki | append(ResetHoldingPayload( |
137 | 6674f31d | Sofia Papagiannaki | entity=item.path, |
138 | 6674f31d | Sofia Papagiannaki | resource='pithos+.diskspace',
|
139 | 6674f31d | Sofia Papagiannaki | key=ENTITY_KEY, |
140 | 6674f31d | Sofia Papagiannaki | imported=item.size, |
141 | 6674f31d | Sofia Papagiannaki | exported=0,
|
142 | 6674f31d | Sofia Papagiannaki | returned=0,
|
143 | 6674f31d | Sofia Papagiannaki | released=0))
|
144 | a7447c76 | Sofia Papagiannaki | return reset_holding
|
145 | d776b3c3 | Sofia Papagiannaki | |
146 | d776b3c3 | Sofia Papagiannaki | |
147 | 4c03c942 | Sofia Papagiannaki | class Command(NoArgsCommand): |
148 | 3e1b20d6 | Sofia Papagiannaki | help = "List and reset pithos usage"
|
149 | 4c03c942 | Sofia Papagiannaki | |
150 | 384dee7e | Sofia Papagiannaki | option_list = NoArgsCommand.option_list + ( |
151 | 3e1b20d6 | Sofia Papagiannaki | make_option('--list',
|
152 | 3e1b20d6 | Sofia Papagiannaki | dest='list',
|
153 | 3e1b20d6 | Sofia Papagiannaki | action="store_true",
|
154 | 3e1b20d6 | Sofia Papagiannaki | default=True,
|
155 | 3e1b20d6 | Sofia Papagiannaki | help="List usage for all or specified user"),
|
156 | 3e1b20d6 | Sofia Papagiannaki | make_option('--reset',
|
157 | 3e1b20d6 | Sofia Papagiannaki | dest='reset',
|
158 | 3e1b20d6 | Sofia Papagiannaki | action="store_true",
|
159 | 3e1b20d6 | Sofia Papagiannaki | default=False,
|
160 | 3e1b20d6 | Sofia Papagiannaki | help="Reset usage for all or specified users"),
|
161 | 989576a6 | Sofia Papagiannaki | make_option('--diverging',
|
162 | 989576a6 | Sofia Papagiannaki | dest='diverging',
|
163 | 9c0c8aa9 | Sofia Papagiannaki | action="store_true",
|
164 | 9c0c8aa9 | Sofia Papagiannaki | default=False,
|
165 | 989576a6 | Sofia Papagiannaki | help=("List or reset diverging usages")),
|
166 | 3e1b20d6 | Sofia Papagiannaki | make_option('--user',
|
167 | 3e1b20d6 | Sofia Papagiannaki | dest='users',
|
168 | 384dee7e | Sofia Papagiannaki | action='append',
|
169 | 3e1b20d6 | Sofia Papagiannaki | metavar='USER_UUID',
|
170 | 8108c68c | Sofia Papagiannaki | help=("Specify which users --list or --reset applies."
|
171 | 8108c68c | Sofia Papagiannaki | "This option can be repeated several times."
|
172 | 989576a6 | Sofia Papagiannaki | "If no user is specified --list or --reset will be applied globally.")),
|
173 | 384dee7e | Sofia Papagiannaki | ) |
174 | 384dee7e | Sofia Papagiannaki | |
175 | 4c03c942 | Sofia Papagiannaki | def handle_noargs(self, **options): |
176 | 4c03c942 | Sofia Papagiannaki | try:
|
177 | 989576a6 | Sofia Papagiannaki | user_nodes = _retrieve_user_nodes(options['users'])
|
178 | 989576a6 | Sofia Papagiannaki | if not user_nodes: |
179 | 989576a6 | Sofia Papagiannaki | raise CommandError('No users found.') |
180 | 989576a6 | Sofia Papagiannaki | usage = _compute_usage(user_nodes) |
181 | 989576a6 | Sofia Papagiannaki | reset_holding = _prepare_reset_holding( |
182 | 989576a6 | Sofia Papagiannaki | usage, only_diverging=options['diverging']
|
183 | 989576a6 | Sofia Papagiannaki | ) |
184 | 989576a6 | Sofia Papagiannaki | |
185 | 3e1b20d6 | Sofia Papagiannaki | if options['list']: |
186 | 3e1b20d6 | Sofia Papagiannaki | print '\n'.join([str(i) for i in reset_holding]) |
187 | 3e1b20d6 | Sofia Papagiannaki | |
188 | 3e1b20d6 | Sofia Papagiannaki | if options['reset']: |
189 | 3e1b20d6 | Sofia Papagiannaki | if not backend.quotaholder_enabled: |
190 | 3e1b20d6 | Sofia Papagiannaki | raise CommandError('Quotaholder component is not enabled') |
191 | 3e1b20d6 | Sofia Papagiannaki | |
192 | 3e1b20d6 | Sofia Papagiannaki | if not backend.quotaholder_url: |
193 | 3e1b20d6 | Sofia Papagiannaki | raise CommandError('Quotaholder url is not set') |
194 | 3e1b20d6 | Sofia Papagiannaki | |
195 | 3e1b20d6 | Sofia Papagiannaki | if not backend.quotaholder_token: |
196 | 3e1b20d6 | Sofia Papagiannaki | raise CommandError('Quotaholder token is not set') |
197 | 3e1b20d6 | Sofia Papagiannaki | |
198 | 3e1b20d6 | Sofia Papagiannaki | while True: |
199 | 3e1b20d6 | Sofia Papagiannaki | result = backend.quotaholder.reset_holding( |
200 | 3e1b20d6 | Sofia Papagiannaki | context={}, |
201 | 3e1b20d6 | Sofia Papagiannaki | clientkey='pithos',
|
202 | 3e1b20d6 | Sofia Papagiannaki | reset_holding=reset_holding) |
203 | 3e1b20d6 | Sofia Papagiannaki | |
204 | 3e1b20d6 | Sofia Papagiannaki | if not result: |
205 | 3e1b20d6 | Sofia Papagiannaki | break
|
206 | 3e1b20d6 | Sofia Papagiannaki | |
207 | 3e1b20d6 | Sofia Papagiannaki | missing_entities = [reset_holding[x].entity for x in result] |
208 | 3e1b20d6 | Sofia Papagiannaki | self.stdout.write(
|
209 | 3e1b20d6 | Sofia Papagiannaki | 'Unknown quotaholder users: %s\n' %
|
210 | 3e1b20d6 | Sofia Papagiannaki | ', '.join(missing_entities))
|
211 | 3e1b20d6 | Sofia Papagiannaki | m = 'Retrying sending quota usage for the rest...\n'
|
212 | 3e1b20d6 | Sofia Papagiannaki | self.stdout.write(m)
|
213 | 3e1b20d6 | Sofia Papagiannaki | missing_indexes = set(result)
|
214 | 3e1b20d6 | Sofia Papagiannaki | reset_holding = [x for i, x in enumerate(reset_holding) |
215 | 3e1b20d6 | Sofia Papagiannaki | if i not in missing_indexes] |
216 | d776b3c3 | Sofia Papagiannaki | finally:
|
217 | 4c03c942 | Sofia Papagiannaki | backend.close() |