Revision 75380308

b/snf-astakos-app/astakos/im/forms.py
66 66
    MODERATION_ENABLED, PROJECT_MEMBER_JOIN_POLICIES,
67 67
    PROJECT_MEMBER_LEAVE_POLICIES, EMAILCHANGE_ENABLED,
68 68
    )
69
from astakos.im.presentation import RESOURCES_PRESENTATION_DATA
69
from astakos.im import presentation
70 70
from astakos.im.widgets import DummyWidget, RecaptchaWidget
71 71
from astakos.im.functions import (
72 72
    send_change_email, submit_application, accept_membership_checks)
......
878 878
                        d.update(dict(resource=prefix, uplimit=None))
879 879
                    append(d)
880 880

  
881
        ordered_keys = RESOURCES_PRESENTATION_DATA['resources_order']
881
        ordered_keys = presentation.RESOURCES['resources_order']
882 882
        policies = sorted(policies, key=lambda r:ordered_keys.index(r['str_repr']))
883 883
        return policies
884 884

  
b/snf-astakos-app/astakos/im/models.py
79 79
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE
80 80
from synnefo.lib.db.intdecimalfield import intDecimalField
81 81
from synnefo.util.text import uenc, udec
82
from astakos.im.presentation import RESOURCES_PRESENTATION_DATA
82
from astakos.im import presentation
83 83

  
84 84
logger = logging.getLogger(__name__)
85 85

  
......
134 134
_presentation_data = {}
135 135
def get_presentation(resource):
136 136
    global _presentation_data
137
    presentation = _presentation_data.get(resource, {})
138
    if not presentation:
139
        resource_presentation = RESOURCES_PRESENTATION_DATA.get('resources', {})
140
        presentation = resource_presentation.get(resource, {})
141
        _presentation_data[resource] = presentation
142
    return presentation
137
    resource_presentation = _presentation_data.get(resource, {})
138
    if not resource_presentation:
139
        resources_presentation = presentation.RESOURCES.get('resources', {})
140
        resource_presentation = resources_presentation.get(resource, {})
141
        _presentation_data[resource] = resource_presentation
142
    return resource_presentation
143 143

  
144 144
class Resource(models.Model):
145 145
    name = models.CharField(_('Name'), max_length=255, unique=True)
b/snf-astakos-app/astakos/im/presentation.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
RESOURCES_PRESENTATION_DATA = {
34
from astakos.im import settings
35

  
36
RESOURCES = {
35 37
    'groups': {
36 38
        'compute': {
37 39
            'help_text': ('Compute resources '
......
55 57
        },
56 58
    },
57 59
    'resources': {
58
        'pithos+.diskspace': {
60
        'pithos.diskspace': {
59 61
            'help_text': ('This is the space on Pithos for storing files '
60 62
                          'and VM Images. '),
61 63
            'help_text_input_each': ('This is the total amount of space on '
......
65 67
            'report_desc': 'Storage Space',
66 68
            'placeholder': 'eg. 10GB',
67 69
            'verbose_name': 'Storage Space',
70
            'group': 'storage'
68 71
        },
69 72
        'cyclades.disk': {
70 73
            'help_text': ('This is the System Disk that the VMs have that '
......
77 80
            'is_abbreviation': False,
78 81
            'report_desc': 'System Disk',
79 82
            'placeholder': 'eg. 5GB, 2GB etc',
80
            'verbose_name': 'System Disk'
83
            'verbose_name': 'System Disk',
84
            'group': 'compute'
81 85
        },
82 86
        'cyclades.ram': {
83 87
            'help_text': 'RAM used by VMs ',
......
87 91
            'is_abbreviation': True,
88 92
            'report_desc': 'RAM',
89 93
            'placeholder': 'eg. 4GB',
90
            'verbose_name': 'ram'
94
            'verbose_name': 'ram',
95
            'group': 'compute'
96

  
91 97
        },
92 98
        'cyclades.cpu': {
93 99
            'help_text': 'CPUs used by VMs ',
......
97 103
            'is_abbreviation': True,
98 104
            'report_desc': 'CPUs',
99 105
            'placeholder': 'eg. 1',
100
            'verbose_name': 'cpu'
106
            'verbose_name': 'cpu',
107
            'group': 'compute'
108

  
101 109
        },
102 110
        'cyclades.vm': {
103 111
            'help_text': ('These are the VMs one can create on the '
......
109 117
            'report_desc': 'Virtual Machines',
110 118
            'placeholder': 'eg. 2',
111 119
            'verbose_name': 'vm',
120
            'group': 'compute'
121

  
112 122
        },
113 123
        'cyclades.network.private': {
114 124
            'help_text': ('These are the Private Networks one can create on '
......
119 129
            'is_abbreviation': False,
120 130
            'report_desc': 'Private Networks',
121 131
            'placeholder': 'eg. 1',
122
            'verbose_name': 'Private Network'
132
            'verbose_name': 'Private Network',
133
            'group': 'network'
134

  
123 135
        }
124 136
    },
125 137
    'groups_order': ['storage', 'compute', 'network'],
126
    'resources_order': ['pithos+.diskspace',
138
    'resources_order': ['pithos.diskspace',
127 139
                        'cyclades.disk',
128 140
                        'cyclades.cpu',
129 141
                        'cyclades.ram',
b/snf-astakos-app/astakos/im/resources.py
54 54
        old_uplimit = None
55 55

  
56 56
    r.uplimit = uplimit
57
    r.service = s
57
    r.service = service
58 58
    for key, value in resource.iteritems():
59 59
        setattr(r, key, value)
60 60

  
b/snf-astakos-app/astakos/im/templates/im/projects/projectapplication_form.html
113 113
	    	</span>    
114 114
    	</legend>
115 115
    	<ul class="clearfix">
116
    	    {% with object|resource_groups as groups %}
116
            {% with object|resource_groups as groups %}
117 117
            {% for g, group_info in resource_groups.items %}
118 118
                {% if g %}
119 119
	    		<li>
120
	    		    <a href="#{{ g }}" id="{{'group_'|add:g}}" {% if g in groups %}class="selected"{% endif %}><img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
121
	    			<input type="hidden" name="proxy_{{ 'is_selected_'|add:g }}"  id="proxy_{{ 'id_is_selected_'|add:g }}" {% if g in groups %}value="1"{% else %}value="0"{% endif %}>
120
                <a href="#{{ g }}" 
121
                    id="{{'group_'|add:g}}" 
122
                    {% if g in groups %}class="selected"{% endif %}>
123
                    <img src="/static/im/images/create-{{ g }}.png" alt="vm"/></a>
124
                <input type="hidden" name="proxy_{{ 'is_selected_'|add:g }}" 
125
                id="proxy_{{ 'id_is_selected_'|add:g }}" {% if g in groups %}value="1"{% else %}value="0"{% endif %}>
122 126
	    			<input type="hidden" name="{{ 'is_selected_'|add:g }}"  id="{{ 'id_is_selected_'|add:g }}" {% if g in groups %}value="1"{% else %}value="0"{% endif %}>
123 127
	                <p class="msg">{{ group_info.help_text }}</p>
124 128
	    		</li>
......
132 136
    <div class="not-visible">
133 137
    	{% for gname, resources in resource_catalog %}
134 138
     	    <div class="group {{'group_'|add:gname}}" id="{{ gname }}">
135
	    		<a href="#icons" class="delete">X remove resource</a>	
139
                <a href="#icons" class="delete">X remove resource</a>	
136 140
	    		{% for rdata in resources %}
137 141
                {% with rdata.str_repr as rname %}
138 142
	    		<fieldset class="quota">
......
167 171
										{% else %}
168 172
											value = "{% get_grant_value rname form %}"
169 173
										{% endif %}
170
			       						autocomplete="off"			
171
							> 
174
                                        autocomplete="off"> 
172 175
			       			<span class="extra-img">&nbsp;</span>
173 176
			         		<span class="info"><em>more info</em><span>{{ rdata.help_text_input_each }}</span></span>
174 177
			    		</p>
b/snf-astakos-app/astakos/im/views.py
109 109
    PAGINATE_BY_ALL,
110 110
    ACTIVATION_REDIRECT_URL,
111 111
    MODERATION_ENABLED)
112
from astakos.im.presentation import RESOURCES_PRESENTATION_DATA
112
from astakos.im import presentation
113 113
from astakos.im.api import get_services_dict
114 114
from astakos.im import settings as astakos_settings
115 115
from astakos.im.api.callpoint import AstakosCallpoint
......
1042 1042
            populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname))
1043 1043
        return response
1044 1044

  
1045

  
1046
def _resources_catalog(request):
1047
    """
1048
    `resource_catalog` contains a list of tuples. Each tuple contains the group
1049
    key the resource is assigned to and resources list of dicts that contain
1050
    resource information.
1051
    `resource_groups` contains information about the groups
1052
    """
1053
    # presentation data
1054
    resource_groups = presentation.RESOURCES.get('groups', {})
1055
    resource_catalog = ()
1056

  
1057
    # resources in database
1058
    result = callpoint.list_resources()
1059
    if not result.is_success:
1060
        messages.error(request, 'Unable to retrieve system resources: %s' %
1061
                                result.reason)
1062
    else:
1063
        # initialize resource_catalog to contain all group/resource information
1064
        for r in result.data:
1065
            if not r.get('group') in resource_groups:
1066
                resource_groups[r.get('group')] = {'icon': 'unknown'}
1067

  
1068
        resource_keys = [r.get('str_repr') for r in result.data]
1069
        resource_catalog = [[g, filter(lambda r: r.get('group', '') == g,
1070
                                       result.data)] for g in resource_groups]
1071

  
1072
    # order groups, also include unknown groups
1073
    groups_order = presentation.RESOURCES.get('groups_order')
1074
    for g in resource_groups.keys():
1075
        if not g in groups_order:
1076
            groups_order.append(g)
1077

  
1078
    # order resources, also include unknown resources
1079
    resources_order = presentation.RESOURCES.get('resources_order')
1080
    for r in resource_keys:
1081
        if not r in resources_order:
1082
            resources_order.append(r)
1083

  
1084
    # sort catalog groups
1085
    resource_catalog = sorted(resource_catalog,
1086
                              key=lambda g: groups_order.index(g[0]))
1087

  
1088
    # sort groups
1089
    def groupindex(g):
1090
        return groups_order.index(g[0])
1091
    resource_groups_list = sorted([(k, v) for k, v in resource_groups.items()],
1092
                                  key=groupindex)
1093
    resource_groups = OrderedDict(resource_groups_list)
1094

  
1095
    # sort resources
1096
    def resourceindex(r):
1097
        return resources_order.index(r['str_repr'])
1098
    for index, group in enumerate(resource_catalog):
1099
        resource_catalog[index][1] = sorted(resource_catalog[index][1],
1100
                                            key=resourceindex)
1101
        if len(resource_catalog[index][1]) == 0:
1102
            resource_catalog.pop(index)
1103
            for gindex, g in enumerate(resource_groups):
1104
                if g[0] == group[0]:
1105
                    resource_groups.pop(gindex)
1106

  
1107
    return resource_catalog, resource_groups
1108

  
1109

  
1045 1110
@require_http_methods(["GET", "POST"])
1046 1111
@valid_astakos_user_required
1047 1112
def project_add(request):
1048

  
1049 1113
    user = request.user
1050 1114
    reached, limit = reached_pending_application_limit(user.id)
1051 1115
    if not user.is_project_admin() and reached:
......
1055 1119
        next = restrict_next(next, domain=COOKIE_DOMAIN)
1056 1120
        return redirect(next)
1057 1121

  
1058
    resource_groups = RESOURCES_PRESENTATION_DATA.get('groups', {})
1059
    resource_catalog = ()
1060
    result = callpoint.list_resources()
1061
    details_fields = [
1062
        "name", "homepage", "description","start_date","end_date", "comments"]
1063
    membership_fields =[
1064
        "member_join_policy", "member_leave_policy", "limit_on_members_number"]
1065
    if not result.is_success:
1066
        messages.error(
1067
            request,
1068
            'Unable to retrieve system resources: %s' % result.reason
1069
    )
1070
    else:
1071
        resource_catalog = [
1072
            [g, filter(lambda r: r.get('group', '') == g, result.data)] \
1073
                for g in resource_groups]
1074

  
1075
    # order resources
1076
    groups_order = RESOURCES_PRESENTATION_DATA.get('groups_order')
1077
    resources_order = RESOURCES_PRESENTATION_DATA.get('resources_order')
1078
    resource_catalog = sorted(resource_catalog, key=lambda g:groups_order.index(g[0]))
1079

  
1080
    resource_groups_list = sorted([(k,v) for k,v in resource_groups.items()],
1081
                                  key=lambda f:groups_order.index(f[0]))
1082
    resource_groups = OrderedDict(resource_groups_list)
1083
    for index, group in enumerate(resource_catalog):
1084
        resource_catalog[index][1] = sorted(resource_catalog[index][1],
1085
                                            key=lambda r: resources_order.index(r['str_repr']))
1086

  
1087

  
1122
    details_fields = ["name", "homepage", "description", "start_date",
1123
                      "end_date", "comments"]
1124
    membership_fields = ["member_join_policy", "member_leave_policy",
1125
                         "limit_on_members_number"]
1126
    resource_catalog, resource_groups = _resources_catalog(request)
1088 1127
    extra_context = {
1089
        'resource_catalog':resource_catalog,
1090
        'resource_groups':resource_groups,
1091
        'show_form':True,
1092
        'details_fields':details_fields,
1093
        'membership_fields':membership_fields}
1128
        'resource_catalog': resource_catalog,
1129
        'resource_groups': resource_groups,
1130
        'show_form': True,
1131
        'details_fields': details_fields,
1132
        'membership_fields': membership_fields}
1094 1133

  
1095 1134
    response = None
1096 1135
    with ExceptionHandler(request):
......
1186 1225
        next = restrict_next(next, domain=COOKIE_DOMAIN)
1187 1226
        return redirect(next)
1188 1227

  
1189
    resource_groups = RESOURCES_PRESENTATION_DATA.get('groups', {})
1190
    resource_catalog = ()
1191
    result = callpoint.list_resources()
1192
    details_fields = [
1193
        "name", "homepage", "description","start_date","end_date", "comments"]
1194
    membership_fields =[
1195
        "member_join_policy", "member_leave_policy", "limit_on_members_number"]
1196
    if not result.is_success:
1197
        messages.error(
1198
            request,
1199
            'Unable to retrieve system resources: %s' % result.reason
1200
    )
1201
    else:
1202
        resource_catalog = [
1203
            (g, filter(lambda r: r.get('group', '') == g, result.data)) \
1204
                for g in resource_groups]
1228
    details_fields = ["name", "homepage", "description", "start_date",
1229
                      "end_date", "comments"]
1230
    membership_fields = ["member_join_policy", "member_leave_policy",
1231
                         "limit_on_members_number"]
1232
    resource_catalog, resource_groups = _resources_catalog(request)
1205 1233
    extra_context = {
1206
        'resource_catalog':resource_catalog,
1207
        'resource_groups':resource_groups,
1208
        'show_form':True,
1209
        'details_fields':details_fields,
1234
        'resource_catalog': resource_catalog,
1235
        'resource_groups': resource_groups,
1236
        'show_form': True,
1237
        'details_fields': details_fields,
1210 1238
        'update_form': True,
1211
        'membership_fields':membership_fields}
1239
        'membership_fields': membership_fields
1240
    }
1212 1241

  
1213 1242
    response = None
1214 1243
    with ExceptionHandler(request):
1215
        response =_update_object(
1244
        response = _update_object(
1216 1245
            request,
1217 1246
            object_id=application_id,
1218 1247
            template_name='im/projects/projectapplication_form.html',
1219
            extra_context=extra_context, post_save_redirect=reverse('project_list'),
1248
            extra_context=extra_context,
1249
            post_save_redirect=reverse('project_list'),
1220 1250
            form_class=ProjectApplicationForm,
1221
            msg = _("The %(verbose_name)s has been received and "
1222
                    "is under consideration."),
1223
            )
1251
            msg=_("The %(verbose_name)s has been received and is under "
1252
                  "consideration."))
1224 1253

  
1225 1254
    if response is not None:
1226 1255
        return response

Also available in: Unified diff