~lutostag/ubuntu/utopic/maas/1.5.2

« back to all changes in this revision

Viewing changes to src/maasserver/views/nodes.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-06-03 17:59:31 UTC
  • mto: This revision was merged to the branch mainline in revision 31.
  • Revision ID: package-import@ubuntu.com-20130603175931-1ifwga0vj04p8vu6
Tags: upstream-1.4+bzr1527+dfsg
ImportĀ upstreamĀ versionĀ 1.4+bzr1527+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
    ]
23
23
 
24
24
from logging import getLogger
 
25
from urllib import urlencode
25
26
 
26
27
from django.conf import settings as django_settings
27
28
from django.contrib import messages
38
39
    DetailView,
39
40
    UpdateView,
40
41
    )
 
42
from django.views.generic.edit import (
 
43
    FormMixin,
 
44
    ProcessFormView,
 
45
    )
41
46
from maasserver.enum import (
42
47
    NODE_PERMISSION,
43
48
    NODE_STATUS,
49
54
    NoSuchConstraint,
50
55
    )
51
56
from maasserver.forms import (
 
57
    BulkNodeActionForm,
52
58
    get_action_form,
53
59
    get_node_edit_form,
54
60
    MACAddressForm,
61
67
    )
62
68
from maasserver.models.node import CONSTRAINTS_JUJU_MAP
63
69
from maasserver.models.node_constraint_filter import constrain_nodes
 
70
from maasserver.node_action import ACTIONS_DICT
64
71
from maasserver.preseed import (
65
72
    get_enlist_preseed,
66
73
    get_preseed,
105
112
    return constraints
106
113
 
107
114
 
 
115
def message_from_form_stats(action, done, not_actionable, not_permitted):
 
116
    """Return a message suitable for user display from the given stats."""
 
117
    action_name = 'The action "%s"' % action.display_bulk
 
118
    # singular/plural messages.
 
119
    done_templates = [
 
120
        '%s was successfully performed on %d node.',
 
121
        '%s was successfully performed on %d nodes.'
 
122
    ]
 
123
    not_actionable_templates = [
 
124
        ('%s could not be performed on %d node because its '
 
125
         'state does not allow that action.'),
 
126
        ('%s could not be performed on %d nodes because their '
 
127
         'state does not allow that action.'),
 
128
    ]
 
129
    not_permitted_templates = [
 
130
        ('%s could not be performed on %d node because you '
 
131
         "don't have the required permissions."),
 
132
        ('%s could not be performed on %d nodes because you '
 
133
         "don't have the required permissions."),
 
134
    ]
 
135
    number_message = [
 
136
        (done, done_templates),
 
137
        (not_actionable, not_actionable_templates),
 
138
        (not_permitted, not_permitted_templates)]
 
139
    message = []
 
140
    for number, message_templates in number_message:
 
141
        singular, plural = message_templates
 
142
        if number != 0:
 
143
            message_template = singular if number == 1 else plural
 
144
            message.append(message_template % (action_name, number))
 
145
            # Override the action name so that only the first sentence will
 
146
            # contain the full name of the action.
 
147
            action_name = 'It'
 
148
    return ' '.join(message)
 
149
 
 
150
 
108
151
def prefetch_nodes_listing(nodes_query):
109
152
    """Prefetch any data needed to display a given query of nodes.
110
153
 
119
162
            .prefetch_related('nodegroup__nodegroupinterface_set'))
120
163
 
121
164
 
122
 
class NodeListView(PaginatedListView):
 
165
class NodeListView(PaginatedListView, FormMixin, ProcessFormView):
123
166
 
124
167
    context_object_name = "node_list"
 
168
    form_class = BulkNodeActionForm
125
169
 
126
 
    def get(self, request, *args, **kwargs):
 
170
    def populate_modifiers(self, request):
127
171
        self.query = request.GET.get("query")
128
172
        self.query_error = None
129
173
        self.sort_by = request.GET.get("sort")
130
174
        self.sort_dir = request.GET.get("dir")
131
175
 
 
176
    def get(self, request, *args, **kwargs):
 
177
        """Handle a GET request."""
 
178
        self.populate_modifiers(request)
132
179
        return super(NodeListView, self).get(request, *args, **kwargs)
133
180
 
 
181
    def get_preserved_params(self):
 
182
        """List of GET parameters that need to be preserved by POST
 
183
        requests.
 
184
 
 
185
        These are sorting and search option we want a POST request to
 
186
        preserve so that the display after a POST request is similar
 
187
        to the display before the request."""
 
188
        return ["dir", "query", "page", "sort"]
 
189
 
 
190
    def get_preserved_query(self):
 
191
        params = {
 
192
            param: self.request.GET.get(param)
 
193
            for param in self.get_preserved_params()
 
194
            if self.request.GET.get(param) is not None}
 
195
        return urlencode(params)
 
196
 
 
197
    def get_next_url(self):
 
198
        return reverse('node-list') + "?" + self.get_preserved_query()
 
199
 
 
200
    def get_success_url(self):
 
201
        return self.get_next_url()
 
202
 
 
203
    def get_form_kwargs(self):
 
204
        kwargs = super(NodeListView, self).get_form_kwargs()
 
205
        kwargs['user'] = self.request.user
 
206
        return kwargs
 
207
 
 
208
    def post(self, request, *args, **kwargs):
 
209
        """Handle a POST request."""
 
210
        self.populate_modifiers(request)
 
211
        return super(NodeListView, self).post(request, *args, **kwargs)
 
212
 
 
213
    def form_invalid(self, form):
 
214
        """Handle the view response when the form is invalid."""
 
215
        self.object_list = self.get_queryset()
 
216
        context = self.get_context_data(
 
217
            object_list=self.object_list,
 
218
            form=form)
 
219
        return self.render_to_response(context)
 
220
 
 
221
    def form_valid(self, form):
 
222
        """Handle the view response when the form is valid."""
 
223
        stats = form.save()
 
224
        action_class = ACTIONS_DICT[form.cleaned_data['action']]
 
225
        message = message_from_form_stats(action_class, *stats)
 
226
        messages.info(self.request, message)
 
227
        return super(NodeListView, self).form_valid(form)
 
228
 
134
229
    def _compose_sort_order(self):
135
230
        """Put together a tuple describing the sort order.
136
231
 
199
294
    def get_context_data(self, **kwargs):
200
295
        context = super(NodeListView, self).get_context_data(**kwargs)
201
296
        context.update(get_longpoll_context())
 
297
        form_class = self.get_form_class()
 
298
        form = self.get_form(form_class)
 
299
        context["preserved_query"] = self.get_preserved_query()
 
300
        context["form"] = form
202
301
        context["input_query"] = self.query
203
302
        context["input_query_error"] = self.query_error
204
303
        links, classes = self._prepare_sort_links()
259
358
# or READY nodes.
260
359
NODE_BOOT_INFO = mark_safe("""
261
360
You can boot this node using Avahi-enabled boot media or an adequately
262
 
configured dhcp server.  See
263
 
<a href="https://wiki.ubuntu.com/ServerTeam/MAAS/AvahiBoot">
264
 
https://wiki.ubuntu.com/ServerTeam/MAAS/AvahiBoot</a> for instructions.
 
361
configured DHCP server.  See
 
362
<a href="https://maas.ubuntu.com/docs/nodes.html"
 
363
>https://maas.ubuntu.com/docs/nodes.html</a> for instructions.
265
364
""")
266
365
 
267
366