Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-app / pithos / api / management / commands / reconcile-resources-pithos.py @ d1e7d2b4

History | View | Annotate | Download (6.5 kB)

1 d1e7d2b4 Sofia Papagiannaki
# Copyright 2012 GRNET S.A. All rights reserved.
2 d1e7d2b4 Sofia Papagiannaki
#
3 d1e7d2b4 Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 d1e7d2b4 Sofia Papagiannaki
# without modification, are permitted provided that the following
5 d1e7d2b4 Sofia Papagiannaki
# conditions are met:
6 d1e7d2b4 Sofia Papagiannaki
#
7 d1e7d2b4 Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 d1e7d2b4 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 d1e7d2b4 Sofia Papagiannaki
#      disclaimer.
10 d1e7d2b4 Sofia Papagiannaki
#
11 d1e7d2b4 Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 d1e7d2b4 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 d1e7d2b4 Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 d1e7d2b4 Sofia Papagiannaki
#      provided with the distribution.
15 d1e7d2b4 Sofia Papagiannaki
#
16 d1e7d2b4 Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 d1e7d2b4 Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 d1e7d2b4 Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 d1e7d2b4 Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 d1e7d2b4 Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 d1e7d2b4 Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 d1e7d2b4 Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 d1e7d2b4 Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 d1e7d2b4 Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 d1e7d2b4 Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 d1e7d2b4 Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 d1e7d2b4 Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 d1e7d2b4 Sofia Papagiannaki
#
29 d1e7d2b4 Sofia Papagiannaki
# The views and conclusions contained in the software and
30 d1e7d2b4 Sofia Papagiannaki
# documentation are those of the authors and should not be
31 d1e7d2b4 Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 d1e7d2b4 Sofia Papagiannaki
# or implied, of GRNET S.A.
33 d1e7d2b4 Sofia Papagiannaki
34 d1e7d2b4 Sofia Papagiannaki
from django.core.management.base import NoArgsCommand, CommandError
35 d1e7d2b4 Sofia Papagiannaki
36 d1e7d2b4 Sofia Papagiannaki
from optparse import make_option
37 d1e7d2b4 Sofia Papagiannaki
38 d1e7d2b4 Sofia Papagiannaki
from pithos.api.util import get_backend
39 d1e7d2b4 Sofia Papagiannaki
from pithos.backends.modular import CLUSTER_NORMAL, DEFAULT_SOURCE
40 d1e7d2b4 Sofia Papagiannaki
from synnefo.webproject.management import utils
41 d1e7d2b4 Sofia Papagiannaki
from astakosclient.errors import AstakosClientException
42 d1e7d2b4 Sofia Papagiannaki
43 d1e7d2b4 Sofia Papagiannaki
ENTITY_KEY = '1'
44 d1e7d2b4 Sofia Papagiannaki
45 d1e7d2b4 Sofia Papagiannaki
backend = get_backend()
46 d1e7d2b4 Sofia Papagiannaki
47 d1e7d2b4 Sofia Papagiannaki
class Command(NoArgsCommand):
48 d1e7d2b4 Sofia Papagiannaki
    help = "List and reset pithos usage"
