Merge ~cgrabowski/maas:add_update_interface_back_to_controller_ws_handler into maas:master

Proposed by Christian Grabowski
Status: Merged
Approved by: Christian Grabowski
Approved revision: 624798b11123c4696d80371ff66ab1b3487e76e8
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~cgrabowski/maas:add_update_interface_back_to_controller_ws_handler
Merge into: maas:master
Diff against target: 288 lines (+115/-79)
4 files modified
src/maasserver/websockets/handlers/controller.py (+7/-5)
src/maasserver/websockets/handlers/machine.py (+0/-74)
src/maasserver/websockets/handlers/node.py (+81/-0)
src/maasserver/websockets/handlers/tests/test_controller.py (+27/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Alexsander de Souza Approve
Review via email: mp+427457@code.launchpad.net

Commit message

ensure node is up to date before dehydrating

include controller interface form

use boot interface in test

move _update_obj_tags to the Node handler for both Controller and Machine handlers

move form import to correct file

move _get_node_or_permission_error to Node handler for use with Controller and Machine handlers

move update_interface into Node handler for controller to inherit

To post a comment you must log in.
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add_update_interface_back_to_controller_ws_handler lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/176/consoleText
COMMIT: c04185ec71067a6e098994170d848d5506a57fe1

review: Needs Fixing
Revision history for this message
Alexsander de Souza (alexsander-souza) wrote :

+1

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add_update_interface_back_to_controller_ws_handler lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/178/consoleText
COMMIT: 624798b11123c4696d80371ff66ab1b3487e76e8

review: Needs Fixing
Revision history for this message
Christian Grabowski (cgrabowski) wrote :

jenkins: !test

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add_update_interface_back_to_controller_ws_handler lp:~cgrabowski/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 624798b11123c4696d80371ff66ab1b3487e76e8

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/maasserver/websockets/handlers/controller.py b/src/maasserver/websockets/handlers/controller.py
index dad5976..609526a 100644
--- a/src/maasserver/websockets/handlers/controller.py
+++ b/src/maasserver/websockets/handlers/controller.py
@@ -90,6 +90,7 @@ class ControllerHandler(NodeHandler):
90 "set_script_result_suppressed",90 "set_script_result_suppressed",
91 "set_script_result_unsuppressed",91 "set_script_result_unsuppressed",
92 "get_latest_failed_testing_script_results",92 "get_latest_failed_testing_script_results",
93 "update_interface",
93 ]94 ]
94 form = ControllerForm95 form = ControllerForm
95 exclude = [96 exclude = [
@@ -168,7 +169,11 @@ class ControllerHandler(NodeHandler):
168 data = super().dehydrate(obj, data, for_list=for_list)169 data = super().dehydrate(obj, data, for_list=for_list)
169170
170 vlan_counts = Counter()171 vlan_counts = Counter()
171 for vlan_id in obj.vlan_ids:172 vlan_ids = [
173 interface.vlan_id
174 for interface in obj.current_config.interface_set.all()
175 ]
176 for vlan_id in vlan_ids:
172 vlan_counts[self._vlans_ha[vlan_id]] += 1177 vlan_counts[self._vlans_ha[vlan_id]] += 1
173178
174 data.update(179 data.update(
@@ -184,10 +189,7 @@ class ControllerHandler(NodeHandler):
184 }189 }
185 )190 )
186 if not for_list:191 if not for_list:
187 data["vlan_ids"] = [192 data["vlan_ids"] = vlan_ids
188 interface.vlan_id
189 for interface in obj.current_config.interface_set.all()
190 ]
191193
192 # include certificate info if present194 # include certificate info if present
193 certificate = obj.power_parameters.get("certificate")195 certificate = obj.power_parameters.get("certificate")
diff --git a/src/maasserver/websockets/handlers/machine.py b/src/maasserver/websockets/handlers/machine.py
index 5a67786..a64d51d 100644
--- a/src/maasserver/websockets/handlers/machine.py
+++ b/src/maasserver/websockets/handlers/machine.py
@@ -45,8 +45,6 @@ from maasserver.forms.interface import (
45 AcquiredBridgeInterfaceForm,45 AcquiredBridgeInterfaceForm,
46 BondInterfaceForm,46 BondInterfaceForm,
47 BridgeInterfaceForm,47 BridgeInterfaceForm,
48 DeployedInterfaceForm,
49 InterfaceForm,
50 PhysicalInterfaceForm,48 PhysicalInterfaceForm,
51 VLANInterfaceForm,49 VLANInterfaceForm,
52)50)
@@ -655,11 +653,6 @@ class MachineHandler(NodeHandler):
655 else:653 else:
656 form.save()654 form.save()
657655
658 def _update_obj_tags(self, obj, params):
659 if "tags" in params:
660 obj.tags = params["tags"]
661 obj.save(update_fields=["tags"])
662
663 def update_disk(self, params):656 def update_disk(self, params):
664 """Update disk information."""657 """Update disk information."""
665 node = self._get_node_or_permission_error(658 node = self._get_node_or_permission_error(
@@ -1079,28 +1072,6 @@ class MachineHandler(NodeHandler):
1079 else:1072 else:
1080 raise ValidationError(form.errors)1073 raise ValidationError(form.errors)
10811074
1082 def update_interface(self, params):
1083 """Update the interface."""
1084 node = self._get_node_or_permission_error(
1085 params, permission=self._meta.edit_permission
1086 )
1087 interface = Interface.objects.get(
1088 node_config__node=node, id=params["interface_id"]
1089 )
1090 if node.status == NODE_STATUS.DEPLOYED:
1091 interface_form = DeployedInterfaceForm
1092 else:
1093 interface_form = InterfaceForm.get_interface_form(interface.type)
1094 form = interface_form(instance=interface, data=params)
1095 if form.is_valid():
1096 interface = form.save()
1097 self._update_obj_tags(interface, params)
1098 else:
1099 raise ValidationError(form.errors)
1100 if "mode" in params:
1101 self.link_subnet(params)
1102 return self.full_dehydrate(node)
1103
1104 def delete_interface(self, params):1075 def delete_interface(self, params):
1105 """Delete the interface."""1076 """Delete the interface."""
1106 node = self._get_node_or_permission_error(1077 node = self._get_node_or_permission_error(
@@ -1111,45 +1082,6 @@ class MachineHandler(NodeHandler):
1111 )1082 )
1112 interface.delete()1083 interface.delete()
11131084
1114 def link_subnet(self, params):
1115 """Create or update the link."""
1116 node = self._get_node_or_permission_error(
1117 params, permission=self._meta.edit_permission
1118 )
1119 interface = Interface.objects.get(
1120 node_config__node=node, id=params["interface_id"]
1121 )
1122 subnet = None
1123 if "subnet" in params:
1124 subnet = Subnet.objects.get(id=params["subnet"])
1125 if "link_id" in params:
1126 if interface.ip_addresses.filter(id=params["link_id"]).exists():
1127 # We are updating an already existing link. Which may have
1128 # been deleted.
1129 interface.update_link_by_id(
1130 params["link_id"],
1131 params["mode"],
1132 subnet,
1133 ip_address=params.get("ip_address", None),
1134 )
1135 else:
1136 # We are creating a new link.
1137 interface.link_subnet(
1138 params["mode"],
1139 subnet,
1140 ip_address=params.get("ip_address", None),
1141 )
1142
1143 def unlink_subnet(self, params):
1144 """Delete the link."""
1145 node = self._get_node_or_permission_error(
1146 params, permission=self._meta.edit_permission
1147 )
1148 interface = Interface.objects.get(
1149 node_config__node=node, id=params["interface_id"]
1150 )
1151 interface.unlink_subnet_by_id(params["link_id"])
1152
1153 @asynchronous(timeout=45)1085 @asynchronous(timeout=45)
1154 def check_power(self, params):1086 def check_power(self, params):
1155 """Check the power state of the node."""1087 """Check the power state of the node."""
@@ -1178,12 +1110,6 @@ class MachineHandler(NodeHandler):
1178 d.addCallback(partial(deferToDatabase, update_state))1110 d.addCallback(partial(deferToDatabase, update_state))
1179 return d1111 return d
11801112
1181 def _get_node_or_permission_error(self, params, permission=None):
1182 node = self.get_object(params, permission=permission)
1183 if node.locked:
1184 raise HandlerPermissionError()
1185 return node
1186
1187 def get_workload_annotations(self, params):1113 def get_workload_annotations(self, params):
1188 """Get the owner data for a machine, known as workload annotations."""1114 """Get the owner data for a machine, known as workload annotations."""
1189 machine = self._get_node_or_permission_error(1115 machine = self._get_node_or_permission_error(
diff --git a/src/maasserver/websockets/handlers/node.py b/src/maasserver/websockets/handlers/node.py
index d6ce3f9..77b6dfc 100644
--- a/src/maasserver/websockets/handlers/node.py
+++ b/src/maasserver/websockets/handlers/node.py
@@ -10,6 +10,7 @@ from itertools import chain
10import logging10import logging
11from operator import attrgetter, itemgetter11from operator import attrgetter, itemgetter
1212
13from django.core.exceptions import ValidationError
13from django.db.models import Model, Prefetch14from django.db.models import Model, Prefetch
14from lxml import etree15from lxml import etree
1516
@@ -26,6 +27,11 @@ from maasserver.enum import (
26 POWER_STATE_CHOICES,27 POWER_STATE_CHOICES,
27)28)
28from maasserver.forms import list_all_usable_architectures29from maasserver.forms import list_all_usable_architectures
30from maasserver.forms.interface import (
31 ControllerInterfaceForm,
32 DeployedInterfaceForm,
33 InterfaceForm,
34)
29from maasserver.models import (35from maasserver.models import (
30 BlockDevice,36 BlockDevice,
31 BMC,37 BMC,
@@ -1433,3 +1439,78 @@ class NodeHandler(TimestampedModelHandler):
1433 if key == "mem":1439 if key == "mem":
1434 return self._get_dynamic_filter_options("memory")1440 return self._get_dynamic_filter_options("memory")
1435 return self._get_dynamic_filter_options(key)1441 return self._get_dynamic_filter_options(key)
1442
1443 def update_interface(self, params):
1444 """Update the interface."""
1445 node = self._get_node_or_permission_error(
1446 params, permission=self._meta.edit_permission
1447 )
1448 interface = Interface.objects.get(
1449 node_config__node=node, id=params["interface_id"]
1450 )
1451 if node.is_controller:
1452 interface_form = ControllerInterfaceForm
1453 elif node.status == NODE_STATUS.DEPLOYED:
1454 interface_form = DeployedInterfaceForm
1455 else:
1456 interface_form = InterfaceForm.get_interface_form(interface.type)
1457 form = interface_form(instance=interface, data=params)
1458 if form.is_valid():
1459 interface = form.save()
1460 self._update_obj_tags(interface, params)
1461 else:
1462 raise ValidationError(form.errors)
1463 if "mode" in params:
1464 self.link_subnet(params)
1465 node.refresh_from_db()
1466 return self.full_dehydrate(node)
1467
1468 def _get_node_or_permission_error(self, params, permission=None):
1469 node = self.get_object(params, permission=permission)
1470 if node.locked:
1471 raise HandlerPermissionError()
1472 return node
1473
1474 def _update_obj_tags(self, obj, params):
1475 if "tags" in params:
1476 obj.tags = params["tags"]
1477 obj.save(update_fields=["tags"])
1478
1479 def link_subnet(self, params):
1480 """Create or update the link."""
1481 node = self._get_node_or_permission_error(
1482 params, permission=self._meta.edit_permission
1483 )
1484 interface = Interface.objects.get(
1485 node_config__node=node, id=params["interface_id"]
1486 )
1487 subnet = None
1488 if "subnet" in params:
1489 subnet = Subnet.objects.get(id=params["subnet"])
1490 if "link_id" in params:
1491 if interface.ip_addresses.filter(id=params["link_id"]).exists():
1492 # We are updating an already existing link. Which may have
1493 # been deleted.
1494 interface.update_link_by_id(
1495 params["link_id"],
1496 params["mode"],
1497 subnet,
1498 ip_address=params.get("ip_address", None),
1499 )
1500 else:
1501 # We are creating a new link.
1502 interface.link_subnet(
1503 params["mode"],
1504 subnet,
1505 ip_address=params.get("ip_address", None),
1506 )
1507
1508 def unlink_subnet(self, params):
1509 """Delete the link."""
1510 node = self._get_node_or_permission_error(
1511 params, permission=self._meta.edit_permission
1512 )
1513 interface = Interface.objects.get(
1514 node_config__node=node, id=params["interface_id"]
1515 )
1516 interface.unlink_subnet_by_id(params["link_id"])
diff --git a/src/maasserver/websockets/handlers/tests/test_controller.py b/src/maasserver/websockets/handlers/tests/test_controller.py
index 59a3278..f961ede 100644
--- a/src/maasserver/websockets/handlers/tests/test_controller.py
+++ b/src/maasserver/websockets/handlers/tests/test_controller.py
@@ -490,3 +490,30 @@ class TestControllerHandler(MAASServerTestCase):
490 controller.refresh_from_db()490 controller.refresh_from_db()
491 # deleting a region+rack controller changes it to just a region controller491 # deleting a region+rack controller changes it to just a region controller
492 self.assertEqual(controller.node_type, NODE_TYPE.REGION_CONTROLLER)492 self.assertEqual(controller.node_type, NODE_TYPE.REGION_CONTROLLER)
493
494 def test_update_interface(self):
495 admin = factory.make_admin()
496 vlan = factory.make_VLAN()
497 handler = ControllerHandler(admin, {}, None)
498 controller = factory.make_RegionRackController()
499 request = {
500 "name": controller.boot_interface.name,
501 "mac_address": controller.boot_interface.mac_address,
502 "tags": [],
503 "fabric": vlan.fabric.id,
504 "vlan": vlan.id,
505 "mode": "link_up",
506 "link_connected": True,
507 "link_speed": 0,
508 "interface_speed": 0,
509 "formatted_link_speed": 0,
510 "formatted_interface_speed": 0,
511 "type": controller.boot_interface.type,
512 "parents": controller.boot_interface.parents,
513 "primary": None,
514 "system_id": controller.system_id,
515 "interface_id": controller.boot_interface.id,
516 }
517 handler.update_interface(request)
518 controller.refresh_from_db()
519 self.assertEqual(controller.boot_interface.vlan, vlan)

Subscribers

People subscribed via source and target branches