← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/maas/maas-accept into lp:maas

 

Raphaël Badin has proposed merging lp:~rvb/maas/maas-accept into lp:maas with lp:~rvb/maas/interface-activation-validation as a prerequisite.

Commit message:
Add buttons on the settings page to accept or reject all the pending clusters.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~rvb/maas/maas-accept/+merge/127810

Add buttons on the settings page to accept or reject all the pending clusters.

I can't say it's really pretty but it does the job.
http://people.canonical.com/~rvb/settings_en_mass.png

If one need to accept only some clusters, that can be done by editing the clusters individually, these buttons are only there as a convenience.
-- 
https://code.launchpad.net/~rvb/maas/maas-accept/+merge/127810
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/maas-accept into lp:maas.
=== modified file 'src/maasserver/models/nodegroup.py'
--- src/maasserver/models/nodegroup.py	2012-10-03 15:53:29 +0000
+++ src/maasserver/models/nodegroup.py	2012-10-03 15:53:29 +0000
@@ -111,6 +111,24 @@
         for nodegroup in self.all():
             refresh_worker(nodegroup)
 
+    def _mass_change_status(self, old_status, new_status):
+        nodegroups = self.filter(status=old_status)
+        nb_nodegroups = nodegroups.count()
+        for nodegroup in nodegroups:
+            nodegroup.status = new_status
+            nodegroup.save()
+        return nb_nodegroups
+
+    def reject_all_pending(self):
+        """Change the status of the 'PENDING' nodegroup to 'REJECTED."""
+        return self._mass_change_status(
+            NODEGROUP_STATUS.PENDING, NODEGROUP_STATUS.REJECTED)
+
+    def accept_all_pending(self):
+        """Change the status of the 'PENDING' nodegroup to 'ACCEPTED."""
+        return self._mass_change_status(
+            NODEGROUP_STATUS.PENDING, NODEGROUP_STATUS.ACCEPTED)
+
 
 NODEGROUP_CLUSTER_NAME_TEMPLATE = "Cluster %(uuid)s"
 

=== modified file 'src/maasserver/templates/maasserver/settings_cluster_listing.html'
--- src/maasserver/templates/maasserver/settings_cluster_listing.html	2012-10-02 17:53:24 +0000
+++ src/maasserver/templates/maasserver/settings_cluster_listing.html	2012-10-03 15:53:29 +0000
@@ -15,6 +15,24 @@
     {% endfor %}
   </tbody>
 </table>
+<div>
+  <form id="reject_all_pending_nodegroups"
+        method="POST"
+        action="{% url 'settings' %}">
+    {% csrf_token %}
+    <input type="hidden" name="mass_accept_submit" value="1" />
+    <input type="submit" class="button right" value="Accept all" />
+  </form>
+  <form id="accept_all_pending_nodegroups"
+        method="POST"
+        action="{% url 'settings' %}">
+    {% csrf_token %}
+    <input type="hidden" name="mass_reject_submit" value="1" />
+    <input type="submit" class="button right space-right-small"
+           value="Reject all" />
+  </form>
+</div>
+<div class="clear"></div>
 {% endif %}
 {% if rejected_clusters %}
 <h3 id="rejected-clusters">Rejected clusters</h3>

=== modified file 'src/maasserver/templates/maasserver/settings_cluster_listing_row.html'
--- src/maasserver/templates/maasserver/settings_cluster_listing_row.html	2012-10-02 17:53:24 +0000
+++ src/maasserver/templates/maasserver/settings_cluster_listing_row.html	2012-10-03 15:53:29 +0000
@@ -12,11 +12,5 @@
        href="{% url 'cluster-delete' cluster.uuid %}">
        <img src="{{ STATIC_URL }}img/delete.png" alt="delete" />
     </a>
-    <form method="POST"
-          action="{% url 'settings' %}">
-      {% csrf_token %}
-      <input type="hidden" name="uuid"
-             value="{{ cluster.uuid }}" />
-    </form>
   </td>
 </tr>

=== modified file 'src/maasserver/tests/test_nodegroup.py'
--- src/maasserver/tests/test_nodegroup.py	2012-09-30 21:48:47 +0000
+++ src/maasserver/tests/test_nodegroup.py	2012-10-03 15:53:29 +0000
@@ -174,6 +174,50 @@
             NodeGroup.objects.get_by_natural_key,
             factory.make_name("nonexistent-nodegroup"))
 