49 d1e7d2b4 Sofia Papagiannaki
50 d1e7d2b4 Sofia Papagiannaki
    option_list = NoArgsCommand.option_list + (
51 d1e7d2b4 Sofia Papagiannaki
        make_option('--list',
52 d1e7d2b4 Sofia Papagiannaki
                    dest='list',
53 d1e7d2b4 Sofia Papagiannaki
                    action="store_true",
54 d1e7d2b4 Sofia Papagiannaki
                    default=True,
55 d1e7d2b4 Sofia Papagiannaki
                    help="List usage for all or specified user"),
56 d1e7d2b4 Sofia Papagiannaki
        make_option('--reset',
57 d1e7d2b4 Sofia Papagiannaki
                    dest='reset',
58 d1e7d2b4 Sofia Papagiannaki
                    action="store_true",
59 d1e7d2b4 Sofia Papagiannaki
                    default=False,
60 d1e7d2b4 Sofia Papagiannaki
                    help="Reset usage for all or specified users"),
61 d1e7d2b4 Sofia Papagiannaki
        make_option('--diverging',
62 d1e7d2b4 Sofia Papagiannaki
                    dest='diverging',
63 d1e7d2b4 Sofia Papagiannaki
                    action="store_true",
64 d1e7d2b4 Sofia Papagiannaki
                    default=False,
65 d1e7d2b4 Sofia Papagiannaki
                    help=("List or reset diverging usages")),
66 d1e7d2b4 Sofia Papagiannaki
        make_option('--user',
67 d1e7d2b4 Sofia Papagiannaki
                    dest='users',
68 d1e7d2b4 Sofia Papagiannaki
                    action='append',
69 d1e7d2b4 Sofia Papagiannaki
                    metavar='USER_UUID',
70 d1e7d2b4 Sofia Papagiannaki
                    help=("Specify which users --list or --reset applies."
71 d1e7d2b4 Sofia Papagiannaki
                          "This option can be repeated several times."
72 d1e7d2b4 Sofia Papagiannaki
                          "If no user is specified --list or --reset "
73 d1e7d2b4 Sofia Papagiannaki
                          "will be applied globally.")),
74 d1e7d2b4 Sofia Papagiannaki
        make_option(
75 d1e7d2b4 Sofia Papagiannaki
            "--no-headers",
76 d1e7d2b4 Sofia Papagiannaki
            dest="headers",
77 d1e7d2b4 Sofia Papagiannaki
            action="store_false",
78 d1e7d2b4 Sofia Papagiannaki
            default=True,
79 d1e7d2b4 Sofia Papagiannaki
            help="Do not display headers"),
80 d1e7d2b4 Sofia Papagiannaki
        make_option(
81 d1e7d2b4 Sofia Papagiannaki
            "--output-format",
82 d1e7d2b4 Sofia Papagiannaki
            dest="output_format",
83 d1e7d2b4 Sofia Papagiannaki
            metavar="[pretty, csv, json]",
84 d1e7d2b4 Sofia Papagiannaki
            default="pretty",
85 d1e7d2b4 Sofia Papagiannaki
            choices=["pretty", "csv", "json"],
86 d1e7d2b4 Sofia Papagiannaki
            help="Select the output format: pretty [the default], tabs"
87 d1e7d2b4 Sofia Papagiannaki
                 " [tab-separated output], csv [comma-separated output]"),
88 d1e7d2b4 Sofia Papagiannaki
89 d1e7d2b4 Sofia Papagiannaki
    )
90 d1e7d2b4 Sofia Papagiannaki
91 d1e7d2b4 Sofia Papagiannaki
    def handle_noargs(self, **options):
92 d1e7d2b4 Sofia Papagiannaki
        try:
93 d1e7d2b4 Sofia Papagiannaki
            account_nodes = backend.node.node_accounts(options['users'])
94 d1e7d2b4 Sofia Papagiannaki
            if not account_nodes:
95 d1e7d2b4 Sofia Papagiannaki
                raise CommandError('No users found.')
96 d1e7d2b4 Sofia Papagiannaki
97 d1e7d2b4 Sofia Papagiannaki
            db_usage = {}
98 d1e7d2b4 Sofia Papagiannaki
            for path, node in account_nodes:
99 d1e7d2b4 Sofia Papagiannaki
                size = backend.node.node_account_usage(node, CLUSTER_NORMAL)
100 d1e7d2b4 Sofia Papagiannaki
                db_usage[path] = size or 0
101 d1e7d2b4 Sofia Papagiannaki
102 d1e7d2b4 Sofia Papagiannaki
            result = backend.quotaholder.service_get_quotas(
103 d1e7d2b4 Sofia Papagiannaki
                backend.quotaholder_token,
104 d1e7d2b4 Sofia Papagiannaki
            )
105 d1e7d2b4 Sofia Papagiannaki
106 d1e7d2b4 Sofia Papagiannaki
            qh_usage = {}
107 d1e7d2b4 Sofia Papagiannaki
            resource = 'pithos.diskspace'
108 d1e7d2b4 Sofia Papagiannaki
            pending_list = []
109 d1e7d2b4 Sofia Papagiannaki
            for uuid, d in result.iteritems():
110 d1e7d2b4 Sofia Papagiannaki
                pithos_dict = d.get(DEFAULT_SOURCE, {}).get(resource, {})
111 d1e7d2b4 Sofia Papagiannaki
                pending = pithos_dict.get('pending', 0)
112 d1e7d2b4 Sofia Papagiannaki
                if pending != 0:
113 d1e7d2b4 Sofia Papagiannaki
                    pending_list.append(pending)
114 d1e7d2b4 Sofia Papagiannaki
                    continue
