Merge lp:~newell-jensen/maas/2.0-fix-1608555-1631079 into lp:maas/2.0

Proposed by Newell Jensen
Status: Merged
Approved by: Newell Jensen
Approved revision: 5197
Merged at revision: 5197
Proposed branch: lp:~newell-jensen/maas/2.0-fix-1608555-1631079
Merge into: lp:maas/2.0
Diff against target: 273 lines (+186/-6)
5 files modified
src/maasserver/static/js/angular/controllers/subnet_details.js (+0/-2)
src/maasserver/static/js/angular/controllers/tests/test_subnet_details.js (+0/-4)
src/maasserver/triggers/tests/test_websocket.py (+3/-0)
src/maasserver/triggers/tests/test_websocket_listener.py (+122/-0)
src/maasserver/triggers/websocket.py (+61/-0)
To merge this branch: bzr merge lp:~newell-jensen/maas/2.0-fix-1608555-1631079
Reviewer Review Type Date Requested Status
Newell Jensen (community) Approve
Review via email: mp+308198@code.launchpad.net

Commit message

Backport trunk r5468: Add triggers for updating a subnet when it's IP range is created/updated/deleted.

To post a comment you must log in.
Revision history for this message
Newell Jensen (newell-jensen) wrote :

Self approved backport.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/static/js/angular/controllers/subnet_details.js'
--- src/maasserver/static/js/angular/controllers/subnet_details.js 2016-10-05 20:30:53 +0000
+++ src/maasserver/static/js/angular/controllers/subnet_details.js 2016-10-11 21:19:50 +0000
@@ -244,8 +244,6 @@
244 $scope.ipRangeConfirmDelete = function() {244 $scope.ipRangeConfirmDelete = function() {
245 IPRangesManager.deleteItem($scope.deleteIPRange).then(function() {245 IPRangesManager.deleteItem($scope.deleteIPRange).then(function() {
246 $scope.deleteIPRange = null;246 $scope.deleteIPRange = null;
247 // Reload the subnet after deleting the IP range.
248 $scope.subnet = SubnetsManager.getItem($scope.subnet.id);
249 });247 });
250 };248 };
251249
252250
=== modified file 'src/maasserver/static/js/angular/controllers/tests/test_subnet_details.js'
--- src/maasserver/static/js/angular/controllers/tests/test_subnet_details.js 2016-10-05 20:30:53 +0000
+++ src/maasserver/static/js/angular/controllers/tests/test_subnet_details.js 2016-10-11 21:19:50 +0000
@@ -601,15 +601,12 @@
601601
602 it("calls deleteItem and clears deleteIPRange on resolve", function() {602 it("calls deleteItem and clears deleteIPRange on resolve", function() {
603 var controller = makeController();603 var controller = makeController();
604 var subnet = makeSubnet();
605 var range = {};604 var range = {};
606 $scope.subnet = subnet;
607 $scope.deleteIPRange = range;605 $scope.deleteIPRange = range;
608606
609 var defer = $q.defer();607 var defer = $q.defer();
610 spyOn(IPRangesManager, "deleteItem").and.returnValue(608 spyOn(IPRangesManager, "deleteItem").and.returnValue(
611 defer.promise);609 defer.promise);
612 spyOn(SubnetsManager, "getItem");
613 $scope.ipRangeConfirmDelete();610 $scope.ipRangeConfirmDelete();
614611
615 expect(IPRangesManager.deleteItem).toHaveBeenCalledWith(range);612 expect(IPRangesManager.deleteItem).toHaveBeenCalledWith(range);
@@ -617,7 +614,6 @@
617 $scope.$digest();614 $scope.$digest();
618615
619 expect($scope.deleteIPRange).toBeNull();616 expect($scope.deleteIPRange).toBeNull();
620 expect(SubnetsManager.getItem).toHaveBeenCalledWith(subnet.id);
621 });617 });
622 });618 });
623});619});
624620
=== modified file 'src/maasserver/triggers/tests/test_websocket.py'
--- src/maasserver/triggers/tests/test_websocket.py 2016-06-10 19:32:52 +0000
+++ src/maasserver/triggers/tests/test_websocket.py 2016-10-11 21:19:50 +0000
@@ -90,6 +90,9 @@
90 "dhcpsnippet_dhcpsnippet_create_notify",90 "dhcpsnippet_dhcpsnippet_create_notify",
91 "dhcpsnippet_dhcpsnippet_update_notify",91 "dhcpsnippet_dhcpsnippet_update_notify",
92 "dhcpsnippet_dhcpsnippet_delete_notify",92 "dhcpsnippet_dhcpsnippet_delete_notify",
93 "iprange_iprange_subnet_insert_notify",
94 "iprange_iprange_subnet_update_notify",
95 "iprange_iprange_subnet_delete_notify",
93 ]96 ]
94 sql, args = psql_array(triggers, sql_type="text")97 sql, args = psql_array(triggers, sql_type="text")
95 with closing(connection.cursor()) as cursor:98 with closing(connection.cursor()) as cursor:
9699
=== modified file 'src/maasserver/triggers/tests/test_websocket_listener.py'
--- src/maasserver/triggers/tests/test_websocket_listener.py 2016-06-14 16:43:53 +0000
+++ src/maasserver/triggers/tests/test_websocket_listener.py 2016-10-11 21:19:50 +0000
@@ -13,6 +13,7 @@
13from crochet import wait_for13from crochet import wait_for
14from maasserver.enum import (14from maasserver.enum import (
15 IPADDRESS_TYPE,15 IPADDRESS_TYPE,
16 IPRANGE_TYPE,
16 NODE_TYPE,17 NODE_TYPE,
17)18)
18from maasserver.listener import PostgresListenerService19from maasserver.listener import PostgresListenerService
@@ -2726,6 +2727,127 @@
2726 yield listener.stopService()2727 yield listener.stopService()
27272728
27282729
2730class TestIPRangeSubnetListener(
2731 MAASTransactionServerTestCase, TransactionalHelpersMixin):
2732 """End-to-end test of both the listeners code and the triggers on
2733 maasserver_iprange tables that notifies affected subnets."""
2734
2735 @wait_for_reactor
2736 @inlineCallbacks
2737 def test__calls_handler_on_create_notification(self):
2738 yield deferToDatabase(register_websocket_triggers)
2739 subnet = yield deferToDatabase(
2740 self.create_subnet, {
2741 "cidr": '192.168.0.0/24',
2742 "gateway_ip": '192.168.0.1',
2743 "dns_servers": [],
2744 })
2745
2746 listener = PostgresListenerService()
2747 dv = DeferredValue()
2748 listener.register("subnet", lambda *args: dv.set(args))
2749 yield listener.startService()
2750 try:
2751 iprange = yield deferToDatabase(
2752 self.create_iprange, {
2753 "type": IPRANGE_TYPE.DYNAMIC,
2754 "subnet": subnet,
2755 "start_ip": '192.168.0.100',
2756 "end_ip": '192.168.0.110',
2757 })
2758 yield dv.get(timeout=2)
2759 self.assertEqual(('update', '%s' % iprange.subnet.id), dv.value)
2760 finally:
2761 yield listener.stopService()
2762
2763 @wait_for_reactor
2764 @inlineCallbacks
2765 def test__calls_handler_on_update_notification(self):
2766 yield deferToDatabase(register_websocket_triggers)
2767 iprange = yield deferToDatabase(self.create_iprange)
2768 new_end_ip = factory.pick_ip_in_IPRange(iprange)
2769
2770 listener = PostgresListenerService()
2771 dv = DeferredValue()
2772 listener.register("subnet", lambda *args: dv.set(args))
2773 yield listener.startService()
2774 try:
2775 yield deferToDatabase(
2776 self.update_iprange,
2777 iprange.id, {"end_ip": new_end_ip})
2778 yield dv.get(timeout=2)
2779 self.assertEqual(('update', '%s' % iprange.subnet.id), dv.value)
2780 finally:
2781 yield listener.stopService()
2782
2783 @wait_for_reactor
2784 @inlineCallbacks
2785 def test__calls_handler_on_update_on_old_and_new_subnet_notification(self):
2786 yield deferToDatabase(register_websocket_triggers)
2787 old_subnet = yield deferToDatabase(
2788 self.create_subnet, {
2789 "cidr": '192.168.0.0/24',
2790 "gateway_ip": '192.168.0.1',
2791 "dns_servers": [],
2792 })
2793 new_subnet = yield deferToDatabase(
2794 self.create_subnet, {
2795 "cidr": '192.168.1.0/24',
2796 "gateway_ip": '192.168.1.1',
2797 "dns_servers": [],
2798 })
2799 iprange = yield deferToDatabase(
2800 self.create_iprange, {
2801 "type": IPRANGE_TYPE.DYNAMIC,
2802 "subnet": old_subnet,
2803 "start_ip": '192.168.0.100',
2804 "end_ip": '192.168.0.110',
2805 })
2806 dvs = [DeferredValue(), DeferredValue()]
2807
2808 def set_defer_value(*args):
2809 for dv in dvs:
2810 if not dv.isSet:
2811 dv.set(args)
2812 break
2813
2814 listener = PostgresListenerService()
2815 listener.register("subnet", set_defer_value)
2816 yield listener.startService()
2817 try:
2818 yield deferToDatabase(self.update_iprange, iprange.id, {
2819 "type": IPRANGE_TYPE.DYNAMIC,
2820 "subnet": new_subnet,
2821 "start_ip": '192.168.1.10',
2822 "end_ip": '192.168.1.150',
2823 })
2824 yield dvs[0].get(timeout=2)
2825 yield dvs[1].get(timeout=2)
2826 self.assertItemsEqual([
2827 ('update', '%s' % old_subnet.id),
2828 ('update', '%s' % new_subnet.id),
2829 ], [dvs[0].value, dvs[1].value])
2830 finally:
2831 yield listener.stopService()
2832
2833 @wait_for_reactor
2834 @inlineCallbacks
2835 def test__calls_handler_on_delete_notification(self):
2836 yield deferToDatabase(register_websocket_triggers)
2837 iprange = yield deferToDatabase(self.create_iprange)
2838
2839 listener = PostgresListenerService()
2840 dv = DeferredValue()
2841 listener.register("subnet", lambda *args: dv.set(args))
2842 yield listener.startService()
2843 try:
2844 yield deferToDatabase(self.delete_iprange, iprange.id)
2845 yield dv.get(timeout=2)
2846 self.assertEqual(('update', '%s' % iprange.subnet.id), dv.value)
2847 finally:
2848 yield listener.stopService()
2849
2850
2729class TestNodeTypeChange(2851class TestNodeTypeChange(
2730 MAASTransactionServerTestCase, TransactionalHelpersMixin):2852 MAASTransactionServerTestCase, TransactionalHelpersMixin):
2731 """End-to-end test of node type change triggers code."""2853 """End-to-end test of node type change triggers code."""
27322854
=== modified file 'src/maasserver/triggers/websocket.py'
--- src/maasserver/triggers/websocket.py 2016-06-10 18:53:59 +0000
+++ src/maasserver/triggers/websocket.py 2016-10-11 21:19:50 +0000
@@ -687,6 +687,50 @@
687 $$ LANGUAGE plpgsql;687 $$ LANGUAGE plpgsql;
688 """)688 """)
689689
690# Procedure that is called when an IP range is created to update its related
691# subnet.
692IP_RANGE_SUBNET_INSERT_NOTIFY = dedent("""\
693 CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
694 BEGIN
695 IF NEW.subnet_id IS NOT NULL THEN
696 PERFORM pg_notify('subnet_update',CAST(NEW.subnet_id AS text));
697 END IF;
698 RETURN NEW;
699 END;
700 $$ LANGUAGE plpgsql;
701 """)
702
703# Procedure that is called when an IP range is updated to update its related
704# subnet.
705IP_RANGE_SUBNET_UPDATE_NOTIFY = dedent("""\
706 CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
707 BEGIN
708 IF OLD.subnet_id != NEW.subnet_id THEN
709 IF OLD.subnet_id IS NOT NULL THEN
710 PERFORM pg_notify('subnet_update',CAST(OLD.subnet_id AS text));
711 END IF;
712 END IF;
713 IF NEW.subnet_id IS NOT NULL THEN
714 PERFORM pg_notify('subnet_update',CAST(NEW.subnet_id AS text));
715 END IF;
716 RETURN NEW;
717 END;
718 $$ LANGUAGE plpgsql;
719 """)
720
721# Procedure that is called when an IP range is deleted to update its related
722# subnet.
723IP_RANGE_SUBNET_DELETE_NOTIFY = dedent("""\
724 CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
725 BEGIN
726 IF OLD.subnet_id IS NOT NULL THEN
727 PERFORM pg_notify('subnet_update',CAST(OLD.subnet_id AS text));
728 END IF;
729 RETURN OLD;
730 END;
731 $$ LANGUAGE plpgsql;
732 """)
733
690# Procedure that is called when a DNSData entry is changed.734# Procedure that is called when a DNSData entry is changed.
691DNSDATA_DOMAIN_NOTIFY = dedent("""\735DNSDATA_DOMAIN_NOTIFY = dedent("""\
692 CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$736 CREATE OR REPLACE FUNCTION %s() RETURNS trigger AS $$
@@ -1100,6 +1144,23 @@
1100 "maasserver_staticipaddress",1144 "maasserver_staticipaddress",
1101 "ipaddress_domain_delete_notify", "delete")1145 "ipaddress_domain_delete_notify", "delete")
11021146
1147 # IP range subnet notifications
1148 register_procedure(
1149 IP_RANGE_SUBNET_INSERT_NOTIFY % 'iprange_subnet_insert_notify')
1150 register_procedure(
1151 IP_RANGE_SUBNET_UPDATE_NOTIFY % 'iprange_subnet_update_notify')
1152 register_procedure(
1153 IP_RANGE_SUBNET_DELETE_NOTIFY % 'iprange_subnet_delete_notify')
1154 register_trigger(
1155 "maasserver_iprange",
1156 "iprange_subnet_insert_notify", "insert")
1157 register_trigger(
1158 "maasserver_iprange",
1159 "iprange_subnet_update_notify", "update")
1160 register_trigger(
1161 "maasserver_iprange",
1162 "iprange_subnet_delete_notify", "delete")
1163
1103 # DNSData table1164 # DNSData table
1104 register_procedure(1165 register_procedure(
1105 DNSDATA_DOMAIN_NOTIFY % (1166 DNSDATA_DOMAIN_NOTIFY % (

Subscribers

People subscribed via source and target branches

to all changes: