Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (6.3 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
backend = get_backend()
44 d1e7d2b4 Sofia Papagiannaki
45 d1e7d2b4 Sofia Papagiannaki
class Command(NoArgsCommand):
46 d1e7d2b4 Sofia Papagiannaki
    help = "List and reset pithos usage"
47 d1e7d2b4 Sofia Papagiannaki
48 d1e7d2b4 Sofia Papagiannaki
    option_list = NoArgsCommand.option_list + (
49 d1e7d2b4 Sofia Papagiannaki
        make_option('--list',
50 d1e7d2b4 Sofia Papagiannaki
                    dest='list',
51 d1e7d2b4 Sofia Papagiannaki
                    action="store_true",
52 d1e7d2b4 Sofia Papagiannaki
                    default=True,
53 d1e7d2b4 Sofia Papagiannaki
                    help="List usage for all or specified user"),
54 d1e7d2b4 Sofia Papagiannaki
        make_option('--reset',
55 d1e7d2b4 Sofia Papagiannaki
                    dest='reset',
56 d1e7d2b4 Sofia Papagiannaki
                    action="store_true",
57 d1e7d2b4 Sofia Papagiannaki
                    default=False,
58 d1e7d2b4 Sofia Papagiannaki
                    help="Reset usage for all or specified users"),
59 d1e7d2b4 Sofia Papagiannaki
        make_option('--diverging',
60 d1e7d2b4 Sofia Papagiannaki
                    dest='diverging',
61 d1e7d2b4 Sofia Papagiannaki
                    action="store_true",
62 d1e7d2b4 Sofia Papagiannaki
                    default=False,
63 d1e7d2b4 Sofia Papagiannaki
                    help=("List or reset diverging usages")),
64 d1e7d2b4 Sofia Papagiannaki
        make_option('--user',
65 d1e7d2b4 Sofia Papagiannaki
                    dest='users',
66 d1e7d2b4 Sofia Papagiannaki
                    action='append',
67 d1e7d2b4 Sofia Papagiannaki
                    metavar='USER_UUID',
68 d1e7d2b4 Sofia Papagiannaki
                    help=("Specify which users --list or --reset applies."
69 d1e7d2b4 Sofia Papagiannaki
                          "This option can be repeated several times."
70 d1e7d2b4 Sofia Papagiannaki
                          "If no user is specified --list or --reset "
71 d1e7d2b4 Sofia Papagiannaki
                          "will be applied globally.")),
72 d1e7d2b4 Sofia Papagiannaki
        make_option(
73 d1e7d2b4 Sofia Papagiannaki
            "--no-headers",
74 d1e7d2b4 Sofia Papagiannaki
            dest="headers",
75 d1e7d2b4 Sofia Papagiannaki
            action="store_false",
76 d1e7d2b4 Sofia Papagiannaki
            default=True,
77 d1e7d2b4 Sofia Papagiannaki
            help="Do not display headers"),
78 d1e7d2b4 Sofia Papagiannaki
        make_option(
79 d1e7d2b4 Sofia Papagiannaki
            "--output-format",
80 d1e7d2b4 Sofia Papagiannaki
            dest="output_format",
81 d1e7d2b4 Sofia Papagiannaki
            metavar="[pretty, csv, json]",
82 d1e7d2b4 Sofia Papagiannaki
            default="pretty",
83 d1e7d2b4 Sofia Papagiannaki
            choices=["pretty", "csv", "json"],
84 d1e7d2b4 Sofia Papagiannaki
            help="Select the output format: pretty [the default], tabs"
85 d1e7d2b4 Sofia Papagiannaki
                 " [tab-separated output], csv [comma-separated output]"),
86 d1e7d2b4 Sofia Papagiannaki
87 d1e7d2b4 Sofia Papagiannaki
    )
88 d1e7d2b4 Sofia Papagiannaki
89 d1e7d2b4 Sofia Papagiannaki
    def handle_noargs(self, **options):
90 d1e7d2b4 Sofia Papagiannaki
        try:
91 d1e7d2b4 Sofia Papagiannaki
            account_nodes = backend.node.node_accounts(options['users'])
92 d1e7d2b4 Sofia Papagiannaki
            if not account_nodes:
93 d1e7d2b4 Sofia Papagiannaki
                raise CommandError('No users found.')
94 d1e7d2b4 Sofia Papagiannaki
95 d1e7d2b4 Sofia Papagiannaki
            db_usage = {}
96 d1e7d2b4 Sofia Papagiannaki
            for path, node in account_nodes:
97 d1e7d2b4 Sofia Papagiannaki
                size = backend.node.node_account_usage(node, CLUSTER_NORMAL)
98 d1e7d2b4 Sofia Papagiannaki
                db_usage[path] = size or 0
99 d1e7d2b4 Sofia Papagiannaki
100 16f2673e Sofia Papagiannaki
            result = backend.astakosclient.service_get_quotas(
101 16f2673e Sofia Papagiannaki
                backend.service_token,
102 d1e7d2b4 Sofia Papagiannaki
            )
103 d1e7d2b4 Sofia Papagiannaki
104 d1e7d2b4 Sofia Papagiannaki
            qh_usage = {}
105 d1e7d2b4 Sofia Papagiannaki
            resource = 'pithos.diskspace'
106 d1e7d2b4 Sofia Papagiannaki
            pending_list = []
107 d1e7d2b4 Sofia Papagiannaki
            for uuid, d in result.iteritems():
108 d1e7d2b4 Sofia Papagiannaki
                pithos_dict = d.get(DEFAULT_SOURCE, {}).get(resource, {})
109 d1e7d2b4 Sofia Papagiannaki
                pending = pithos_dict.get('pending', 0)
110 d1e7d2b4 Sofia Papagiannaki
                if pending != 0:
111 d1e7d2b4 Sofia Papagiannaki
                    pending_list.append(pending)
112 d1e7d2b4 Sofia Papagiannaki
                    continue
113 d1e7d2b4 Sofia Papagiannaki
                qh_usage[uuid] = pithos_dict.get('usage', 0)
114 d1e7d2b4 Sofia Papagiannaki
115 d1e7d2b4 Sofia Papagiannaki
            if pending_list:
116 d1e7d2b4 Sofia Papagiannaki
                self.stdout.write((
117 d1e7d2b4 Sofia Papagiannaki
                    "There are pending commissions for: %s.\n"
118 d1e7d2b4 Sofia Papagiannaki
                    "Reconcile commissions and retry"
119 d1e7d2b4 Sofia Papagiannaki
                    "in order to list/reset their quota.\n"
120 d1e7d2b4 Sofia Papagiannaki
                ) % pending_list)
121 d1e7d2b4 Sofia Papagiannaki
122 d1e7d2b4 Sofia Papagiannaki
            headers = ['uuid', 'usage']
123 d1e7d2b4 Sofia Papagiannaki
            table = []
124 d1e7d2b4 Sofia Papagiannaki
            provisions = []
125 d1e7d2b4 Sofia Papagiannaki
            for uuid in db_usage.keys():
126 d1e7d2b4 Sofia Papagiannaki
                try:
127 d1e7d2b4 Sofia Papagiannaki
                    delta = db_usage[uuid] - qh_usage[uuid]
128 d1e7d2b4 Sofia Papagiannaki
                except KeyError:
129 d1e7d2b4 Sofia Papagiannaki
                    self.stdout.write('Unknown holder: %s\n' % uuid)
130 d1e7d2b4 Sofia Papagiannaki
                    continue
131 d1e7d2b4 Sofia Papagiannaki
                else:
132 d1e7d2b4 Sofia Papagiannaki
                    if options['diverging'] and delta == 0:
133 d1e7d2b4 Sofia Papagiannaki
                        continue
134 d1e7d2b4 Sofia Papagiannaki
                    table.append((uuid, db_usage[uuid]))
135 d1e7d2b4 Sofia Papagiannaki
                    provisions.append({"holder": uuid,
136 d1e7d2b4 Sofia Papagiannaki
                                       "source": DEFAULT_SOURCE,
137 d1e7d2b4 Sofia Papagiannaki
                                       "resource": resource,
138 d1e7d2b4 Sofia Papagiannaki
                                       "quantity": delta
139 d1e7d2b4 Sofia Papagiannaki
                    })
140 d1e7d2b4 Sofia Papagiannaki
141 d1e7d2b4 Sofia Papagiannaki
142 d1e7d2b4 Sofia Papagiannaki
            if options['reset']:
143 d1e7d2b4 Sofia Papagiannaki
                if not provisions:
144 d1e7d2b4 Sofia Papagiannaki
                    raise CommandError('Nothing to reset')
145 d1e7d2b4 Sofia Papagiannaki
                request = {}
146 d1e7d2b4 Sofia Papagiannaki
                request['force'] = True
147 d1e7d2b4 Sofia Papagiannaki
                request['auto_accept'] = True
148 d1e7d2b4 Sofia Papagiannaki
                request['provisions'] = provisions
149 d1e7d2b4 Sofia Papagiannaki
                try:
150 71585c27 Sofia Papagiannaki
                    backend.astakosclient.issue_commission(
151 16f2673e Sofia Papagiannaki
                        backend.service_token, request
152 d1e7d2b4 Sofia Papagiannaki
                    )
153 d1e7d2b4 Sofia Papagiannaki
                except AstakosClientException, e:
154 d1e7d2b4 Sofia Papagiannaki
                    self.stdout.write(e.details)
155 d1e7d2b4 Sofia Papagiannaki
            elif options['list'] and table:
156 d1e7d2b4 Sofia Papagiannaki
                output_format = options["output_format"]
157 d1e7d2b4 Sofia Papagiannaki
                if output_format != "json" and not options["headers"]:
158 d1e7d2b4 Sofia Papagiannaki
                    headers = None
159 d1e7d2b4 Sofia Papagiannaki
                utils.pprint_table(self.stdout, table, headers, output_format)
160 d1e7d2b4 Sofia Papagiannaki
        finally:
161 d1e7d2b4 Sofia Papagiannaki
            backend.close()