Merge ~ltrager/maas:fix_script_result_triggers into maas:master

Proposed by Lee Trager
Status: Merged
Approved by: Lee Trager
Approved revision: b7bbb5d9d1bbfb7a3b4a473a4d5849166494a966
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~ltrager/maas:fix_script_result_triggers
Merge into: maas:master
Diff against target: 264 lines (+57/-162)
4 files modified
src/maasserver/static/js/angular/factories/node_results.js (+11/-25)
src/maasserver/static/js/angular/factories/tests/test_node_results.js (+0/-121)
src/maasserver/static/js/angular/services/manager.js (+3/-16)
src/metadataserver/migrations/builtin/0015_migrate_storage_tests.py (+43/-0)
Reviewer Review Type Date Requested Status
MAAS Lander Needs Fixing
Andres Rodriguez (community) Approve
Review via email: mp+332946@code.launchpad.net

Commit message

LP: #1727568, #1727575 - Create migration to show old storage tests on all devices.

MAAS 2.2 did not support assoicated a ScriptResult with a hardware_type or
physical_blockdevice. When the UI was updated in 2.3 it was decided that
these old results should be assoicated with all known PhysicalBlockDevices.
This was implemented in Javascript but has been causing issues with the
triggers as some ScriptResults are associated with a PhyicalBlockDevice while
others aren't.

Old ScriptResults are now assoicated with the node's known
PhysicalBlockDevices in a migration so the UI gets a similar data set.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

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

LANDING
-b fix_script_result_triggers lp:~ltrager/maas into -b master lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/566/consoleText

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

UNIT TESTS
-b fix_script_result_triggers lp:~ltrager/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/567/console
COMMIT: 8a382b39679f0a1b0a501ddebdac6687227c5d2f

review: Needs Fixing
b7bbb5d... by Lee Trager

