launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #12879
[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