Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / reconcile-resources-astakos.py @ a3e3917f

History | View | Annotate | Download (5.9 kB)

1 3f5851eb Giorgos Korfiatis
# Copyright 2013 GRNET S.A. All rights reserved.
2 3f5851eb Giorgos Korfiatis
#
3 3f5851eb Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or
4 3f5851eb Giorgos Korfiatis
# without modification, are permitted provided that the following
5 3f5851eb Giorgos Korfiatis
# conditions are met:
6 3f5851eb Giorgos Korfiatis
#
7 3f5851eb Giorgos Korfiatis
#   1. Redistributions of source code must retain the above
8 3f5851eb Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
9 3f5851eb Giorgos Korfiatis
#      disclaimer.
10 3f5851eb Giorgos Korfiatis
#
11 3f5851eb Giorgos Korfiatis
#   2. Redistributions in binary form must reproduce the above
12 3f5851eb Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
13 3f5851eb Giorgos Korfiatis
#      disclaimer in the documentation and/or other materials
14 3f5851eb Giorgos Korfiatis
#      provided with the distribution.
15 3f5851eb Giorgos Korfiatis
#
16 3f5851eb Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 3f5851eb Giorgos Korfiatis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 3f5851eb Giorgos Korfiatis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 3f5851eb Giorgos Korfiatis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 3f5851eb Giorgos Korfiatis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 3f5851eb Giorgos Korfiatis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 3f5851eb Giorgos Korfiatis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 3f5851eb Giorgos Korfiatis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 3f5851eb Giorgos Korfiatis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 3f5851eb Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 3f5851eb Giorgos Korfiatis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 3f5851eb Giorgos Korfiatis
# POSSIBILITY OF SUCH DAMAGE.
28 3f5851eb Giorgos Korfiatis
#
29 3f5851eb Giorgos Korfiatis
# The views and conclusions contained in the software and
30 3f5851eb Giorgos Korfiatis
# documentation are those of the authors and should not be
31 3f5851eb Giorgos Korfiatis
# interpreted as representing official policies, either expressed
32 3f5851eb Giorgos Korfiatis
# or implied, of GRNET S.A.
33 3f5851eb Giorgos Korfiatis
34 3f5851eb Giorgos Korfiatis
from optparse import make_option
35 3f5851eb Giorgos Korfiatis
36 3f5851eb Giorgos Korfiatis
from django.core.management.base import BaseCommand, CommandError
37 a3e3917f Giorgos Korfiatis
from django.db import transaction
38 3f5851eb Giorgos Korfiatis
39 d758784b Christos Stavrakakis
from snf_django.management.utils import pprint_table
40 d9f634a2 Giorgos Korfiatis
from astakos.im.models import Component, AstakosUser
41 3f5851eb Giorgos Korfiatis
from astakos.im.quotas import service_get_quotas, SYSTEM
42 3f5851eb Giorgos Korfiatis
from astakos.im.functions import count_pending_app
43 3f5851eb Giorgos Korfiatis
import astakos.quotaholder_app.callpoint as qh
44 205cc8d3 Giorgos Korfiatis
import astakos.quotaholder_app.exception as qh_exception
45 3f5851eb Giorgos Korfiatis
46 3f5851eb Giorgos Korfiatis
47 3f5851eb Giorgos Korfiatis
class Command(BaseCommand):
48 3f5851eb Giorgos Korfiatis
    help = """Reconcile resource usage of Quotaholder with Astakos DB.
49 3f5851eb Giorgos Korfiatis

50 3f5851eb Giorgos Korfiatis
    Detect unsynchronized usage between Quotaholder and Astakos DB resources
51 3f5851eb Giorgos Korfiatis
    and synchronize them if specified so.
52 3f5851eb Giorgos Korfiatis

53 3f5851eb Giorgos Korfiatis
    """
