Merge ~lloydwaltersj/maas:add-machine-count into maas:master

Proposed by Jack Lloyd-Walters
Status: Merged
Approved by: Jack Lloyd-Walters
Approved revision: 539c8f98deea3870b92f461b548c42964a4b54cb
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~lloydwaltersj/maas:add-machine-count
Merge into: maas:master
Diff against target: 181 lines (+116/-1)
2 files modified
src/maasserver/websockets/handlers/bootresource.py (+59/-1)
src/maasserver/websockets/handlers/tests/test_bootresource.py (+57/-0)
Reviewer Review Type Date Requested Status
Anton Troyanov Approve
Christian Grabowski Approve
MAAS Lander Approve
Review via email: mp+436064@code.launchpad.net

Commit message

Introduce machineCount to the UI

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

UNIT TESTS
-b add-machine-count lp:~lloydwaltersj/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas-tester/1839/consoleText
COMMIT: 6e835aca9d485a73a05282422ac86ebf59bf07b5

review: Needs Fixing
Revision history for this message
Adam Collard (adam-collard) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b add-machine-count lp:~lloydwaltersj/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 8eb01a9d5667ef6d74d3d55c31ca130ed5f336ed

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

UNIT TESTS
-b add-machine-count lp:~lloydwaltersj/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 539c8f98deea3870b92f461b548c42964a4b54cb

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

+1

review: Approve
Revision history for this message
Anton Troyanov (troyanov) wrote :

LGTM!

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

UNABLE TO START LANDING

STATUS: MISSING COMMIT MESSAGE

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

UNABLE TO START LANDING