Fix test failure

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/static/js/angular/factories/node_results.js b/src/maasserver/static/js/angular/factories/node_results.js
2index eba3c70..1f51330 100644
3--- a/src/maasserver/static/js/angular/factories/node_results.js
4+++ b/src/maasserver/static/js/angular/factories/node_results.js
5@@ -160,37 +160,23 @@ angular.module('MAAS').factory(
6 }
7 }
8
9- if(result.hardware_type === 3) {
10+ if(result.hardware_type === 3 &&
11+ result.physical_blockdevice !== null) {
12 // Storage results are split into individual components.
13 var disk, subtext;
14- if(result.physical_blockdevice !== null) {
15- // If the storage result is assoicated with a specific
16- // component generate subtext for that component.
17- for(i = 0; i < this._node.disks.length; i++) {
18- disk = this._node.disks[i];
19- if(disk.id === result.physical_blockdevice) {
20- subtext = this._getStorageSubtext(disk);
21- if(!angular.isArray(
22- hardware_type_results[subtext])) {
23- hardware_type_results[subtext] = [];
24- }
25- this._addOrReplace(
26- hardware_type_results[subtext], result);
27- break;
28- }
29- }
30- }else{
31- // Storage results which do not have an associated physical
32- // block device are associated with all known storage
33- // devices.
34- for(i = 0; i < this._node.disks.length; i++) {
35- disk = this._node.disks[i];
36+ // If the storage result is associated with a specific
37+ // component generate subtext for that component.
38+ for(i = 0; i < this._node.disks.length; i++) {
39+ disk = this._node.disks[i];
40+ if(disk.id === result.physical_blockdevice) {
41 subtext = this._getStorageSubtext(disk);
42- if(!angular.isArray(hardware_type_results[subtext])) {
43- hardware_type_results[subtext] = [];
44+ if(!angular.isArray(
45+ hardware_type_results[subtext])) {
46+ hardware_type_results[subtext] = [];
47 }
48 this._addOrReplace(
49 hardware_type_results[subtext], result);
50+ break;
51 }
52 }
53 }else{
54diff --git a/src/maasserver/static/js/angular/factories/tests/test_node_results.js b/src/maasserver/static/js/angular/factories/tests/test_node_results.js
55index c94fcc1..55fccae 100644
56--- a/src/maasserver/static/js/angular/factories/tests/test_node_results.js
57+++ b/src/maasserver/static/js/angular/factories/tests/test_node_results.js
58@@ -280,127 +280,6 @@ describe("NodeResultsManagerFactory", function() {
59 $selected: old_result.$selected
60 }]);
61 });
62-
63- it("add " + result_type_name + " storage result no blockdevice",
64- function() {
65- // Regression test for LP: #1721524
66- var node = makenode();
67- node.disks = [];
68- var i;
69- for(i = 0; i < 3; i++) {
70- node.disks.push({
71- id: makeInteger(0, 100),
72- name: makeName("name"),
73- model: makeName("model"),
74- serial: makeName("serial")
75- });
76- }
77- var manager = NodeResultsManagerFactory.getManager(
78- node, result_type_name);
79- var result = {
80- name: makeName("name"),
81- status: makeInteger(0, 100),
82- status_name: makeName("status_name"),
83- result_type: parseInt(result_type, 10),
84- hardware_type: 3,
85- physical_blockdevice: null,
86- showing_results: false,
87- showing_menu: false,
88- showing_history: false,
89- $selected: false
90- };
91- var results_list = [];
92- for(i = 0; i < manager.results.length; i++) {
93- if(manager.results[i].hardware_type === 3) {
94- var j;
95- for(j = 0; j < node.disks.length; j++) {
96- var subtext = "/dev/" + node.disks[j].name +
97- " (Model: " + node.disks[j].model +
98- ", Serial: " + node.disks[j].serial + ")";
99- var results = manager.results[i].results[
100- subtext] = [];
101- results_list.push(results);
102- }
103- break;
104- }
105- }
106-
107- manager._processItem(result);
108- for(i = 0; i < results_list.length; i++) {
109- expect(results_list[i]).toEqual([result]);
110- }
111- });
112-
113- it("update " + result_type_name + " storage result no blockdevice",
114- function() {
115- var node = makenode();
116- node.disks = [];
117- var i;
118- for(i = 0; i < 3; i++) {
119- node.disks.push({
120- id: makeInteger(0, 100),
121- name: makeName("name"),
122- model: makeName("model"),
123- serial: makeName("serial")
124- });
125- }
126- var manager = NodeResultsManagerFactory.getManager(
127- node, result_type_name);
128- var old_result = {
129- name: makeName("name"),
130- status: makeInteger(0, 100),
131- status_name: makeName("status_name"),
132- result_type: parseInt(result_type, 10),
133- hardware_type: 3,
134- physical_blockdevice: null,
135- showing_results: makeBoolean(),
136- showing_menu: makeBoolean(),
137- showing_history: makeBoolean(),
138- $selected: makeBoolean()
139- };
140- var results_list = [];
141- for(i = 0; i < manager.results.length; i++) {
142- if(manager.results[i].hardware_type === 3) {
143- var j;
144- for(j = 0; j < node.disks.length; j++) {
145- var subtext = "/dev/" + node.disks[j].name +
146- " (Model: " + node.disks[j].model +
147- ", Serial: " + node.disks[j].serial + ")";
148- var results = manager.results[i].results[
149- subtext] = [old_result];
150- results_list.push(results);
151- }
152- break;
153- }
154- }
155- var result = {
156- name: old_result.name,
157- status: makeInteger(0, 100),
158- status_name: makeName("status_name"),
159- result_type: parseInt(result_type, 10),
160- hardware_type: 3,
161- physical_blockdevice: null,
162- showing_results: false,
163- showing_menu: false,
164- showing_history: false,
165- $selected: false
166- };
167- manager._processItem(result);
168- for(i = 0; i < results_list.length; i++) {
169- expect(results_list[i]).toEqual([{
170- name: old_result.name,
171- status: result.status,
172- status_name: result.status_name,
173- result_type: parseInt(result_type, 10),
174- hardware_type: 3,
175- physical_blockdevice: null,
176- showing_results: old_result.showing_results,
177- showing_menu: old_result.showing_menu,
178- showing_history: old_result.showing_history,
179- $selected: old_result.$selected
180- }]);
181- }
182- });
183 });
184
185 // Installation results are stored in a signal list.
186diff --git a/src/maasserver/static/js/angular/services/manager.js b/src/maasserver/static/js/angular/services/manager.js
187index b6d73b9..6703b52 100644
188--- a/src/maasserver/static/js/angular/services/manager.js
189+++ b/src/maasserver/static/js/angular/services/manager.js
190@@ -112,22 +112,9 @@ angular.module('MAAS').service(
191 Manager.prototype._replaceItemInArray = function(array, item) {
192 var idx = this._getIndexOfItem(array, item[this._pk]);
193 if(idx >= 0) {
194- // angular.copy deletes all fields on the original object
195- // before adding the new items. This causes a race conidtion
196- // in NodeResultsManager as it uses the node object to
197- // determine the subtext for storage results. Instead replace
198- // items atomically.
199- angular.forEach(item, function(value, key) {
200- if(!angular.isDefined(array[idx][key]) ||
201- (array[idx][key] !== value && key !== "$selected")) {
202- array[idx][key] = value;
203- }
204- });
205- angular.forEach(array[idx], function(value, key) {
206- if(!angular.isDefined(item[key])) {
207- delete item[key];
208- }
209- });
210+ // Keep the current selection on the item.
211+ item.$selected = array[idx].$selected;
212+ angular.copy(item, array[idx]);
213 }
214 };
215
216diff --git a/src/metadataserver/migrations/builtin/0015_migrate_storage_tests.py b/src/metadataserver/migrations/builtin/0015_migrate_storage_tests.py
217new file mode 100644
218index 0000000..05ad0d6
219--- /dev/null
220+++ b/src/metadataserver/migrations/builtin/0015_migrate_storage_tests.py
221@@ -0,0 +1,43 @@
222+# -*- coding: utf-8 -*-
223+from __future__ import unicode_literals
224+
225+from django.db import (
226+ migrations,
227+ models,
228+)
229+
230+
231+def run_migration(apps, schema_editor):
232+ ScriptResult = apps.get_model('metadataserver', 'ScriptResult')
233+ PhysicalBlockDevice = apps.get_model('maasserver', 'PhysicalBlockDevice')
234+ # Previously ScriptResults were not assoicated with PhysicalBlockDevice as
235+ # one test ran on all hardware. In 2.3 each storage device has its own
236+ # ScriptResult. To properly show this in the UI make copies of each old
237+ # result for all know storage devices.
238+ for old_script_result in ScriptResult.objects.filter(
239+ physical_blockdevice=None, script_name__in=[
240+ 'smartctl-validate', 'smartctl-short', 'smartctl-long',
241+ 'smartctl-conveyance', 'badblocks', 'badblocks-destructive']):
242+ for bd in PhysicalBlockDevice.objects.filter(
243+ node=old_script_result.script_set.node):
244+ script_result = ScriptResult()
245+ for field in ScriptResult._meta.fields:
246+ if field.name == 'id':
247+ continue
248+ setattr(
249+ script_result, field.name,
250+ getattr(old_script_result, field.name))
251+ script_result.physical_blockdevice = bd
252+ script_result.save()
253+ old_script_result.delete()
254+
255+
256+class Migration(migrations.Migration):
257+
258+ dependencies = [
259+ ('metadataserver', '0014_rename_dhcp_unconfigured_ifaces'),
260+ ]
261+
262+ operations = [
263+ migrations.RunPython(run_migration),
264+ ]

Subscribers

People subscribed via source and target branches