Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (6.1 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 3f5851eb Giorgos Korfiatis
38 3f5851eb Giorgos Korfiatis
from synnefo.webproject.management.utils import pprint_table
39 3f5851eb Giorgos Korfiatis
from snf_django.lib.db.transaction import commit_on_success_strict
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 3f5851eb Giorgos Korfiatis
    @commit_on_success_strict()
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 3848b521 Giorgos Korfiatis
            users = AstakosUser.objects.accepted()
86 3f5851eb Giorgos Korfiatis
        else:
87 3f5851eb Giorgos Korfiatis
            try:
88 3848b521 Giorgos Korfiatis
                user = 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 3848b521 Giorgos Korfiatis
            if not user.is_accepted():
92 3848b521 Giorgos Korfiatis
                raise CommandError("%s is not an accepted user." % userid)
93 3848b521 Giorgos Korfiatis
            users = [user]
94 3f5851eb Giorgos Korfiatis
95 3f5851eb Giorgos Korfiatis
        db_holdings = count_pending_app(users)
96 3f5851eb Giorgos Korfiatis
97 3f5851eb Giorgos Korfiatis
        pending_exists = False
98 3f5851eb Giorgos Korfiatis
        unknown_user_exists = False
99 3f5851eb Giorgos Korfiatis
        unsynced = []
100 3f5851eb Giorgos Korfiatis
        for user in users:
101 3f5851eb Giorgos Korfiatis
            uuid = user.uuid
102 3f5851eb Giorgos Korfiatis
            db_value = db_holdings.get(uuid, 0)
103 3f5851eb Giorgos Korfiatis
            try:
104 3f5851eb Giorgos Korfiatis
                qh_all = qh_holdings[uuid]
105 3f5851eb Giorgos Korfiatis
            except KeyError:
106 3f5851eb Giorgos Korfiatis
                write("User '%s' does not exist in Quotaholder!\n" % uuid)
107 3f5851eb Giorgos Korfiatis
                unknown_user_exists = True
108 3f5851eb Giorgos Korfiatis
                continue
109 3f5851eb Giorgos Korfiatis
110 3f5851eb Giorgos Korfiatis
            # Assuming only one source
111 3f5851eb Giorgos Korfiatis
            system_qh = qh_all.get(SYSTEM, {})
112 3f5851eb Giorgos Korfiatis
            # Assuming only one resource
113 3f5851eb Giorgos Korfiatis
            resource = 'astakos.pending_app'
114 3f5851eb Giorgos Korfiatis
            try:
115 3f5851eb Giorgos Korfiatis
                qh_values = system_qh[resource]
116 3f5851eb Giorgos Korfiatis
                qh_value = qh_values['usage']
117 3f5851eb Giorgos Korfiatis
                qh_pending = qh_values['pending']
118 3f5851eb Giorgos Korfiatis
            except KeyError:
119 3f5851eb Giorgos Korfiatis
                write("Resource '%s' does not exist in Quotaholder"
120 3f5851eb Giorgos Korfiatis
                      " for user '%s'!\n" % (resource, uuid))
121 3f5851eb Giorgos Korfiatis
                continue
122 3f5851eb Giorgos Korfiatis
            if qh_pending:
123 3f5851eb Giorgos Korfiatis
                write("Pending commission. User '%s', resource '%s'.\n" %
124 3f5851eb Giorgos Korfiatis
                      (uuid, resource))
125 3f5851eb Giorgos Korfiatis
                pending_exists = True
126 3f5851eb Giorgos Korfiatis
                continue
127 3f5851eb Giorgos Korfiatis
            if db_value != qh_value:
128 3f5851eb Giorgos Korfiatis
                data = (uuid, resource, db_value, qh_value)
129 3f5851eb Giorgos Korfiatis
                unsynced.append(data)
130 3f5851eb Giorgos Korfiatis
131 3f5851eb Giorgos Korfiatis
        headers = ("User", "Resource", "Astakos", "Quotaholder")
132 3f5851eb Giorgos Korfiatis
        if unsynced:
133 3f5851eb Giorgos Korfiatis
            pprint_table(self.stderr, unsynced, headers)
134 3f5851eb Giorgos Korfiatis
            if options["fix"]:
135 3f5851eb Giorgos Korfiatis
                provisions = map(create_provision, unsynced)
136 205cc8d3 Giorgos Korfiatis
                try:
137 205cc8d3 Giorgos Korfiatis
                    s = qh.issue_commission('astakos', provisions,
138 205cc8d3 Giorgos Korfiatis
                                            name='RECONCILE', force=force)
139 205cc8d3 Giorgos Korfiatis
                except qh_exception.NoCapacityError:
140 205cc8d3 Giorgos Korfiatis
                    write("Reconciling failed because a limit has been "
141 205cc8d3 Giorgos Korfiatis
                          "reached. Use --force to ignore the check.\n")
142 205cc8d3 Giorgos Korfiatis
                    return
143 205cc8d3 Giorgos Korfiatis
144 3f5851eb Giorgos Korfiatis
                qh.resolve_pending_commission('astakos', s)
145 3f5851eb Giorgos Korfiatis
                write("Fixed unsynced resources\n")
146 3f5851eb Giorgos Korfiatis
147 3f5851eb Giorgos Korfiatis
        if pending_exists:
148 3f5851eb Giorgos Korfiatis
            write("Found pending commissions. "
149 3f5851eb Giorgos Korfiatis
                  "This is probably a bug. Please report.\n")
150 3f5851eb Giorgos Korfiatis
        elif not (unsynced or unknown_user_exists):
151 3f5851eb Giorgos Korfiatis
            write("Everything in sync.\n")
152 3f5851eb Giorgos Korfiatis
153 3f5851eb Giorgos Korfiatis
154 3f5851eb Giorgos Korfiatis
def create_provision(provision_info):
155 3f5851eb Giorgos Korfiatis
    user, resource, db_value, qh_value = provision_info
156 3f5851eb Giorgos Korfiatis
    return (user, SYSTEM, resource), (db_value - qh_value)