STATUS: MISSING COMMIT MESSAGE

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/websockets/handlers/bootresource.py b/src/maasserver/websockets/handlers/bootresource.py
2index fa4b17c..66d45b9 100644
3--- a/src/maasserver/websockets/handlers/bootresource.py
4+++ b/src/maasserver/websockets/handlers/bootresource.py
5@@ -26,7 +26,7 @@ from maasserver.clusterrpc.boot_images import (
6 get_common_available_boot_images,
7 is_import_boot_images_running,
8 )
9-from maasserver.enum import BOOT_RESOURCE_TYPE, NODE_STATUS
10+from maasserver.enum import BOOT_RESOURCE_TYPE, NODE_STATUS, NODE_TYPE
11 from maasserver.models import (
12 BootResource,
13 BootSource,
14@@ -252,6 +252,11 @@ class BootResourceHandler(Handler):
15 resource.number_of_nodes = self.get_number_of_nodes_deployed_for(
16 resource
17 )
18+ resource.machine_count = (
19+ self.get_number_of_nodes_of_node_type_deployed_for(
20+ resource, NODE_TYPE.MACHINE
21+ )
22+ )
23 resource_set = resource.get_latest_set()
24 if resource_set is None:
25 resource.size = human_readable_bytes(0)
26@@ -378,6 +383,43 @@ class BootResourceHandler(Handler):
27 count += 1
28 return count
29
30+ def get_number_of_nodes_of_node_type_deployed_for(
31+ self, resource, node_type=NODE_TYPE.MACHINE
32+ ):
33+ """Return number of nodes of node_type='node_type' that are deploying the given
34+ os, series, and architecture."""
35+ if resource.rtype == BOOT_RESOURCE_TYPE.UPLOADED:
36+ osystem = "custom"
37+ distro_series = resource.name
38+ else:
39+ osystem, distro_series = resource.name.split("/")
40+
41+ # Count the number of nodes with same os/release and architecture.
42+ count = sum(
43+ 1
44+ for node in self.nodes.filter(
45+ osystem=osystem,
46+ distro_series=distro_series,
47+ node_type=node_type,
48+ )
49+ if self.node_has_architecture_for_resource(node, resource)
50+ )
51+
52+ # Any node that is deployed without osystem and distro_series,
53+ # will be using the defaults.
54+ if (
55+ self.default_osystem == osystem
56+ and self.default_distro_series == distro_series
57+ ):
58+ count += sum(
59+ 1
60+ for node in self.nodes.filter(
61+ osystem="", distro_series="", node_type=node_type
62+ )
63+ if self.node_has_architecture_for_resource(node, resource)
64+ )
65+ return count
66+
67 def pick_latest_datetime(
68 self, time: datetime, other_time: datetime
69 ) -> datetime:
70@@ -437,6 +479,17 @@ class BootResourceHandler(Handler):
71 for resource in resources
72 )
73
74+ def get_number_of_nodes_of_node_type_for_resources(
75+ self, resources, node_type=NODE_TYPE.MACHINE
76+ ):
77+ """Return the number of nodes of node_type='node_type' used by all resources"""
78+ return sum(
79+ self.get_number_of_nodes_of_node_type_deployed_for(
80+ resource, node_type
81+ )
82+ for resource in resources
83+ )
84+
85 def get_last_deployed_for_resources(
86 self, resources: list[BootResource]
87 ) -> Optional[datetime]:
88@@ -496,6 +549,9 @@ class BootResourceHandler(Handler):
89 last_update = self.get_last_update_for_resources(group)
90 unique_size = self.calculate_unique_size_for_resources(group)
91 number_of_nodes = self.get_number_of_nodes_for_resources(group)
92+ machine_count = self.get_number_of_nodes_of_node_type_for_resources(
93+ group, NODE_TYPE.MACHINE
94+ )
95 complete = self.are_all_resources_complete(group)
96 progress = self.get_progress_for_resources(group)
97 last_deployed = self.get_last_deployed_for_resources(group)
98@@ -509,6 +565,7 @@ class BootResourceHandler(Handler):
99 resource.size = human_readable_bytes(unique_size)
100 resource.last_update = last_update
101 resource.number_of_nodes = number_of_nodes
102+ resource.machine_count = machine_count
103 resource.last_deployed = last_deployed
104 resource.complete = complete
105 if not complete:
106@@ -615,6 +672,7 @@ class BootResourceHandler(Handler):
107 "icon": resource.icon,
108 "downloading": resource.downloading,
109 "numberOfNodes": resource.number_of_nodes,
110+ "machineCount": resource.machine_count,
111 "lastUpdate": resource.last_update.strftime(
112 "%a, %d %b. %Y %H:%M:%S"
113 ),
114diff --git a/src/maasserver/websockets/handlers/tests/test_bootresource.py b/src/maasserver/websockets/handlers/tests/test_bootresource.py
115index 96c773f..01bda2c 100644
116--- a/src/maasserver/websockets/handlers/tests/test_bootresource.py
117+++ b/src/maasserver/websockets/handlers/tests/test_bootresource.py
118@@ -390,6 +390,63 @@ class TestBootResourcePoll(MAASServerTestCase, PatchOSInfoMixin):
119 start_time,
120 )
121
122+ def test_shows_latest_deployment_time(self) -> None:
123+ owner = factory.make_admin()
124+ handler = BootResourceHandler(owner, {}, None)
125+ resource = factory.make_usable_boot_resource(
126+ rtype=BOOT_RESOURCE_TYPE.SYNCED
127+ )
128+ os_name, series = resource.name.split("/")
129+ node = factory.make_Node(
130+ status=NODE_STATUS.DEPLOYED,
131+ osystem=os_name,
132+ distro_series=series,
133+ architecture=resource.architecture,
134+ )
135+ node.end_deployment()
136+ start_time = datetime.datetime.now().replace(microsecond=0)
137+ node = factory.make_Node(
138+ status=NODE_STATUS.DEPLOYED,
139+ osystem=os_name,
140+ distro_series=series,
141+ architecture=resource.architecture,
142+ )
143+ node.end_deployment()
144+ response = handler.poll({})
145+ resource = response["resources"][0]
146+ self.assertGreaterEqual(
147+ datetime.datetime.strptime(
148+ resource["lastDeployed"], "%a, %d %b. %Y %H:%M:%S"
149+ ),
150+ start_time,
151+ )
152+
153+ def test_shows_number_of_machines_deployed_at_current(self) -> None:
154+ owner = factory.make_admin()
155+ handler = BootResourceHandler(owner, {}, None)
156+ resource = factory.make_usable_boot_resource(
157+ rtype=BOOT_RESOURCE_TYPE.SYNCED
158+ )
159+ os_name, series = resource.name.split("/")
160+ node = factory.make_Machine(
161+ status=NODE_STATUS.DEPLOYED,
162+ osystem=os_name,
163+ distro_series=series,
164+ architecture=resource.architecture,
165+ )
166+ factory.make_Node(
167+ status=NODE_STATUS.DEPLOYED, architecture=resource.architecture
168+ )
169+ factory.make_RegionController(
170+ status=NODE_STATUS.DEPLOYED,
171+ )
172+ response = handler.poll({})
173+ self.assertEqual(1, response["resources"][0]["machineCount"])
174+ node.delete()
175+
176+ response = handler.poll({})
177+ self.assertEqual(0, response["resources"][0]["machineCount"])
178+
179 def test_shows_number_of_nodes_deployed_for_resource(self):
180 owner = factory.make_admin()
181 handler = BootResourceHandler(owner, {}, None)

Subscribers

People subscribed via source and target branches