Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / project-show.py @ 7cfc0cef

History | View | Annotate | Download (8.5 kB)

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

    
34
from optparse import make_option
35
from django.core.management.base import CommandError
36

    
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
    args = "<id>"
46
    help = "Show details for project (or application) <id>"
47

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

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

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

    
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
        id_ = args[0]
87
        try:
88
            id_ = int(id_)
89
        except ValueError:
90
            raise CommandError("id should be an integer value.")
91

    
92
        if search_apps:
93
            app = get_app(id_)
94
            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
            if show_pending and state in Chain.PENDING_STATES:
103
                self.stdout.write("\n")
104
                self.print_app(app)
105

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

    
110
    def pprint_table(self, tbl, labels, title=None):
111
        utils.pprint_table(self.stdout, tbl, labels,
112
                           self.output_format, title=title)
113

    
114
    def print_app(self, app):
115
        app_info = app_fields(app)
116
        self.pprint_dict(app_info)
117
        self.print_resources(app)
118

    
119
    def print_project(self, state, project, app):
120
        if project is None:
121
            self.print_app(app)
122
        else:
123
            self.pprint_dict(project_fields(state, project, app))
124
            self.print_resources(project.application)
125

    
126
    def print_resources(self, app):
127
        fields, labels = resource_fields(app, self.unit_style)
128
        if fields:
129
            self.stdout.write("\n")
130
            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
    except ProjectApplication.DoesNotExist:
137
        raise CommandError("Application with id %s not found." % app_id)
138

    
139

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

    
147

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

    
154

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

    
167

    
168
def app_fields(app):
169
    mem_limit = app.limit_on_members_number
170
    mem_limit_show = mem_limit if mem_limit is not None else "unlimited"
171

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

    
190
    return d
191

    
192

    
193
def project_fields(s, project, last_app):
194
    app = project.application
195

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

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

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

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

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

    
230
    return d
231

    
232

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

    
244
    return collect, labels