Revision ccfbf77b
b/snf-cyclades-app/synnefo/quotas/__init__.py | ||
---|---|---|
148 | 148 |
try: |
149 | 149 |
serial = qh.issue_one_commission(ASTAKOS_TOKEN, |
150 | 150 |
user, source, provisions, |
151 |
force, auto_accept)
|
|
151 |
force=force, auto_accept=auto_accept)
|
|
152 | 152 |
except QuotaLimit as e: |
153 | 153 |
msg, details = render_overlimit_exception(e) |
154 | 154 |
raise faults.OverLimit(msg, details=details) |
/dev/null | ||
---|---|---|
1 |
# Copyright 2012, 2013 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
from django.core.management.base import BaseCommand |
|
35 |
from optparse import make_option |
|
36 |
|
|
37 |
from synnefo.quotas import Quotaholder |
|
38 |
from synnefo.quotas.util import get_db_holdings |
|
39 |
|
|
40 |
|
|
41 |
class Command(BaseCommand): |
|
42 |
help = """Reset cyclades.* usage values in Quotaholder""" |
|
43 |
output_transaction = True |
|
44 |
option_list = BaseCommand.option_list + ( |
|
45 |
make_option("--userid", dest="userid", |
|
46 |
default=None, |
|
47 |
help="Verify quotas only for this user"), |
|
48 |
make_option("--dry-run", dest="dry_run", |
|
49 |
action='store_true', |
|
50 |
default=False), |
|
51 |
) |
|
52 |
|
|
53 |
def handle(self, *args, **options): |
|
54 |
userid = options['userid'] |
|
55 |
|
|
56 |
users = [userid] if userid else None |
|
57 |
# Get info from DB |
|
58 |
db_holdings = get_db_holdings(users) |
|
59 |
|
|
60 |
# Create commissions |
|
61 |
qh = Quotaholder.get() |
|
62 |
for user, resources in db_holdings.items(): |
|
63 |
if not user: |
|
64 |
continue |
|
65 |
reset_holding = [] |
|
66 |
for res, val in resources.items(): |
|
67 |
reset_holding.append((user, "cyclades." + res, "1", val, 0, |
|
68 |
0, 0)) |
|
69 |
if not options['dry_run']: |
|
70 |
try: |
|
71 |
qh.reset_holding(context={}, |
|
72 |
reset_holding=reset_holding) |
|
73 |
except Exception as e: |
|
74 |
self.stderr.write("Can not set up holding:%s" % e) |
|
75 |
else: |
|
76 |
self.stdout.write("Reseting holding: %s\n" % reset_holding) |
b/snf-cyclades-app/synnefo/quotas/management/commands/cyclades-usage-verify.py | ||
---|---|---|
34 | 34 |
from django.core.management.base import BaseCommand |
35 | 35 |
from optparse import make_option |
36 | 36 |
|
37 |
from synnefo.quotas import DEFAULT_SOURCE |
|
37 |
|
|
38 |
from synnefo import quotas |
|
38 | 39 |
from synnefo.quotas.util import (get_db_holdings, get_quotaholder_holdings, |
39 | 40 |
transform_quotas) |
40 | 41 |
from synnefo.webproject.management.utils import pprint_table |
42 |
from synnefo.settings import CYCLADES_ASTAKOS_SERVICE_TOKEN as ASTAKOS_TOKEN |
|
41 | 43 |
|
42 | 44 |
|
43 | 45 |
class Command(BaseCommand): |
44 |
help = """ |
|
45 |
Verify that cyclades.* resource usage. |
|
46 |
help = """Reconcile quotas of Astakos with Cyclades DB. |
|
46 | 47 |
|
47 |
Verify that usage calculated from Cyclades DB agrees with the usage
|
|
48 |
recorded in the effective quota database (Quotaholder)
|
|
48 |
Detect unsynchronized quotas between Astakos and Cyclades DB and
|
|
49 |
synchronize them if specified so.
|
|
49 | 50 |
|
50 | 51 |
""" |
51 |
output_transaction = True |
|
52 | 52 |
option_list = BaseCommand.option_list + ( |
53 | 53 |
make_option("--userid", dest="userid", |
54 | 54 |
default=None, |
55 |
help="Verify usage only for this user"), |
|
55 |
help="Reconcile resources only for this user"), |
|
56 |
make_option("--fix", dest="fix", |
|
57 |
default=False, |
|
58 |
action="store_true", |
|
59 |
help="Synchronize Astakos quotas with Cyclades DB."), |
|
60 |
make_option("--force", |
|
61 |
default=False, |
|
62 |
action="store_true", |
|
63 |
help="Override Astakos quotas. Force Astakos to impose" |
|
64 |
" the Cyclades quota, independently of their value.") |
|
56 | 65 |
) |
57 | 66 |
|
58 | 67 |
def handle(self, *args, **options): |
59 | 68 |
write = self.stdout.write |
60 | 69 |
userid = options['userid'] |
61 | 70 |
|
62 |
users = [userid] if userid else None |
|
63 |
# Get info from DB |
|
64 |
db_holdings = get_db_holdings(users) |
|
65 |
users = db_holdings.keys() |
|
71 |
# Get holdings from Cyclades DB |
|
72 |
db_holdings = get_db_holdings(userid) |
|
73 |
# Get holdings from QuotaHolder |
|
66 | 74 |
qh_holdings = get_quotaholder_holdings(userid) |
67 |
qh_users = qh_holdings.keys() |
|
68 | 75 |
|
69 |
if len(qh_users) < len(users):
|
|
70 |
for u in set(users) - set(qh_users):
|
|
71 |
write("Unknown entity: %s\n" % u)
|
|
72 |
users = qh_users
|
|
76 |
users = set(db_holdings.keys())
|
|
77 |
users.update(qh_holdings.keys())
|
|
78 |
# Remove 'None' user
|
|
79 |
users.discard(None)
|
|
73 | 80 |
|
74 |
headers = ("User", "Resource", "Database", "Quotaholder") |
|
75 | 81 |
unsynced = [] |
76 | 82 |
for user in users: |
77 |
db = db_holdings[user]
|
|
78 |
qh_all = qh_holdings[user]
|
|
83 |
db = db_holdings.get(user, {})
|
|
84 |
qh_all = qh_holdings.get(user, {})
|
|
79 | 85 |
# Assuming only one source |
80 |
qh = qh_all[DEFAULT_SOURCE]
|
|
86 |
qh = qh_all.get(quotas.DEFAULT_SOURCE, {})
|
|
81 | 87 |
qh = transform_quotas(qh) |
82 |
|
|
83 |
for resource, (value, value1) in qh.iteritems:
|
|
84 |
db_value = db.pop(resource, None)
|
|
85 |
if value != value1:
|
|
86 |
write("Commission pending for %s"
|
|
87 |
% str((user, resource)))
|
|
88 |
for resource in quotas.RESOURCES: |
|
89 |
db_value = db.pop(resource, 0)
|
|
90 |
qh_value, _, qh_pending = qh.pop(resource, (0, 0))
|
|
91 |
if qh_pending:
|
|
92 |
write("Pending commission. User '%s', resource '%s'.\n" %
|
|
93 |
(user, resource))
|
|
88 | 94 |
continue |
89 |
if db_value is None: |
|
90 |
write("Resource %s exists in QH for %s but not in DB\n" |
|
91 |
% (resource, user)) |
|
92 |
elif db_value != value: |
|
93 |
data = (user, resource, str(db_value), str(value)) |
|
95 |
if db_value != qh_value: |
|
96 |
data = (user, resource, db_value, qh_value) |
|
94 | 97 |
unsynced.append(data) |
95 | 98 |
|
96 |
for resource, db_value in db.iteritems(): |
|
97 |
write("Resource %s exists in DB for %s but not in QH\n" |
|
98 |
% (resource, user)) |
|
99 |
|
|
99 |
headers = ("User", "Resource", "Database", "Quotaholder") |
|
100 | 100 |
if unsynced: |
101 | 101 |
pprint_table(self.stderr, unsynced, headers) |
102 |
if options["fix"]: |
|
103 |
qh = quotas.Quotaholder.get() |
|
104 |
request = {} |
|
105 |
request["force"] = options["force"] |
|
106 |
request["auto_accept"] = True |
|
107 |
request["provisions"] = map(create_provision, unsynced) |
|
108 |
qh.issue_commission(ASTAKOS_TOKEN, request) |
|
109 |
else: |
|
110 |
write("Everything in sync.\n") |
|
111 |
|
|
112 |
|
|
113 |
def create_provision(provision_info): |
|
114 |
user, resource, db_value, qh_value = provision_info |
|
115 |
return {"holder": user, |
|
116 |
"source": quotas.DEFAULT_SOURCE, |
|
117 |
"resource": resource, |
|
118 |
"quantity": db_value - qh_value} |
Also available in: Unified diff