project-show.py 8.49 KB
Newer Older
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
1
# Copyright 2012-2013 GRNET S.A. All rights reserved.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
#   1. Redistributions of source code must retain the above
#      copyright notice, this list of conditions and the following
#      disclaimer.
#
#   2. Redistributions in binary form must reproduce the above
#      copyright notice, this list of conditions and the following
#      disclaimer in the documentation and/or other materials
#      provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
34
from optparse import make_option
35
from django.core.management.base import CommandError
36

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
37
from synnefo.lib.ordereddict import OrderedDict
38
from snf_django.management.commands import SynnefoCommand
39
from synnefo.webproject.management import utils
40
from astakos.im.models import Chain, ProjectApplication
41
from ._common import show_resource_value, style_options, check_style
42
43


44
class Command(SynnefoCommand):
45
46
    args = "<id>"
    help = "Show details for project (or application) <id>"
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
47

48
    option_list = SynnefoCommand.option_list + (
49
50
51
52
        make_option('--app',
                    action='store_true',
                    dest='app',
                    default=False,
53
54
                    help="Show details of applications instead of projects"
                    ),
55
        make_option('--pending',
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
56
                    action='store_true',
57
                    dest='pending',
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
58
                    default=False,
59
60
61
62
63
64
65
66
                    help=("For a given project, show also pending "
                          "modifications (applications), if any")
                    ),
        make_option('--members',
                    action='store_true',
                    dest='members',
                    default=False,
                    help=("Show a list of project memberships")
67
                    ),
68
69
70
71
        make_option('--unit-style',
                    default='mb',
                    help=("Specify display unit for resource values "
                          "(one of %s); defaults to mb") % style_options),
72
    )
73
74
75

    def handle(self, *args, **options):
        if len(args) != 1:
76
77
            raise CommandError("Please provide project ID or name")

78
79
80
        self.unit_style = options['unit_style']
        check_style(self.unit_style)

81
        show_pending = bool(options['pending'])
82
        show_members = bool(options['members'])
83
        search_apps = options['app']
84
        self.output_format = options['output_format']
85

86
87
88
89
90
        id_ = args[0]
        try:
            id_ = int(id_)
        except ValueError:
            raise CommandError("id should be an integer value.")
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
91

92
        if search_apps:
93
94
            app = get_app(id_)
            self.print_app(app)
95
        else:
96
            state, project, app = get_chain_state(id_)
97
            self.print_project(state, project, app)
98
            if show_members and project is not None:
99
                self.stdout.write("\n")
100
                fields, labels = members_fields(project)
101
                self.pprint_table(fields, labels, title="Members")
102
103
            if show_pending and state in Chain.PENDING_STATES:
                self.stdout.write("\n")
104
                self.print_app(app)
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
105

106
107
108
    def pprint_dict(self, d, vertical=True):
        utils.pprint_table(self.stdout, [d.values()], d.keys(),
                           self.output_format, vertical=vertical)
109

110
    def pprint_table(self, tbl, labels, title=None):
111
        utils.pprint_table(self.stdout, tbl, labels,
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
                           self.output_format, title=title)

    def print_app(self, app):
        app_info = app_fields(app)
        self.pprint_dict(app_info)
        self.print_resources(app)

    def print_project(self, state, project, app):
        if project is None:
            self.print_app(app)
        else:
            self.pprint_dict(project_fields(state, project, app))
            self.print_resources(project.application)

    def print_resources(self, app):
        fields, labels = resource_fields(app, self.unit_style)
        if fields:
            self.stdout.write("\n")
            self.pprint_table(fields, labels, title="Resource limits")
131

132

133
def get_app(app_id):
134
    try:
135
        return ProjectApplication.objects.get(id=app_id)
136
137
    except ProjectApplication.DoesNotExist:
        raise CommandError("Application with id %s not found." % app_id)
138

139

140
141
142
143
144
145
def get_chain_state(project_id):
    try:
        chain = Chain.objects.get(chain=project_id)
        return chain.full_state()
    except Chain.DoesNotExist:
        raise CommandError("Project with id %s not found." % project_id)
146

147

148
149
150
def chain_fields(state, project, app):
    if project is not None:
        return project_fields(state, project, app)
151
    else:
152
        return app_fields(app)
153

154

155
156
157
158
159
160
161
162
163
164
165
166
167
def resource_fields(app, style):
    labels = ('name', 'description', 'max per member')
    policies = app.projectresourcegrant_set.all()
    collect = []
    for policy in policies:
        name = policy.resource.name
        desc = policy.resource.desc
        capacity = policy.member_capacity
        collect.append((name, desc,
                        show_resource_value(capacity, name, style)))
    return collect, labels


Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
168
def app_fields(app):
169
170
171
    mem_limit = app.limit_on_members_number
    mem_limit_show = mem_limit if mem_limit is not None else "unlimited"

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
172
    d = OrderedDict([
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
        ('project id', app.chain),
        ('application id', app.id),
        ('name', app.name),
        ('status', app.state_display()),
        ('owner', app.owner),
        ('applicant', app.applicant),
        ('homepage', app.homepage),
        ('description', app.description),
        ('comments for review', app.comments),
        ('request issue date', app.issue_date),
        ('request start date', app.start_date),
        ('request end date', app.end_date),
        ('join policy', app.member_join_policy_display),
        ('leave policy', app.member_leave_policy_display),
        ('max members', mem_limit_show),
    ])
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
189
190
191
192

    return d


193
def project_fields(s, project, last_app):
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
194
    app = project.application
195

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
196
    d = OrderedDict([
197
198
199
200
201
        ('project id', project.id),
        ('application id', app.id),
        ('name', app.name),
        ('status', Chain.state_display(s)),
    ])
202
203
204
205
    if s in Chain.PENDING_STATES:
        d.update([('pending application', last_app.id)])

    d.update([('owner', app.owner),
206
              ('applicant', app.applicant),
207
208
209
              ('homepage', app.homepage),
              ('description', app.description),
              ('comments for review', app.comments),
210
211
212
213
              ('request issue date', app.issue_date),
              ('request start date', app.start_date),
              ('creation date', project.creation_date),
              ('request end date', app.end_date),
214
215
              ])

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
216
217
    deact_date = project.deactivation_date
    if deact_date is not None:
218
        d['deactivation date'] = deact_date
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
219

220
221
222
    mem_limit = app.limit_on_members_number
    mem_limit_show = mem_limit if mem_limit is not None else "unlimited"

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
223
224
225
    d.update([
            ('join policy', app.member_join_policy_display),
            ('leave policy', app.member_leave_policy_display),
226
            ('max members', mem_limit_show),
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
227
            ('total members', project.members_count()),
228
    ])
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
229

230
    return d
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
231
232


233
234
235
236
237
238
239
240
241
242
def members_fields(project):
    labels = ('member uuid', 'email', 'status')
    objs = project.projectmembership_set.select_related('person')
    memberships = objs.all().order_by('state', 'person__email')
    collect = []
    for m in memberships:
        user = m.person
        collect.append((user.uuid,
                       user.email,
                       m.state_display()))
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
243

244
    return collect, labels