Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / quota-verify.py @ def409e0

History | View | Annotate | Download (5.4 kB)

1 a69ad12b Giorgos Korfiatis
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2 a69ad12b Giorgos Korfiatis
#
3 a69ad12b Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or
4 a69ad12b Giorgos Korfiatis
# without modification, are permitted provided that the following
5 a69ad12b Giorgos Korfiatis
# conditions are met:
6 a69ad12b Giorgos Korfiatis
#
7 a69ad12b Giorgos Korfiatis
#   1. Redistributions of source code must retain the above
8 a69ad12b Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
9 a69ad12b Giorgos Korfiatis
#      disclaimer.
10 a69ad12b Giorgos Korfiatis
#
11 a69ad12b Giorgos Korfiatis
#   2. Redistributions in binary form must reproduce the above
12 a69ad12b Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
13 a69ad12b Giorgos Korfiatis
#      disclaimer in the documentation and/or other materials
14 a69ad12b Giorgos Korfiatis
#      provided with the distribution.
15 a69ad12b Giorgos Korfiatis
#
16 a69ad12b Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 a69ad12b Giorgos Korfiatis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 a69ad12b Giorgos Korfiatis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 a69ad12b Giorgos Korfiatis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 a69ad12b Giorgos Korfiatis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 a69ad12b Giorgos Korfiatis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 a69ad12b Giorgos Korfiatis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 a69ad12b Giorgos Korfiatis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 a69ad12b Giorgos Korfiatis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 a69ad12b Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 a69ad12b Giorgos Korfiatis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 a69ad12b Giorgos Korfiatis
# POSSIBILITY OF SUCH DAMAGE.
28 a69ad12b Giorgos Korfiatis
#
29 a69ad12b Giorgos Korfiatis
# The views and conclusions contained in the software and
30 a69ad12b Giorgos Korfiatis
# documentation are those of the authors and should not be
31 a69ad12b Giorgos Korfiatis
# interpreted as representing official policies, either expressed
32 a69ad12b Giorgos Korfiatis
# or implied, of GRNET S.A.
33 a69ad12b Giorgos Korfiatis
34 a69ad12b Giorgos Korfiatis
from optparse import make_option
35 a69ad12b Giorgos Korfiatis
from django.db import transaction
36 a69ad12b Giorgos Korfiatis
37 44d950c6 Giorgos Korfiatis
from astakos.im.models import Project
38 44d950c6 Giorgos Korfiatis
from astakos.im import quotas
39 44d950c6 Giorgos Korfiatis
from snf_django.management.utils import pprint_table
40 a69ad12b Giorgos Korfiatis
from snf_django.management.commands import SynnefoCommand
41 a69ad12b Giorgos Korfiatis
42 a69ad12b Giorgos Korfiatis
import logging
43 a69ad12b Giorgos Korfiatis
logger = logging.getLogger(__name__)
44 a69ad12b Giorgos Korfiatis
45 a69ad12b Giorgos Korfiatis
46 44d950c6 Giorgos Korfiatis
def differences(local_quotas, qh_quotas):
47 44d950c6 Giorgos Korfiatis
    unsynced = []
48 44d950c6 Giorgos Korfiatis
    unexpected = []
49 44d950c6 Giorgos Korfiatis
    for holder, h_quotas in local_quotas.iteritems():
50 44d950c6 Giorgos Korfiatis
        qh_h_quotas = qh_quotas.pop(holder, {})
51 44d950c6 Giorgos Korfiatis
        for source, s_quotas in h_quotas.iteritems():
52 44d950c6 Giorgos Korfiatis
            qh_s_quotas = qh_h_quotas.pop(source, {})
53 44d950c6 Giorgos Korfiatis
            for resource, value in s_quotas.iteritems():
54 44d950c6 Giorgos Korfiatis
                qh_value = qh_s_quotas.pop(resource, None)
55 44d950c6 Giorgos Korfiatis
                if value != qh_value:
56 44d950c6 Giorgos Korfiatis
                    data = (holder, source, resource, value, qh_value)
57 44d950c6 Giorgos Korfiatis
                    unsynced.append(data)
58 44d950c6 Giorgos Korfiatis
            unexpected += unexpected_resources(holder, source, qh_s_quotas)
59 44d950c6 Giorgos Korfiatis
        unexpected += unexpected_sources(holder, qh_h_quotas)
60 44d950c6 Giorgos Korfiatis
    unexpected += unexpected_holders(qh_quotas)
61 44d950c6 Giorgos Korfiatis
    return unsynced, unexpected
62 44d950c6 Giorgos Korfiatis
63 44d950c6 Giorgos Korfiatis
64 44d950c6 Giorgos Korfiatis
def unexpected_holders(qh_quotas):
65 44d950c6 Giorgos Korfiatis
    unexpected = []
66 44d950c6 Giorgos Korfiatis
    for holder, qh_h_quotas in qh_quotas.iteritems():
67 44d950c6 Giorgos Korfiatis
        unexpected += unexpected_sources(holder, qh_h_quotas)
68 44d950c6 Giorgos Korfiatis
    return unexpected
69 44d950c6 Giorgos Korfiatis
70 44d950c6 Giorgos Korfiatis
71 44d950c6 Giorgos Korfiatis
def unexpected_sources(holder, qh_h_quotas):
72 44d950c6 Giorgos Korfiatis
    unexpected = []
73 44d950c6 Giorgos Korfiatis
    for source, qh_s_quotas in qh_h_quotas.iteritems():
