Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / management / commands / project-show.py @ 35cbac33

History | View | Annotate | Download (8.3 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

    
36
from synnefo.lib.ordereddict import OrderedDict
37
from snf_django.management.commands import SynnefoCommand, CommandError
38
from snf_django.management import utils
39
from astakos.im.models import ProjectApplication, Project
40
from astakos.im import quotas
41
from ._common import show_resource_value, style_options, check_style
42
from synnefo.util import units
43

    
44

    
45
class Command(SynnefoCommand):
46
    args = "<id>"
47
    help = "Show details for project <id>"
48

    
49
    option_list = SynnefoCommand.option_list + (
50
        make_option('--pending',
51
                    action='store_true',
52
                    dest='pending',
53
                    default=False,
54
                    help=("For a given project, show also pending "
55
                          "modification, if any")
56
                    ),
57
        make_option('--members',
58
                    action='store_true',
59
                    dest='members',
60
                    default=False,
61
                    help=("Show a list of project memberships")
62
                    ),
63
        make_option('--quota',
64
                    action='store_true',
65
                    dest='list_quotas',
66
                    default=False,
67
                    help="List project quota"),
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
        show_quota = bool(options['list_quotas'])
84
        self.output_format = options['output_format']
85

    
86
        id_ = args[0]
87
        if True:
88
            project = get_chain_state(id_)
89
            self.print_project(project, show_quota)
90
            if show_members and project is not None:
91
                self.stdout.write("\n")
92
                fields, labels = members_fields(project)
93
                self.pprint_table(fields, labels, title="Members")
94
            if show_pending:
95
                app = project.last_application
96
                if app and app.state == ProjectApplication.PENDING:
97
                    self.stdout.write("\n")
98
                    self.print_app(app)
99

    
100
    def pprint_dict(self, d, vertical=True):
101
        utils.pprint_table(self.stdout, [d.values()], d.keys(),
102
                           self.output_format, vertical=vertical)
103

    
104
    def pprint_table(self, tbl, labels, title=None):
105
        utils.pprint_table(self.stdout, tbl, labels,
106
                           self.output_format, title=title)
107

    
108
    def print_app(self, app):
109
        app_info = app_fields(app)
110
        self.pprint_dict(app_info)
111
        self.print_app_resources(app)
112

    
113
    def print_project(self, project, show_quota=False):
114
        self.pprint_dict(project_fields(project))
115
        quota = (quotas.get_project_quota(project)
116
                 if show_quota else None)
117
        self.print_resources(project, quota=quota)
118

    
119
    def print_resources(self, project, quota=None):
120
        policies = project.projectresourcequota_set.all()
121
        fields, labels = resource_fields(policies, quota, self.unit_style)
122
        if fields:
123
            self.stdout.write("\n")
124
            self.pprint_table(fields, labels, title="Resource limits")
125

    
126
    def print_app_resources(self, app):
127
        policies = app.projectresourcegrant_set.all()
128
        fields, labels = resource_fields(policies, None, self.unit_style)
129
        if fields:
130
            self.stdout.write("\n")
131
            self.pprint_table(fields, labels, title="Resource limits")
132

    
133

    
134
def get_chain_state(project_id):
135
    try:
136
        return Project.objects.get(uuid=project_id)
137
    except Project.DoesNotExist:
138
        raise CommandError("Project with id %s not found." % project_id)
139

    
140

    
141
def resource_fields(policies, quota, style):
142
    labels = ('name', 'max per member', 'max per project')
143
    if quota:
144
        labels += ('usage',)
145
    collect = []
146
    for policy in policies:
147
        name = policy.resource.name
148
        capacity = policy.member_capacity
149
        p_capacity = policy.project_capacity
150
        row = (name,
151
               show_resource_value(capacity, name, style),
152
               show_resource_value(p_capacity, name, style))
153
        if quota:
154
            r_quota = quota.get(name)
155
            usage = r_quota.get('project_usage')
156
            row += (show_resource_value(usage, name, style),)
157
        collect.append(row)
158
    return collect, labels
159

    
160

    
161
def app_fields(app):
162
    d = OrderedDict([
163
        ('project id', app.chain.uuid),
164
        ('application id', app.id),
165
        ('status', app.state_display()),
166
        ('applicant', app.applicant),
167
        ('comments for review', app.comments),
168
        ('request issue date', app.issue_date),
169
        ])
170
    if app.name:
171
        d['name'] = app.name
172
    if app.owner:
173
        d['owner'] = app.owner
174
    if app.homepage:
175
        d['homepage'] = app.homepage
176
    if app.description:
177
        d['description'] = app.description
178
    if app.start_date:
179
        d['request start date'] = app.start_date
180
    if app.end_date:
181
        d['request end date'] = app.end_date
182
    if app.member_join_policy:
183
        d['join policy'] = app.member_join_policy_display
184
    if app.member_leave_policy:
185
        d['leave policy'] = app.member_leave_policy_display
186
    if app.limit_on_members_number:
187
        d['max members'] = units.show(app.limit_on_members_number, None)
188

    
189
    return d
190

    
191

    
192
def project_fields(project):
193
    app = project.last_application
194

    
195
    d = OrderedDict([
196
        ('project id', project.uuid),
197
        ('name', project.realname),
198
        ('status', project.state_display()),
199
        ('owner', project.owner),
200
        ('homepage', project.homepage),
201
        ('description', project.description),
202
        ('creation date', project.creation_date),
203
        ('request end date', project.end_date),
204
        ])
205

    
206
    deact = project.last_deactivation()
207
    if deact is not None:
208
        d['deactivation date'] = deact.date
209

    
210
    d.update([
211
            ('join policy', project.member_join_policy_display),
212
            ('leave policy', project.member_leave_policy_display),
213
            ('max members', units.show(project.limit_on_members_number, None)),
214
            ('total members', project.members_count()),
215
    ])
216

    
217
    return d
218

    
219

    
220
def members_fields(project):
221
    labels = ('member uuid', 'email', 'status')
222
    objs = project.projectmembership_set.select_related('person')
223
    memberships = objs.all().order_by('state', 'person__email')
224
    collect = []
225
    for m in memberships:
226
        user = m.person
227
        collect.append((user.uuid,
228
                       user.email,
229
                       m.state_display()))
230

    
231
    return collect, labels