115 d1e7d2b4 Sofia Papagiannaki
                qh_usage[uuid] = pithos_dict.get('usage', 0)
116 d1e7d2b4 Sofia Papagiannaki
117 d1e7d2b4 Sofia Papagiannaki
            if pending_list:
118 d1e7d2b4 Sofia Papagiannaki
                self.stdout.write((
119 d1e7d2b4 Sofia Papagiannaki
                    "There are pending commissions for: %s.\n"
120 d1e7d2b4 Sofia Papagiannaki
                    "Reconcile commissions and retry"
121 d1e7d2b4 Sofia Papagiannaki
                    "in order to list/reset their quota.\n"
122 d1e7d2b4 Sofia Papagiannaki
                ) % pending_list)
123 d1e7d2b4 Sofia Papagiannaki
124 d1e7d2b4 Sofia Papagiannaki
            headers = ['uuid', 'usage']
125 d1e7d2b4 Sofia Papagiannaki
            table = []
126 d1e7d2b4 Sofia Papagiannaki
            provisions = []
127 d1e7d2b4 Sofia Papagiannaki
            for uuid in db_usage.keys():
128 d1e7d2b4 Sofia Papagiannaki
                try:
129 d1e7d2b4 Sofia Papagiannaki
                    delta = db_usage[uuid] - qh_usage[uuid]
130 d1e7d2b4 Sofia Papagiannaki
                except KeyError:
131 d1e7d2b4 Sofia Papagiannaki
                    self.stdout.write('Unknown holder: %s\n' % uuid)
132 d1e7d2b4 Sofia Papagiannaki
                    continue
133 d1e7d2b4 Sofia Papagiannaki
                else:
134 d1e7d2b4 Sofia Papagiannaki
                    if options['diverging'] and delta == 0:
135 d1e7d2b4 Sofia Papagiannaki
                        continue
136 d1e7d2b4 Sofia Papagiannaki
                    table.append((uuid, db_usage[uuid]))
137 d1e7d2b4 Sofia Papagiannaki
                    provisions.append({"holder": uuid,
138 d1e7d2b4 Sofia Papagiannaki
                                       "source": DEFAULT_SOURCE,
139 d1e7d2b4 Sofia Papagiannaki
                                       "resource": resource,
140 d1e7d2b4 Sofia Papagiannaki
                                       "quantity": delta
141 d1e7d2b4 Sofia Papagiannaki
                    })
142 d1e7d2b4 Sofia Papagiannaki
143 d1e7d2b4 Sofia Papagiannaki
144 d1e7d2b4 Sofia Papagiannaki
            if options['reset']:
145 d1e7d2b4 Sofia Papagiannaki
                if not provisions:
146 d1e7d2b4 Sofia Papagiannaki
                    raise CommandError('Nothing to reset')
147 d1e7d2b4 Sofia Papagiannaki
                request = {}
148 d1e7d2b4 Sofia Papagiannaki
                request['force'] = True
149 d1e7d2b4 Sofia Papagiannaki
                request['auto_accept'] = True
150 d1e7d2b4 Sofia Papagiannaki
                request['provisions'] = provisions
151 d1e7d2b4 Sofia Papagiannaki
                try:
152 d1e7d2b4 Sofia Papagiannaki
                    serial = backend.quotaholder.issue_commission(
153 d1e7d2b4 Sofia Papagiannaki
                        backend.quotaholder_token, request
154 d1e7d2b4 Sofia Papagiannaki
                    )
155 d1e7d2b4 Sofia Papagiannaki
                except AstakosClientException, e:
156 d1e7d2b4 Sofia Papagiannaki
                    self.stdout.write(e.details)
157 d1e7d2b4 Sofia Papagiannaki
                else:
158 d1e7d2b4 Sofia Papagiannaki
                    backend.quotaholder_serials.insert_many([serial])
159 d1e7d2b4 Sofia Papagiannaki
            elif options['list'] and table:
160 d1e7d2b4 Sofia Papagiannaki
                output_format = options["output_format"]
161 d1e7d2b4 Sofia Papagiannaki
                if output_format != "json" and not options["headers"]:
162 d1e7d2b4 Sofia Papagiannaki
                    headers = None
163 d1e7d2b4 Sofia Papagiannaki
                utils.pprint_table(self.stdout, table, headers, output_format)
164 d1e7d2b4 Sofia Papagiannaki
        finally:
165 d1e7d2b4 Sofia Papagiannaki
            backend.close()