74 44d950c6 Giorgos Korfiatis
        unexpected += unexpected_resources(holder, source, qh_s_quotas)
75 44d950c6 Giorgos Korfiatis
    return unexpected
76 44d950c6 Giorgos Korfiatis
77 44d950c6 Giorgos Korfiatis
78 44d950c6 Giorgos Korfiatis
def unexpected_resources(holder, source, qh_s_quotas):
79 44d950c6 Giorgos Korfiatis
    unexpected = []
80 44d950c6 Giorgos Korfiatis
    for resource, qh_value in qh_s_quotas.iteritems():
81 44d950c6 Giorgos Korfiatis
        data = (holder, source, resource, None, qh_value)
82 44d950c6 Giorgos Korfiatis
        unexpected.append(data)
83 44d950c6 Giorgos Korfiatis
    return unexpected
84 44d950c6 Giorgos Korfiatis
85 44d950c6 Giorgos Korfiatis
86 a69ad12b Giorgos Korfiatis
class Command(SynnefoCommand):
87 44d950c6 Giorgos Korfiatis
    help = "Check the integrity of user and project quota"
88 a69ad12b Giorgos Korfiatis
89 a69ad12b Giorgos Korfiatis
    option_list = SynnefoCommand.option_list + (
90 44d950c6 Giorgos Korfiatis
        make_option("--include-unexpected-holdings",
91 44d950c6 Giorgos Korfiatis
                    default=False,
92 44d950c6 Giorgos Korfiatis
                    action="store_true",
93 44d950c6 Giorgos Korfiatis
                    help=("Also check for holdings that do not correspond "
94 44d950c6 Giorgos Korfiatis
                          "to Astakos projects or user. Note that fixing such "
95 44d950c6 Giorgos Korfiatis
                          "inconsistencies will permanently delete these "
96 44d950c6 Giorgos Korfiatis
                          "holdings.")),
97 44d950c6 Giorgos Korfiatis
        make_option("--fix", dest="fix",
98 a69ad12b Giorgos Korfiatis
                    default=False,
99 44d950c6 Giorgos Korfiatis
                    action="store_true",
100 44d950c6 Giorgos Korfiatis
                    help="Synchronize Quotaholder with Astakos DB."),
101 a69ad12b Giorgos Korfiatis
    )
102 a69ad12b Giorgos Korfiatis
103 a69ad12b Giorgos Korfiatis
    @transaction.commit_on_success
104 a69ad12b Giorgos Korfiatis
    def handle(self, *args, **options):
105 44d950c6 Giorgos Korfiatis
        write = self.stderr.write
106 44d950c6 Giorgos Korfiatis
        fix = options['fix']
107 44d950c6 Giorgos Korfiatis
        check_unexpected = options["include_unexpected_holdings"]
108 44d950c6 Giorgos Korfiatis
109 44d950c6 Giorgos Korfiatis
        projects = Project.objects.all()
110 44d950c6 Giorgos Korfiatis
        local_proj_quotas, local_user_quotas = \
111 44d950c6 Giorgos Korfiatis
            quotas.astakos_project_quotas(projects)
112 44d950c6 Giorgos Korfiatis
        qh_proj_quotas, qh_user_quotas = \
113 44d950c6 Giorgos Korfiatis
            quotas.get_projects_quota_limits()
114 44d950c6 Giorgos Korfiatis
        unsynced, unexpected = differences(local_proj_quotas, qh_proj_quotas)
115 44d950c6 Giorgos Korfiatis
        unsync_u, unexpect_u = differences(local_user_quotas, qh_user_quotas)
116 44d950c6 Giorgos Korfiatis
        unsynced += unsync_u
117 44d950c6 Giorgos Korfiatis
        unexpected += unexpect_u
118 44d950c6 Giorgos Korfiatis
119 44d950c6 Giorgos Korfiatis
        headers = ("Holder", "Source", "Resource", "Astakos", "Quotaholder")
120 44d950c6 Giorgos Korfiatis
        if not unsynced and (not check_unexpected or not unexpected):
121 44d950c6 Giorgos Korfiatis
            write("Everything in sync.\n")
122 44d950c6 Giorgos Korfiatis
            return
123 44d950c6 Giorgos Korfiatis
124 44d950c6 Giorgos Korfiatis
        printable = (unsynced if not check_unexpected
125 44d950c6 Giorgos Korfiatis
                     else unsynced + unexpected)
126 44d950c6 Giorgos Korfiatis
        pprint_table(self.stdout, printable, headers, title="Inconsistencies")
127 44d950c6 Giorgos Korfiatis
        if fix:
128 44d950c6 Giorgos Korfiatis
            to_sync = []
129 44d950c6 Giorgos Korfiatis
            for holder, source, resource, value, qh_value in unsynced:
130 44d950c6 Giorgos Korfiatis
                to_sync.append(((holder, source, resource), value))
131 44d950c6 Giorgos Korfiatis
            quotas.qh.set_quota(to_sync)
132 44d950c6 Giorgos Korfiatis
133 44d950c6 Giorgos Korfiatis
            if check_unexpected:
134 44d950c6 Giorgos Korfiatis
                to_del = []
135 44d950c6 Giorgos Korfiatis
                for holder, source, resource, value, qh_value in unexpected:
136 44d950c6 Giorgos Korfiatis
                    to_del.append((holder, source, resource))
137 44d950c6 Giorgos Korfiatis
                quotas.qh.delete_quota(to_del)