54 3f5851eb Giorgos Korfiatis
55 3f5851eb Giorgos Korfiatis
    option_list = BaseCommand.option_list + (
56 3f5851eb Giorgos Korfiatis
        make_option("--userid", dest="userid",
57 3f5851eb Giorgos Korfiatis
                    default=None,
58 3f5851eb Giorgos Korfiatis
                    help="Reconcile resources only for this user"),
59 3f5851eb Giorgos Korfiatis
        make_option("--fix", dest="fix",
60 3f5851eb Giorgos Korfiatis
                    default=False,
61 3f5851eb Giorgos Korfiatis
                    action="store_true",
62 3f5851eb Giorgos Korfiatis
                    help="Synchronize Quotaholder with Astakos DB."),
63 3f5851eb Giorgos Korfiatis
        make_option("--force",
64 3f5851eb Giorgos Korfiatis
                    default=False,
65 3f5851eb Giorgos Korfiatis
                    action="store_true",
66 3f5851eb Giorgos Korfiatis
                    help="Override Quotaholder. Force Quotaholder to impose"
67 3f5851eb Giorgos Korfiatis
                         " the quota, independently of their value.")
68 3f5851eb Giorgos Korfiatis
    )
69 3f5851eb Giorgos Korfiatis
70 a3e3917f Giorgos Korfiatis
    @transaction.commit_on_success
71 3f5851eb Giorgos Korfiatis
    def handle(self, *args, **options):
72 3f5851eb Giorgos Korfiatis
        write = self.stdout.write
73 3f5851eb Giorgos Korfiatis
        force = options['force']
74 3f5851eb Giorgos Korfiatis
        userid = options['userid']
75 3f5851eb Giorgos Korfiatis
76 3f5851eb Giorgos Korfiatis
        try:
77 d9f634a2 Giorgos Korfiatis
            astakos = Component.objects.get(name="astakos")
78 d9f634a2 Giorgos Korfiatis
        except Component.DoesNotExist:
79 d9f634a2 Giorgos Korfiatis
            raise CommandError("Component 'astakos' not found.")
80 3f5851eb Giorgos Korfiatis
81 3f5851eb Giorgos Korfiatis
        query = [userid] if userid is not None else None
82 3f5851eb Giorgos Korfiatis
        qh_holdings = service_get_quotas(astakos, query)
83 3f5851eb Giorgos Korfiatis
84 3f5851eb Giorgos Korfiatis
        if userid is None:
85 3f5851eb Giorgos Korfiatis
            users = AstakosUser.objects.verified()
86 3f5851eb Giorgos Korfiatis
        else:
87 3f5851eb Giorgos Korfiatis
            try:
88 3f5851eb Giorgos Korfiatis
                users = [AstakosUser.objects.get(uuid=userid)]
89 3f5851eb Giorgos Korfiatis
            except AstakosUser.DoesNotExist:
90 3f5851eb Giorgos Korfiatis
                raise CommandError("There is no user with uuid '%s'." % userid)
91 3f5851eb Giorgos Korfiatis
92 3f5851eb Giorgos Korfiatis
        db_holdings = count_pending_app(users)
93 3f5851eb Giorgos Korfiatis
94 3f5851eb Giorgos Korfiatis
        pending_exists = False
95 3f5851eb Giorgos Korfiatis
        unknown_user_exists = False
96 3f5851eb Giorgos Korfiatis
        unsynced = []
97 3f5851eb Giorgos Korfiatis
        for user in users:
98 3f5851eb Giorgos Korfiatis
            uuid = user.uuid
99 3f5851eb Giorgos Korfiatis
            db_value = db_holdings.get(uuid, 0)
100 3f5851eb Giorgos Korfiatis
            try:
101 3f5851eb Giorgos Korfiatis
                qh_all = qh_holdings[uuid]
102 3f5851eb Giorgos Korfiatis
            except KeyError:
103 3f5851eb Giorgos Korfiatis
                write("User '%s' does not exist in Quotaholder!\n" % uuid)
104 3f5851eb Giorgos Korfiatis
                unknown_user_exists = True
105 3f5851eb Giorgos Korfiatis
                continue