+    def test__mass_change_status_changes_statuses(self):
+        old_status = factory.getRandomEnum(NODEGROUP_STATUS)
+        nodegroup1 = factory.make_node_group(status=old_status)
+        nodegroup2 = factory.make_node_group(status=old_status)
+        new_status = factory.getRandomEnum(
+            NODEGROUP_STATUS, but_not=[old_status])
+        changed = NodeGroup.objects._mass_change_status(old_status, new_status)
+        self.assertEqual(
+            (
+                reload_object(nodegroup1).status,
+                reload_object(nodegroup2).status,
+                2,
+            ),
+            (
+                new_status,
+                new_status,
+                changed,
+            ))
+
+    def test__mass_change_status_does_not_change_others(self):
+        old_status = factory.getRandomEnum(NODEGROUP_STATUS)
+        unaffected_status = factory.getRandomEnum(
+            NODEGROUP_STATUS, but_not=[old_status])
+        nodegroup = factory.make_node_group(status=unaffected_status)
+        changed = NodeGroup.objects._mass_change_status(
+            old_status, factory.getRandomEnum(NODEGROUP_STATUS))
+        self.assertEqual(
+            (unaffected_status, 0),
+            (reload_object(nodegroup).status, changed))
+
+    def test_reject_all_pending_rejects_nodegroups(self):
+        nodegroup = factory.make_node_group(status=NODEGROUP_STATUS.PENDING)
+        changed = NodeGroup.objects.reject_all_pending()
+        self.assertEqual(
+            (NODEGROUP_STATUS.REJECTED, 1),
+            (reload_object(nodegroup).status, changed))
+
+    def test_accept_all_pending_accepts_nodegroups(self):
+        nodegroup = factory.make_node_group(status=NODEGROUP_STATUS.PENDING)
+        changed = NodeGroup.objects.accept_all_pending()
+        self.assertEqual(
+            (NODEGROUP_STATUS.ACCEPTED, 1),
+            (reload_object(nodegroup).status, changed))
+
 
 class TestNodeGroup(TestCase):
 

=== modified file 'src/maasserver/tests/test_views_settings.py'
--- src/maasserver/tests/test_views_settings.py	2012-09-27 13:50:34 +0000
+++ src/maasserver/tests/test_views_settings.py	2012-10-03 15:53:29 +0000
@@ -21,6 +21,7 @@
 from maasserver.enum import (
     DISTRO_SERIES,
     NODE_AFTER_COMMISSIONING_ACTION,
+    NODEGROUP_STATUS,
     )
 from maasserver.models import (
     Config,
@@ -173,6 +174,41 @@
             choices + [['my.hostname.com', 'my.hostname.com']],
             new_choices)
 
+    def test_settings_contains_form_to_accept_all_nodegroups(self):
+        factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
+        response = self.client.get('/settings/')
+        doc = fromstring(response.content)
+        forms = doc.cssselect('form#accept_all_pending_nodegroups')
+        self.assertEqual(1, len(forms))
+
+    def test_settings_contains_form_to_reject_all_nodegroups(self):
+        factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
+        response = self.client.get('/settings/')
+        doc = fromstring(response.content)
+        forms = doc.cssselect('form#reject_all_pending_nodegroups')
+        self.assertEqual(1, len(forms))
+
+    def test_settings_accepts_all_pending_nodegroups_POST(self):
+        nodegroups = {
+            factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
+            factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
+        }
+        response = self.client.post('/settings/', {'mass_accept_submit': 1})
+        self.assertEqual(httplib.FOUND, response.status_code)
+        self.assertEqual(
+            [reload_object(nodegroup).status for nodegroup in nodegroups],
+            [NODEGROUP_STATUS.ACCEPTED] * 2)
+
+    def test_settings_rejects_all_pending_nodegroups_POST(self):
+        nodegroups = {
+            factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
+            factory.make_node_group(status=NODEGROUP_STATUS.PENDING),
+        }
+        response = self.client.post('/settings/', {'mass_reject_submit': 1})
+        self.assertEqual(httplib.FOUND, response.status_code)
+        self.assertEqual(
+            [reload_object(nodegroup).status for nodegroup in nodegroups],
+            [NODEGROUP_STATUS.REJECTED] * 2)
 
 # Settable attributes on User.
 user_attributes = [

=== modified file 'src/maasserver/views/settings.py'
--- src/maasserver/views/settings.py	2012-10-02 17:53:24 +0000
+++ src/maasserver/views/settings.py	2012-10-03 15:53:29 +0000
@@ -177,7 +177,19 @@
     if response is not None:
         return response
 
-    # Cluster settings:
+    # Process accept clusters en masse.
+    if 'mass_accept_submit' in request.POST:
+        number = NodeGroup.objects.accept_all_pending()
+        messages.info(request, "Accepted %d cluster(s)." % number)
+        return HttpResponseRedirect(reverse('settings'))
+
+    # Process reject clusters en masse.
+    if 'mass_reject_submit' in request.POST:
+        number = NodeGroup.objects.reject_all_pending()
+        messages.info(request, "Rejected %d cluster(s)." % number)
+        return HttpResponseRedirect(reverse('settings'))
+
+    # Cluster listings:
     accepted_clusters = NodeGroup.objects.filter(
         status=NODEGROUP_STATUS.ACCEPTED).order_by('cluster_name')
     pending_clusters = NodeGroup.objects.filter(


Follow ups