106 3f5851eb Giorgos Korfiatis
107 3f5851eb Giorgos Korfiatis
            # Assuming only one source
108 3f5851eb Giorgos Korfiatis
            system_qh = qh_all.get(SYSTEM, {})
109 3f5851eb Giorgos Korfiatis
            # Assuming only one resource
110 3f5851eb Giorgos Korfiatis
            resource = 'astakos.pending_app'
111 3f5851eb Giorgos Korfiatis
            try:
112 3f5851eb Giorgos Korfiatis
                qh_values = system_qh[resource]
113 3f5851eb Giorgos Korfiatis
                qh_value = qh_values['usage']
114 3f5851eb Giorgos Korfiatis
                qh_pending = qh_values['pending']
115 3f5851eb Giorgos Korfiatis
            except KeyError:
116 3f5851eb Giorgos Korfiatis
                write("Resource '%s' does not exist in Quotaholder"
117 3f5851eb Giorgos Korfiatis
                      " for user '%s'!\n" % (resource, uuid))
118 3f5851eb Giorgos Korfiatis
                continue
119 3f5851eb Giorgos Korfiatis
            if qh_pending:
120 3f5851eb Giorgos Korfiatis
                write("Pending commission. User '%s', resource '%s'.\n" %
121 3f5851eb Giorgos Korfiatis
                      (uuid, resource))
122 3f5851eb Giorgos Korfiatis
                pending_exists = True
123 3f5851eb Giorgos Korfiatis
                continue
124 3f5851eb Giorgos Korfiatis
            if db_value != qh_value:
125 3f5851eb Giorgos Korfiatis
                data = (uuid, resource, db_value, qh_value)
126 3f5851eb Giorgos Korfiatis
                unsynced.append(data)
127 3f5851eb Giorgos Korfiatis
128 3f5851eb Giorgos Korfiatis
        headers = ("User", "Resource", "Astakos", "Quotaholder")
129 3f5851eb Giorgos Korfiatis
        if unsynced:
130 3f5851eb Giorgos Korfiatis
            pprint_table(self.stderr, unsynced, headers)
131 3f5851eb Giorgos Korfiatis
            if options["fix"]:
132 3f5851eb Giorgos Korfiatis
                provisions = map(create_provision, unsynced)
133 205cc8d3 Giorgos Korfiatis
                try:
134 205cc8d3 Giorgos Korfiatis
                    s = qh.issue_commission('astakos', provisions,
135 205cc8d3 Giorgos Korfiatis
                                            name='RECONCILE', force=force)
136 205cc8d3 Giorgos Korfiatis
                except qh_exception.NoCapacityError:
137 205cc8d3 Giorgos Korfiatis
                    write("Reconciling failed because a limit has been "
138 205cc8d3 Giorgos Korfiatis
                          "reached. Use --force to ignore the check.\n")
139 205cc8d3 Giorgos Korfiatis
                    return
140 205cc8d3 Giorgos Korfiatis
141 3f5851eb Giorgos Korfiatis
                qh.resolve_pending_commission('astakos', s)
142 3f5851eb Giorgos Korfiatis
                write("Fixed unsynced resources\n")
143 3f5851eb Giorgos Korfiatis
144 3f5851eb Giorgos Korfiatis
        if pending_exists:
145 3f5851eb Giorgos Korfiatis
            write("Found pending commissions. "
146 3f5851eb Giorgos Korfiatis
                  "This is probably a bug. Please report.\n")
147 3f5851eb Giorgos Korfiatis
        elif not (unsynced or unknown_user_exists):
148 3f5851eb Giorgos Korfiatis
            write("Everything in sync.\n")
149 3f5851eb Giorgos Korfiatis
150 3f5851eb Giorgos Korfiatis
151 3f5851eb Giorgos Korfiatis
def create_provision(provision_info):
152 3f5851eb Giorgos Korfiatis
    user, resource, db_value, qh_value = provision_info
153 3f5851eb Giorgos Korfiatis
    return (user, SYSTEM, resource), (db_value - qh_value)