Merge ~mpontillo/maas:preseed-per-interface-routes--bug-1758919--2.3 into maas:master
- Git
- lp:~mpontillo/maas
- preseed-per-interface-routes--bug-1758919--2.3
- Merge into master
Status: | Superseded |
---|---|
Proposed branch: | ~mpontillo/maas:preseed-per-interface-routes--bug-1758919--2.3 |
Merge into: | maas:master |
Diff against target: |
1785 lines (+1501/-2) (has conflicts) 17 files modified
debian/changelog (+10/-0) snap/snapcraft.yaml (+9/-0) src/maasserver/bootsources.py (+3/-0) src/maasserver/models/tests/test_userprofile.py (+3/-0) src/maasserver/rpc/boot.py (+5/-0) src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js (+17/-0) src/maasserver/static/partials/ipranges.html (+17/-0) src/maasserver/static/partials/node-details.html (+134/-0) src/maasserver/static/partials/nodes-list.html (+1017/-0) src/maasserver/static/partials/script-results-list.html (+76/-0) src/maasserver/tests/test_bootsources.py (+3/-0) src/maasserver/triggers/tests/test_websocket_listener.py (+5/-0) src/provisioningserver/import_images/boot_resources.py (+61/-0) src/provisioningserver/import_images/tests/test_boot_resources.py (+92/-0) src/provisioningserver/import_images/tests/test_download_resources.py (+35/-0) src/provisioningserver/utils/tests/test_network.py (+3/-0) utilities/release-build (+11/-2) Conflict in debian/changelog Conflict in snap/snapcraft.yaml Conflict in src/maasserver/bootsources.py Conflict in src/maasserver/models/tests/test_userprofile.py Conflict in src/maasserver/rpc/boot.py Conflict in src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js Conflict in src/maasserver/static/partials/ipranges.html Conflict in src/maasserver/static/partials/node-details.html Conflict in src/maasserver/static/partials/nodes-list.html Conflict in src/maasserver/static/partials/script-results-list.html Conflict in src/maasserver/tests/test_bootsources.py Conflict in src/maasserver/triggers/tests/test_websocket_listener.py Conflict in src/provisioningserver/import_images/boot_resources.py Conflict in src/provisioningserver/import_images/tests/test_boot_resources.py Conflict in src/provisioningserver/import_images/tests/test_download_resources.py Conflict in src/provisioningserver/utils/tests/test_network.py Conflict in utilities/release-build |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
MAAS Maintainers | Pending | ||
Review via email: mp+342242@code.launchpad.net |
Commit message
LP: #1758919 - Move routes to interface context within preseed.
Backports: 9fbf7eb682c3c3f
Description of the change
Unmerged commits
- 434ff94... by Mike Pontillo
-
LP: #1758919 - Move routes to interface context within preseed.
Backports: 9fbf7eb682c3c3f
f1de08b33bb967f ffdf4a61bf - b830483... by Newell Jensen
-
Backport of 611eaccf792a388
fc7b5d8e2420502 28a6bc0e57 LP: #1753874 -- Fix typo in virsh pod driver for get_pod_
pool_size_ map. - a318f7c... by Newell Jensen
-
Backport 476dcf44f137062
5d5c5637d3b459c dd6511db0c Convert number to exponential representation in RSD Pod driver.
- b3b05a9... by Andres Rodriguez
-
Update to reflect 2.3.1 release
- 036d646... by Andres Rodriguez
-
Clean-up build scripts
- 8289431... by Andres Rodriguez
-
debian/changelog: Update in preparation for 2.3.1 release.
- d5c58de... by Lee Trager
-
LP: #1751946 - Only cleanup ScriptSets of the same type.
Backport 1f9751aec9041dc
079b83db4e9e814 85cd188ef6 from master - 5a7cb12... by Newell Jensen
-
Backport of c5a810187578776
c9dacf386d2628f 23678a6aa2 LP: #1741165 -- Remove --delete-snapshots flag to workaround volumes not being deleted for node decomposition.
- 8442748... by Andres Rodriguez
-
LP: #1711203 - Use grub instead of shim to workaround issues with Secure Boot deployment
Backport 1223c03c6ae2396
7561ec7218344da af3a95698d from master - d5bd3b1... by Lee Trager
-
Backport 02b1bf4 - LP: #1750160 - Confirm running tests on deployed hardware in the UI.
Preview Diff
1 | diff --git a/debian/changelog b/debian/changelog | |||
2 | index 09263b4..ab17966 100644 | |||
3 | --- a/debian/changelog | |||
4 | +++ b/debian/changelog | |||
5 | @@ -1,3 +1,4 @@ | |||
6 | 1 | <<<<<<< debian/changelog | ||
7 | 1 | maas (2.4.0~beta1-0ubuntu1) UNRELEASED; urgency=medium | 2 | maas (2.4.0~beta1-0ubuntu1) UNRELEASED; urgency=medium |
8 | 2 | 3 | ||
9 | 3 | * UNRELEASED | 4 | * UNRELEASED |
10 | @@ -28,6 +29,15 @@ maas (2.4.0~alpha1-6573-g12ee2331b-0ubuntu1) bionic; urgency=medium | |||
11 | 28 | -- Andres Rodriguez <andreserl@ubuntu.com> Fri, 09 Feb 2018 18:50:10 -0500 | 29 | -- Andres Rodriguez <andreserl@ubuntu.com> Fri, 09 Feb 2018 18:50:10 -0500 |
12 | 29 | 30 | ||
13 | 30 | maas (2.3.0-6434-gd354690-0ubuntu1) bionic; urgency=medium | 31 | maas (2.3.0-6434-gd354690-0ubuntu1) bionic; urgency=medium |
14 | 32 | ======= | ||
15 | 33 | maas (2.3.1-6470-g036d646-0ubuntu1) artful; urgency=medium | ||
16 | 34 | |||
17 | 35 | * New upstream release, MAAS 2.3.1 | ||
18 | 36 | |||
19 | 37 | -- Andres Rodriguez <andreserl@ubuntu.com> Mon, 05 Mar 2018 10:25:44 -0500 | ||
20 | 38 | |||
21 | 39 | maas (2.3.0-6434-gd354690-0ubuntu1) artful; urgency=medium | ||
22 | 40 | >>>>>>> debian/changelog | ||
23 | 31 | 41 | ||
24 | 32 | * New upstream release, MAAS 2.3.0: | 42 | * New upstream release, MAAS 2.3.0: |
25 | 33 | - Add support for CentOS & Windows networking. | 43 | - Add support for CentOS & Windows networking. |
26 | diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml | |||
27 | index 4c39956..3b31301 100644 | |||
28 | --- a/snap/snapcraft.yaml | |||
29 | +++ b/snap/snapcraft.yaml | |||
30 | @@ -133,6 +133,15 @@ parts: | |||
31 | 133 | source: src/maasserver/static | 133 | source: src/maasserver/static |
32 | 134 | organize: | 134 | organize: |
33 | 135 | '*': usr/share/maas/web/static/ | 135 | '*': usr/share/maas/web/static/ |
34 | 136 | <<<<<<< snap/snapcraft.yaml | ||
35 | 137 | ======= | ||
36 | 138 | twisted-plugins: | ||
37 | 139 | plugin: dump | ||
38 | 140 | source: twisted/plugins | ||
39 | 141 | organize: | ||
40 | 142 | maasrackd.py: usr/lib/python3/dist-packages/twisted/plugins/maasrackd.py | ||
41 | 143 | maasregiond.py: usr/lib/python3/dist-packages/twisted/plugins/maasregiond.py | ||
42 | 144 | >>>>>>> snap/snapcraft.yaml | ||
43 | 136 | snap: | 145 | snap: |
44 | 137 | plugin: dump | 146 | plugin: dump |
45 | 138 | source: snap | 147 | source: snap |
46 | diff --git a/src/maasserver/bootsources.py b/src/maasserver/bootsources.py | |||
47 | index f71040f..1e11784 100644 | |||
48 | --- a/src/maasserver/bootsources.py | |||
49 | +++ b/src/maasserver/bootsources.py | |||
50 | @@ -26,7 +26,10 @@ from maasserver.models import ( | |||
51 | 26 | Config, | 26 | Config, |
52 | 27 | Notification, | 27 | Notification, |
53 | 28 | ) | 28 | ) |
54 | 29 | <<<<<<< src/maasserver/bootsources.py | ||
55 | 29 | from maasserver.models.timestampedmodel import now | 30 | from maasserver.models.timestampedmodel import now |
56 | 31 | ======= | ||
57 | 32 | >>>>>>> src/maasserver/bootsources.py | ||
58 | 30 | from maasserver.utils import get_maas_user_agent | 33 | from maasserver.utils import get_maas_user_agent |
59 | 31 | from maasserver.utils.orm import transactional | 34 | from maasserver.utils.orm import transactional |
60 | 32 | from maasserver.utils.threads import deferToDatabase | 35 | from maasserver.utils.threads import deferToDatabase |
61 | diff --git a/src/maasserver/models/tests/test_userprofile.py b/src/maasserver/models/tests/test_userprofile.py | |||
62 | index 8a0efac..4bf4730 100644 | |||
63 | --- a/src/maasserver/models/tests/test_userprofile.py | |||
64 | +++ b/src/maasserver/models/tests/test_userprofile.py | |||
65 | @@ -139,6 +139,7 @@ class UserProfileTest(MAASServerTestCase): | |||
66 | 139 | self.assertEqual(reload_object(node).owner, new_user) | 139 | self.assertEqual(reload_object(node).owner, new_user) |
67 | 140 | self.assertEqual(reload_object(ipaddress).user, new_user) | 140 | self.assertEqual(reload_object(ipaddress).user, new_user) |
68 | 141 | self.assertEqual(reload_object(iprange).user, new_user) | 141 | self.assertEqual(reload_object(iprange).user, new_user) |
69 | 142 | <<<<<<< src/maasserver/models/tests/test_userprofile.py | ||
70 | 142 | 143 | ||
71 | 143 | def test_transfer_resources_missing_target_access(self): | 144 | def test_transfer_resources_missing_target_access(self): |
72 | 144 | user = factory.make_User() | 145 | user = factory.make_User() |
73 | @@ -153,6 +154,8 @@ class UserProfileTest(MAASServerTestCase): | |||
74 | 153 | " resource pool(s)") | 154 | " resource pool(s)") |
75 | 154 | # owner didn't change | 155 | # owner didn't change |
76 | 155 | self.assertEqual(reload_object(node).owner, user) | 156 | self.assertEqual(reload_object(node).owner, user) |
77 | 157 | ======= | ||
78 | 158 | >>>>>>> src/maasserver/models/tests/test_userprofile.py | ||
79 | 156 | 159 | ||
80 | 157 | def test_manager_all_users(self): | 160 | def test_manager_all_users(self): |
81 | 158 | users = set(factory.make_User() for _ in range(3)) | 161 | users = set(factory.make_User() for _ in range(3)) |
82 | diff --git a/src/maasserver/rpc/boot.py b/src/maasserver/rpc/boot.py | |||
83 | index 5b5f1de..9a51bf3 100644 | |||
84 | --- a/src/maasserver/rpc/boot.py | |||
85 | +++ b/src/maasserver/rpc/boot.py | |||
86 | @@ -280,10 +280,15 @@ def get_config( | |||
87 | 280 | osystem = configs['commissioning_osystem'] | 280 | osystem = configs['commissioning_osystem'] |
88 | 281 | series = configs['commissioning_distro_series'] | 281 | series = configs['commissioning_distro_series'] |
89 | 282 | else: | 282 | else: |
90 | 283 | <<<<<<< src/maasserver/rpc/boot.py | ||
91 | 283 | osystem = machine.get_osystem( | 284 | osystem = machine.get_osystem( |
92 | 284 | default=configs['default_osystem']) | 285 | default=configs['default_osystem']) |
93 | 285 | series = machine.get_distro_series( | 286 | series = machine.get_distro_series( |
94 | 286 | default=configs['default_distro_series']) | 287 | default=configs['default_distro_series']) |
95 | 288 | ======= | ||
96 | 289 | osystem = machine.get_osystem() | ||
97 | 290 | series = machine.get_distro_series() | ||
98 | 291 | >>>>>>> src/maasserver/rpc/boot.py | ||
99 | 287 | # XXX: roaksoax LP: #1739761 - Since the switch to squashfs (and | 292 | # XXX: roaksoax LP: #1739761 - Since the switch to squashfs (and |
100 | 288 | # drop of iscsi), precise is no longer deployable. To address a | 293 | # drop of iscsi), precise is no longer deployable. To address a |
101 | 289 | # squashfs image is made available allowing it to be deployed in | 294 | # squashfs image is made available allowing it to be deployed in |
102 | diff --git a/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js b/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js | |||
103 | index 0a48138..8f8743a 100644 | |||
104 | --- a/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js | |||
105 | +++ b/src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js | |||
106 | @@ -1580,6 +1580,7 @@ describe("NodesListController", function() { | |||
107 | 1580 | it("sets showing_confirmation with testOptions", | 1580 | it("sets showing_confirmation with testOptions", |
108 | 1581 | function() { | 1581 | function() { |
109 | 1582 | var controller = makeController(); | 1582 | var controller = makeController(); |
110 | 1583 | <<<<<<< src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js | ||
111 | 1583 | var object = makeObject("machines"); | 1584 | var object = makeObject("machines"); |
112 | 1584 | object.status_code = 6; | 1585 | object.status_code = 6; |
113 | 1585 | var spy = spyOn( | 1586 | var spy = spyOn( |
114 | @@ -1594,6 +1595,22 @@ describe("NodesListController", function() { | |||
115 | 1594 | true); | 1595 | true); |
116 | 1595 | expect($scope.tabs[ | 1596 | expect($scope.tabs[ |
117 | 1596 | "machines"].actionProgress.affected_nodes).toBe(1); | 1597 | "machines"].actionProgress.affected_nodes).toBe(1); |
118 | 1598 | ======= | ||
119 | 1599 | var object = makeObject("nodes"); | ||
120 | 1600 | object.status_code = 6; | ||
121 | 1601 | var spy = spyOn( | ||
122 | 1602 | $scope.tabs.nodes.manager, | ||
123 | 1603 | "performAction").and.returnValue( | ||
124 | 1604 | $q.defer().promise); | ||
125 | 1605 | $scope.tabs.nodes.actionOption = { name: "test" }; | ||
126 | 1606 | $scope.tabs.nodes.selectedItems = [object]; | ||
127 | 1607 | $scope.actionGo("nodes"); | ||
128 | 1608 | expect($scope.tabs[ | ||
129 | 1609 | "nodes"].actionProgress.showing_confirmation).toBe( | ||
130 | 1610 | true); | ||
131 | 1611 | expect($scope.tabs[ | ||
132 | 1612 | "nodes"].actionProgress.affected_nodes).toBe(1); | ||
133 | 1613 | >>>>>>> src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js | ||
134 | 1597 | expect(spy).not.toHaveBeenCalled(); | 1614 | expect(spy).not.toHaveBeenCalled(); |
135 | 1598 | }); | 1615 | }); |
136 | 1599 | 1616 | ||
137 | diff --git a/src/maasserver/static/partials/ipranges.html b/src/maasserver/static/partials/ipranges.html | |||
138 | index 897d959..3d48a68 100755 | |||
139 | --- a/src/maasserver/static/partials/ipranges.html | |||
140 | +++ b/src/maasserver/static/partials/ipranges.html | |||
141 | @@ -15,6 +15,7 @@ | |||
142 | 15 | <tbody> | 15 | <tbody> |
143 | 16 | <tr data-ng-repeat="iprange in (subnetIPRanges = ipranges | filterBySubnetOrVlan:subnet:vlan) | orderBy:ipRangeSort" | 16 | <tr data-ng-repeat="iprange in (subnetIPRanges = ipranges | filterBySubnetOrVlan:subnet:vlan) | orderBy:ipRangeSort" |
144 | 17 | data-ng-class="{ 'is-active': isIPRangeInEditMode(iprange) || isIPRangeInDeleteMode(iprange)}"> | 17 | data-ng-class="{ 'is-active': isIPRangeInEditMode(iprange) || isIPRangeInDeleteMode(iprange)}"> |
145 | 18 | <<<<<<< src/maasserver/static/partials/ipranges.html | ||
146 | 18 | <td class="col-2" aria-label="Start IP Address">{$ iprange.start_ip $}</td> | 19 | <td class="col-2" aria-label="Start IP Address">{$ iprange.start_ip $}</td> |
147 | 19 | <td class="col-2" aria-label="End IP Address">{$ iprange.end_ip $}</td> | 20 | <td class="col-2" aria-label="End IP Address">{$ iprange.end_ip $}</td> |
148 | 20 | <td class="col-1" aria-label="Owner">{$ iprange.type == "dynamic" ? "MAAS" : iprange.user $}</td> | 21 | <td class="col-1" aria-label="Owner">{$ iprange.type == "dynamic" ? "MAAS" : iprange.user $}</td> |
149 | @@ -26,6 +27,22 @@ | |||
150 | 26 | data-ng-click="toggleMenu(); ipRangeToggleEditMode(iprange)">Edit</button> | 27 | data-ng-click="toggleMenu(); ipRangeToggleEditMode(iprange)">Edit</button> |
151 | 27 | <button class="table__controls-action u-text--error" aria-label="Remove range" | 28 | <button class="table__controls-action u-text--error" aria-label="Remove range" |
152 | 28 | data-ng-click="toggleMenu(); ipRangeEnterDeleteMode(iprange)">Remove</button> | 29 | data-ng-click="toggleMenu(); ipRangeEnterDeleteMode(iprange)">Remove</button> |
153 | 30 | ======= | ||
154 | 31 | <div class="table__data table-col--20" aria-label="Start IP Address">{$ iprange.start_ip $}</div> | ||
155 | 32 | <div class="table__data table-col--20" aria-label="End IP Address">{$ iprange.end_ip $}</div> | ||
156 | 33 | <div class="table__data table-col--10" aria-label="Owner">{$ iprange.type == "dynamic" ? "MAAS" : iprange.user $}</div> | ||
157 | 34 | <div class="table__data table-col--10" aria-label="Type">{$ iprange.type == "dynamic" ? "Dynamic" : "Reserved" $}</div> | ||
158 | 35 | <div class="table__data table-col--31" aria-label="Comment">{$ iprange.type == "dynamic" ? "Dynamic" : iprange.comment $}</div> | ||
159 | 36 | <div class="table__data table-col--9 table--mobile-controls"> | ||
160 | 37 | <div class="table__controls" toggle-ctrl data-ng-if="ipRangeCanBeModified(iprange)"> | ||
161 | 38 | <button class="table__controls-toggle" data-ng-click="toggleMenu()">View actions</button> | ||
162 | 39 | <div class="table__controls-menu" role="menu" data-ng-show="isToggled"> | ||
163 | 40 | <button class="table__controls-action" aria-label="Edit row" | ||
164 | 41 | data-ng-click="toggleMenu(); ipRangeToggleEditMode(iprange)">Edit reserved range</button> | ||
165 | 42 | <button class="table__controls-action u-text--error" aria-label="Remove" | ||
166 | 43 | data-ng-click="toggleMenu(); ipRangeEnterDeleteMode(iprange)">Remove range</button> | ||
167 | 44 | </div> | ||
168 | 45 | >>>>>>> src/maasserver/static/partials/ipranges.html | ||
169 | 29 | </div> | 46 | </div> |
170 | 30 | </td> | 47 | </td> |
171 | 31 | <td class="is-active p-table-expanding__panel col-12" col-span="6" data-ng-if="isIPRangeInDeleteMode(iprange)"> | 48 | <td class="is-active p-table-expanding__panel col-12" col-span="6" data-ng-if="isIPRangeInDeleteMode(iprange)"> |
172 | diff --git a/src/maasserver/static/partials/node-details.html b/src/maasserver/static/partials/node-details.html | |||
173 | index 33688a5..6f4de0f 100755 | |||
174 | --- a/src/maasserver/static/partials/node-details.html | |||
175 | +++ b/src/maasserver/static/partials/node-details.html | |||
176 | @@ -98,6 +98,7 @@ | |||
177 | 98 | </ul> | 98 | </ul> |
178 | 99 | </div> | 99 | </div> |
179 | 100 | 100 | ||
180 | 101 | <<<<<<< src/maasserver/static/partials/node-details.html | ||
181 | 101 | <div class="col-8" data-ng-show="action.option.name === 'deploy' || action.option.name === 'release'"> | 102 | <div class="col-8" data-ng-show="action.option.name === 'deploy' || action.option.name === 'release'"> |
182 | 102 | <div class="ng-hide" data-ng-show="action.option.name === 'deploy'"> | 103 | <div class="ng-hide" data-ng-show="action.option.name === 'deploy'"> |
183 | 103 | <div class="p-form__group"> | 104 | <div class="p-form__group"> |
184 | @@ -236,6 +237,139 @@ | |||
185 | 236 | </div> | 237 | </div> |
186 | 237 | </div> | 238 | </div> |
187 | 238 | </div> | 239 | </div> |
188 | 240 | ======= | ||
189 | 241 | <!-- XXX blake_r 2015-02-19 - Need to add e2e test. --> | ||
190 | 242 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': action.option }"> | ||
191 | 243 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-if="!isDevice && !node.dhcp_on"> | ||
192 | 244 | <p class="page-header__message page-header__message--warning">MAAS is not providing DHCP.</p> | ||
193 | 245 | </div> | ||
194 | 246 | |||
195 | 247 | <!-- XXX blake_r 2015-02-19 - Need to add e2e test. --> | ||
196 | 248 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-hide="isActionError() || isDeployError() || isSSHKeyError() || hasActionPowerError(action.option.name)"> | ||
197 | 249 | <form class="form form--inline u-display--inline"> | ||
198 | 250 | <fieldset class="form__fieldset ng-hide" data-ng-show="action.option.name === 'commission' || action.option.name === 'test'"> | ||
199 | 251 | <div class="form__group"> | ||
200 | 252 | <input class="checkbox" id="enableSSH" type="checkbox" | ||
201 | 253 | data-ng-model="commissionOptions.enableSSH"> | ||
202 | 254 | <label for="enableSSH">Allow SSH access and prevent machine from powering off</label> | ||
203 | 255 | </div> | ||
204 | 256 | </fieldset> | ||
205 | 257 | <fieldset class="form__fieldset ng-hide" data-ng-show="action.option.name === 'commission'"> | ||
206 | 258 | <div class="form__group"> | ||
207 | 259 | <input class="checkbox" id="skipNetworking" type="checkbox" | ||
208 | 260 | data-ng-model="commissionOptions.skipNetworking"> | ||
209 | 261 | <label for="skipNetworking">Retain network configuration</label> | ||
210 | 262 | </div> | ||
211 | 263 | <div class="form__group"> | ||
212 | 264 | <input class="checkbox" id="skipStorage" type="checkbox" | ||
213 | 265 | data-ng-model="commissionOptions.skipStorage"> | ||
214 | 266 | <label for="skipStorage">Retain storage configuration</label> | ||
215 | 267 | </div> | ||
216 | 268 | </fieldset> | ||
217 | 269 | <fieldset class="form__fieldset ng-hide" data-ng-show="action.option.name === 'deploy'"> | ||
218 | 270 | <div class="form__group"> | ||
219 | 271 | <label class="form__group-label">Choose your image</label> | ||
220 | 272 | <div class="form__group-input" data-maas-os-select="osinfo" data-ng-model="osSelection"></div> | ||
221 | 273 | </div> | ||
222 | 274 | </fieldset> | ||
223 | 275 | <fieldset class="form__fieldset" data-ng-if="action.option.name === 'release'"> | ||
224 | 276 | <div class="form__group"> | ||
225 | 277 | <div data-maas-release-options="releaseOptions"></div> | ||
226 | 278 | </div> | ||
227 | 279 | </fieldset> | ||
228 | 280 | <div class="page-header__controls" data-ng-if="action.option.name !== 'commission' && action.option.name !== 'test'"> | ||
229 | 281 | <button class="button--base button--inline" data-ng-click="actionCancel()">Cancel</button> | ||
230 | 282 | <button class="button--inline" data-ng-class="action.option.name === 'delete' ? 'button--destructive' : 'button--positive'" data-ng-click="actionGo('nodes')" data-ng-hide="hasActionsFailed('nodes')"> | ||
231 | 283 | <span data-ng-if="action.option.name === 'acquire'">Acquire {$ type_name $}</span> | ||
232 | 284 | <span data-ng-if="action.option.name === 'deploy'">Deploy {$ type_name $}</span> | ||
233 | 285 | <span data-ng-if="action.option.name === 'release'">Release {$ type_name $}</span> | ||
234 | 286 | <span data-ng-if="action.option.name === 'set-zone'">Set zone for {$ type_name $}</span> | ||
235 | 287 | <span data-ng-if="action.option.name === 'on'">Power on {$ type_name $}</span> | ||
236 | 288 | <span data-ng-if="action.option.name === 'off'">Power off {$ type_name $}</span> | ||
237 | 289 | <span data-ng-if="action.option.name === 'abort'">Abort action on {$ type_name $}</span> | ||
238 | 290 | <span data-ng-if="action.option.name === 'rescue-mode'">Rescue {$ type_name $}</span> | ||
239 | 291 | <span data-ng-if="action.option.name === 'exit-rescue-mode'">Exit rescue mode</span> | ||
240 | 292 | <span data-ng-if="action.option.name === 'mark-broken'">Mark {$ type_name $}</span> | ||
241 | 293 | <span data-ng-if="action.option.name === 'mark-fixed'">Mark {$ type_name $}</span> | ||
242 | 294 | <span data-ng-if="action.option.name === 'override-failed-testing'">Override failed testing</span> | ||
243 | 295 | <span data-ng-if="action.option.name === 'delete'">Delete {$ type_name $}</span> | ||
244 | 296 | <span data-ng-if="action.option.name === 'import-images'">Import images</span> | ||
245 | 297 | </button> | ||
246 | 298 | </div> | ||
247 | 299 | </form> | ||
248 | 300 | </div> | ||
249 | 301 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-hide="isActionError() || isDeployError() || isSSHKeyError() || hasActionPowerError(action.option.name) || action.option.name !== 'commission'" data-ng-if="hasCustomCommissioningScripts()"> | ||
250 | 302 | <form class="form form--stack"> | ||
251 | 303 | <fieldset class="form__fieldset eight-col u-margin--bottom-small"> | ||
252 | 304 | <div class="form__group"> | ||
253 | 305 | <label for="commissioning-scripts">Additional commissioning scripts</label> | ||
254 | 306 | <span id="commissioning-scripts" data-maas-script-select="script" data-script-type="0" data-ng-model="commissioningSelection" class="tags--inline"></span> | ||
255 | 307 | </div> | ||
256 | 308 | </fieldset> | ||
257 | 309 | </form> | ||
258 | 310 | </div> | ||
259 | 311 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-hide="isActionError() || isDeployError() || isSSHKeyError() || hasActionPowerError(action.option.name) || (action.option.name !== 'commission' && action.option.name !== 'test')"> | ||
260 | 312 | <form class="form form--stack"> | ||
261 | 313 | <fieldset class="form__fieldset eight-col u-margin--bottom-small"> | ||
262 | 314 | <div class="form__group"> | ||
263 | 315 | <label>Hardware tests</label> | ||
264 | 316 | <span id="testing-scripts" data-maas-script-select="script" data-script-type="2" data-ng-model="testSelection" class="tags--inline"></span> | ||
265 | 317 | </div> | ||
266 | 318 | </fieldset> | ||
267 | 319 | </form> | ||
268 | 320 | </div> | ||
269 | 321 | <div class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="isActionError() || isDeployError() || isSSHKeyError() || hasActionPowerError(action.option.name)" data-ng-if="action.option.name === 'commission' || action.option.name === 'test'"> | ||
270 | 322 | <form class="form form--inline"> | ||
271 | 323 | <div class="page-header__controls"> | ||
272 | 324 | <button class="button--base button--inline" data-ng-click="actionCancel()">Cancel</button> | ||
273 | 325 | <button class="button--inline" data-ng-class="action.option.name === 'delete' ? 'button--destructive' : 'button--positive'" data-ng-click="actionGo('nodes')" data-ng-hide="hasActionsFailed('nodes')"> | ||
274 | 326 | <span data-ng-if="action.option.name === 'commission'">Commission {$ type_name $}</span> | ||
275 | 327 | <span data-ng-if="action.option.name === 'test'">Test {$ type_name $}</span> | ||
276 | 328 | </button> | ||
277 | 329 | </div> | ||
278 | 330 | </form> | ||
279 | 331 | </div> | ||
280 | 332 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="action.showing_confirmation && action.option.name === 'test'"> | ||
281 | 333 | <p class="page-header__message page-header__message--warning"> | ||
282 | 334 | Node is currently deployed. Are you sure you want to continue to test hardware? | ||
283 | 335 | </p> | ||
284 | 336 | <div class="page-header__controls"> | ||
285 | 337 | <button class="button--base button--inline" data-ng-click="actionCancel()">No</button> | ||
286 | 338 | <button class="button--secondary button--inline" data-ng-click="actionGo()">Yes</button> | ||
287 | 339 | </div> | ||
288 | 340 | </div> | ||
289 | 341 | <!-- XXX blake_r 2015-02-19 - Need to add e2e test. --> | ||
290 | 342 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="isActionError()"> | ||
291 | 343 | <p class="page-header__message page-header__message--error"> | ||
292 | 344 | Node failed to be {$ action.option.sentence $}, because of the following error: {$ action.error $} | ||
293 | 345 | </p> | ||
294 | 346 | <div class="page-header__controls"> | ||
295 | 347 | <button class="button--base button--inline" data-ng-click="actionCancel()">Cancel</button> | ||
296 | 348 | <button class="button--secondary button--inline" data-ng-click="actionGo()">Retry</button> | ||
297 | 349 | </div> | ||
298 | 350 | </div> | ||
299 | 351 | |||
300 | 352 | <!-- XXX blake_r 2015-02-19 - Need to add e2e test. --> | ||
301 | 353 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="isDeployError()"> | ||
302 | 354 | <p class="page-header__message page-header__message--error"> | ||
303 | 355 | Node cannot be {$ action.option.sentence $}, because the required boot images have not been imported. To import boot images, visit the <a href="images/">images page</a>. | ||
304 | 356 | </p> | ||
305 | 357 | <div class="page-header__controls"> | ||
306 | 358 | <button class="button--base button--inline" data-ng-click="actionCancel()">Cancel</button> | ||
307 | 359 | </div> | ||
308 | 360 | </div> | ||
309 | 361 | |||
310 | 362 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="hasActionPowerError(action.option.name)"> | ||
311 | 363 | <p class="page-header__message page-header__message--error"> | ||
312 | 364 | Node cannot be {$ action.option.sentence $}, because power control software for the | ||
313 | 365 | node is missing from its rack controller. To proceed, install the | ||
314 | 366 | {$ getPowerErrors() $} on the rack controller. | ||
315 | 367 | </p> | ||
316 | 368 | <div class="page-header__controls"> | ||
317 | 369 | <button class="button--base button--inline" data-ng-click="actionCancel()">Cancel</button> | ||
318 | 370 | </div> | ||
319 | 371 | </div> | ||
320 | 372 | >>>>>>> src/maasserver/static/partials/node-details.html | ||
321 | 239 | 373 | ||
322 | 240 | <nav class="p-tabs"> | 374 | <nav class="p-tabs"> |
323 | 241 | <ul class="p-tabs__list" role="tablist" data-ng-class="{ 'u-hide': action.option }"> | 375 | <ul class="p-tabs__list" role="tablist" data-ng-class="{ 'u-hide': action.option }"> |
324 | diff --git a/src/maasserver/static/partials/nodes-list.html b/src/maasserver/static/partials/nodes-list.html | |||
325 | index 8952e21..71f4b64 100644 | |||
326 | --- a/src/maasserver/static/partials/nodes-list.html | |||
327 | +++ b/src/maasserver/static/partials/nodes-list.html | |||
328 | @@ -1,3 +1,4 @@ | |||
329 | 1 | <<<<<<< src/maasserver/static/partials/nodes-list.html | ||
330 | 1 | <header class="p-strip--light is-shallow is-bordered page-header" media-query="min-width: 769px"> | 2 | <header class="p-strip--light is-shallow is-bordered page-header" media-query="min-width: 769px"> |
331 | 2 | <div class="row"> | 3 | <div class="row"> |
332 | 3 | <div class="col-8"> | 4 | <div class="col-8"> |
333 | @@ -1047,3 +1048,1019 @@ sudo maas-rack register --url {$ tabs.controllers.registerUrl $} --secret {$ tab | |||
334 | 1047 | on-check-all="toggleCheckAll('switches')" on-check="toggleChecked($switch_, 'switches')"></maas-switches-table> | 1048 | on-check-all="toggleCheckAll('switches')" on-check="toggleChecked($switch_, 'switches')"></maas-switches-table> |
335 | 1048 | </div> | 1049 | </div> |
336 | 1049 | </div> | 1050 | </div> |
337 | 1051 | ======= | ||
338 | 1052 | <header class="page-header u-margin--bottom-none" sticky media-query="min-width: 769px"> | ||
339 | 1053 | <div class="wrapper--inner"> | ||
340 | 1054 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
341 | 1055 | <h1 class="page-header__title">Nodes</h1> | ||
342 | 1056 | |||
343 | 1057 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
344 | 1058 | <p class="page-header__status" data-ng-show="loading"><span class="u-text--loading"><i class="icon icon--loading u-animation--spin"></i> Loading...</span></p> | ||
345 | 1059 | |||
346 | 1060 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
347 | 1061 | <div class="page-header__controls u-float--right ng-hide" data-ng-show="currentpage === 'nodes'"> | ||
348 | 1062 | <div data-ng-hide="tabs.nodes.selectedItems.length"> | ||
349 | 1063 | <div data-maas-cta="addHardwareOptions" | ||
350 | 1064 | data-ng-model="addHardwareOption" | ||
351 | 1065 | data-ng-change="addHardwareOptionChanged()" data-default-title="Add hardware"> | ||
352 | 1066 | </div> | ||
353 | 1067 | </div> | ||
354 | 1068 | <div class="ng-hide" data-ng-show="tabs.nodes.selectedItems.length"> | ||
355 | 1069 | <a class="u-display--inline u-margin--right" data-ng-click="showSelected('nodes')">{$ tabs.nodes.selectedItems.length $} Selected</a> | ||
356 | 1070 | <div data-maas-cta="tabs.nodes.takeActionOptions" | ||
357 | 1071 | data-ng-model="tabs.nodes.actionOption" | ||
358 | 1072 | data-ng-change="actionOptionSelected('nodes')"> | ||
359 | 1073 | </div> | ||
360 | 1074 | </div> | ||
361 | 1075 | </div> | ||
362 | 1076 | |||
363 | 1077 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
364 | 1078 | <div class="page-header__controls u-float--rightng-hide" data-ng-show="currentpage === 'devices'"> | ||
365 | 1079 | <div data-ng-hide="tabs.devices.selectedItems.length"> | ||
366 | 1080 | <button class="button--secondary button--inline" | ||
367 | 1081 | data-ng-click="addDevice()" | ||
368 | 1082 | data-ng-hide="addDeviceScope.viewable">Add device</button> | ||
369 | 1083 | <button class="button--secondary button--inline ng-hide" | ||
370 | 1084 | data-ng-click="cancelAddDevice()" | ||
371 | 1085 | data-ng-show="addDeviceScope.viewable">Cancel add device</button> | ||
372 | 1086 | </div> | ||
373 | 1087 | <div data-ng-show="tabs.devices.selectedItems.length"> | ||
374 | 1088 | <a class="u-display--inline u-margin--right" data-ng-click="showSelected('devices')">{$ tabs.devices.selectedItems.length $} Selected</a> | ||
375 | 1089 | <div data-maas-cta="tabs.devices.takeActionOptions" | ||
376 | 1090 | data-ng-model="tabs.devices.actionOption" | ||
377 | 1091 | data-ng-change="actionOptionSelected('devices')"> | ||
378 | 1092 | </div> | ||
379 | 1093 | </div> | ||
380 | 1094 | </div> | ||
381 | 1095 | |||
382 | 1096 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
383 | 1097 | <div class="page-header__controls u-float--rightng-hide" data-ng-show="currentpage === 'controllers'"> | ||
384 | 1098 | <div data-ng-if="!tabs.controllers.selectedItems.length"> | ||
385 | 1099 | <button class="button--secondary button--inline" | ||
386 | 1100 | data-ng-click="tabs.controllers.addController = true" | ||
387 | 1101 | data-ng-hide="tabs.controllers.addController">Add rack controller</button> | ||
388 | 1102 | <button class="button--secondary button--inline ng-hide" | ||
389 | 1103 | data-ng-click="tabs.controllers.addController = false" | ||
390 | 1104 | data-ng-show="tabs.controllers.addController">Close add rack controller</button> | ||
391 | 1105 | </div> | ||
392 | 1106 | <div data-ng-show="tabs.controllers.selectedItems.length"> | ||
393 | 1107 | <a class="u-display--inline u-margin--right" data-ng-click="showSelected('controllers')">{$ tabs.controllers.selectedItems.length $} Selected</a> | ||
394 | 1108 | <div data-maas-cta="tabs.controllers.takeActionOptions" | ||
395 | 1109 | data-ng-model="tabs.controllers.actionOption" | ||
396 | 1110 | data-ng-change="actionOptionSelected('controllers')"> | ||
397 | 1111 | </div> | ||
398 | 1112 | </div> | ||
399 | 1113 | </div> | ||
400 | 1114 | |||
401 | 1115 | <div class="page-header__controls u-float--right ng-hide" data-ng-show="currentpage === 'switches'"> | ||
402 | 1116 | <div class="ng-hide" data-ng-show="tabs.switches.selectedItems.length"> | ||
403 | 1117 | <a class="u-display--inline u-margin--right" data-ng-click="showSelected('switches')">{$ tabs.switches.selectedItems.length $} Selected</a> | ||
404 | 1118 | <div data-maas-cta="tabs.switches.takeActionOptions" | ||
405 | 1119 | data-ng-model="tabs.switches.actionOption" | ||
406 | 1120 | data-ng-change="actionOptionSelected('switches')"> | ||
407 | 1121 | </div> | ||
408 | 1122 | </div> | ||
409 | 1123 | </div> | ||
410 | 1124 | |||
411 | 1125 | <div data-ng-repeat="tab in ['nodes', 'switches']" data-ng-show="currentpage == tab"> | ||
412 | 1126 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
413 | 1127 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': tabs[tab].actionOption }"> | ||
414 | 1128 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
415 | 1129 | <section class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="isActionError(tab) || hasActionsInProgress(tab)"> | ||
416 | 1130 | <form class="form form--inline u-display--inline"> | ||
417 | 1131 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs[tab].actionOption.name === 'commission' || tabs[tab].actionOption.name === 'test'"> | ||
418 | 1132 | <div class="form__group"> | ||
419 | 1133 | <input class="form__group-label" id="{$ tab $}-enableSSH" type="checkbox" | ||
420 | 1134 | data-ng-model="tabs[tab].commissionOptions.enableSSH"> | ||
421 | 1135 | <label class="checkbox-label" for="{$ tab $}-enableSSH">Allow SSH access and prevent machine from powering off</label> | ||
422 | 1136 | </div> | ||
423 | 1137 | </fieldset> | ||
424 | 1138 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs[tab].actionOption.name === 'commission'"> | ||
425 | 1139 | <div class="form__group"> | ||
426 | 1140 | <input class="form__group-label" id="{$ tab $}-skipNetworking" type="checkbox" | ||
427 | 1141 | data-ng-model="tabs[tab].commissionOptions.skipNetworking"> | ||
428 | 1142 | <label class="checkbox-label" for="{$ tab $}-skipNetworking">Retain network configuration</label> | ||
429 | 1143 | </div> | ||
430 | 1144 | <div class="form__group"> | ||
431 | 1145 | <input class="form__group-label" id="{$ tab $}-skipStorage" type="checkbox" | ||
432 | 1146 | data-ng-model="tabs[tab].commissionOptions.skipStorage"> | ||
433 | 1147 | <label class="checkbox-label" for="{$ tab $}-skipStorage">Retain storage configuration</label> | ||
434 | 1148 | </div> | ||
435 | 1149 | </fieldset> | ||
436 | 1150 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs[tab].actionOption.name === 'deploy'"> | ||
437 | 1151 | <div class="form__group"> | ||
438 | 1152 | <label for="image" class="form__group-label">Choose your image</label> | ||
439 | 1153 | <div class="form__group-input" data-maas-os-select="osinfo" data-ng-model="tabs[tab].osSelection"></div> | ||
440 | 1154 | </div> | ||
441 | 1155 | </fieldset> | ||
442 | 1156 | <fieldset class="form__fieldset" data-ng-if="tabs[tab].actionOption.name === 'release'"> | ||
443 | 1157 | <div class="form__group"> | ||
444 | 1158 | <div data-maas-release-options="tabs[tab].releaseOptions"></div> | ||
445 | 1159 | </div> | ||
446 | 1160 | </fieldset> | ||
447 | 1161 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs[tab].actionOption.name === 'set-zone'"> | ||
448 | 1162 | <div class="form__group"> | ||
449 | 1163 | <label for="{$ tab $}-zone3" class="form__group-label">Select Zone</label> | ||
450 | 1164 | <div class="form__group-input"> | ||
451 | 1165 | <select name="zone" id="{$ tab $}-zone3" | ||
452 | 1166 | data-ng-model="tabs[tab].zoneSelection" | ||
453 | 1167 | data-ng-options="zone as zone.name for zone in zones"> | ||
454 | 1168 | <option value="" disabled="disabled">Choose a zone</option> | ||
455 | 1169 | </select> | ||
456 | 1170 | </div> | ||
457 | 1171 | </div> | ||
458 | 1172 | </fieldset> | ||
459 | 1173 | </form> | ||
460 | 1174 | <div class="page-header__controls" data-ng-if="tabs[tab].actionOption.name !== 'commission' && tabs[tab].actionOption.name !== 'test'"> | ||
461 | 1175 | <button class="button--base button--inline" data-ng-click="actionCancel(tab)">Cancel</button> | ||
462 | 1176 | <button class="button--inline" data-ng-class="tabs[tab].actionOption.name === 'delete' ? 'button--destructive' : 'button--positive'" data-ng-click="actionGo(tab)" data-ng-hide="hasActionsFailed(tab)"> | ||
463 | 1177 | <span data-ng-if="tabs[tab].actionOption.name === 'acquire'">Acquire {$ tabs[tab].selectedItems.length $} | ||
464 | 1178 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
465 | 1179 | </span> | ||
466 | 1180 | <span data-ng-if="tabs[tab].actionOption.name === 'deploy'">Deploy {$ tabs[tab].selectedItems.length $} | ||
467 | 1181 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
468 | 1182 | </span> | ||
469 | 1183 | <span data-ng-if="tabs[tab].actionOption.name === 'release'">Release {$ tabs[tab].selectedItems.length $} | ||
470 | 1184 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
471 | 1185 | </span> | ||
472 | 1186 | <span data-ng-if="tabs[tab].actionOption.name === 'set-zone'">Set zone for {$ tabs[tab].selectedItems.length $} | ||
473 | 1187 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
474 | 1188 | </span> | ||
475 | 1189 | <span data-ng-if="tabs[tab].actionOption.name === 'on'">Power on {$ tabs[tab].selectedItems.length $} | ||
476 | 1190 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
477 | 1191 | </span> | ||
478 | 1192 | <span data-ng-if="tabs[tab].actionOption.name === 'off'">Power off {$ tabs[tab].selectedItems.length $} | ||
479 | 1193 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
480 | 1194 | </span> | ||
481 | 1195 | <span data-ng-if="tabs[tab].actionOption.name === 'abort'">Abort action for {$ tabs[tab].selectedItems.length $} | ||
482 | 1196 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
483 | 1197 | </span> | ||
484 | 1198 | <span data-ng-if="tabs[tab].actionOption.name === 'rescue-mode'">Set rescue mode for {$ tabs[tab].selectedItems.length $} | ||
485 | 1199 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
486 | 1200 | </span> | ||
487 | 1201 | <span data-ng-if="tabs[tab].actionOption.name === 'exit-rescue-mode'">Exit rescue mode for {$ tabs[tab].selectedItems.length $} | ||
488 | 1202 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
489 | 1203 | </span> | ||
490 | 1204 | <span data-ng-if="tabs[tab].actionOption.name === 'mark-broken'">Mark {$ tabs[tab].selectedItems.length $} | ||
491 | 1205 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> as broken | ||
492 | 1206 | </span> | ||
493 | 1207 | <span data-ng-if="tabs[tab].actionOption.name === 'mark-fixed'">Mark {$ tabs[tab].selectedItems.length $} | ||
494 | 1208 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> as fixed | ||
495 | 1209 | </span> | ||
496 | 1210 | <span data-ng-if="tabs[tab].actionOption.name === 'override-failed-testing'">Override failed testing on {$ tabs[tab].selectedItems.length $} | ||
497 | 1211 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
498 | 1212 | </span> | ||
499 | 1213 | <span data-ng-if="tabs[tab].actionOption.name === 'delete'">Delete {$ tabs[tab].selectedItems.length $} | ||
500 | 1214 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
501 | 1215 | </span> | ||
502 | 1216 | </button> | ||
503 | 1217 | <button class="button--secondary button--inline" data-ng-click="actionGo(tab)" data-ng-show="hasActionsFailed(tab)">Retry</button> | ||
504 | 1218 | </div> | ||
505 | 1219 | </section> | ||
506 | 1220 | <section class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="isActionError(tab) || hasActionsInProgress(tab)" data-ng-if="tabs[tab].actionOption.name === 'commission' && hasCustomCommissioningScripts()"> | ||
507 | 1221 | <form class="form form--stack"> | ||
508 | 1222 | <fieldset class="form__fieldset eight-col u-margin--bottom-small"> | ||
509 | 1223 | <div class="form__group"> | ||
510 | 1224 | <label for="{$ tab $}-commissiong-scripts">Additional commissioning Scripts</label> | ||
511 | 1225 | <span id="{$ tab $}-commissioning-scripts" data-maas-script-select="script" data-script-type="0" data-ng-model="tabs[tab].commissioningSelection" class="tags--inline"></span> | ||
512 | 1226 | </div> | ||
513 | 1227 | </fieldset> | ||
514 | 1228 | </form> | ||
515 | 1229 | </section> | ||
516 | 1230 | <section class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="isActionError(tab) || hasActionsInProgress(tab)" data-ng-if="tabs[tab].actionOption.name === 'commission' || tabs[tab].actionOption.name ==='test'"> | ||
517 | 1231 | <form class="form form--stack"> | ||
518 | 1232 | <fieldset class="form__fieldset eight-col u-margin--bottom-small"> | ||
519 | 1233 | <div class="form__group"> | ||
520 | 1234 | <label for="{$ tab $}-testing-scripts">Hardware Tests</label> | ||
521 | 1235 | <span id="{$ tab $}-testing-scripts" data-maas-script-select="script" data-script-type="2" data-ng-model="tabs[tab].testSelection" class="tags--inline"></span> | ||
522 | 1236 | </div> | ||
523 | 1237 | </fieldset> | ||
524 | 1238 | </form> | ||
525 | 1239 | </section> | ||
526 | 1240 | <section class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="isActionError(tab) || hasActionsInProgress(tab)" data-ng-if="tabs[tab].actionOption.name === 'commission' || tabs[tab].actionOption.name === 'test'"> | ||
527 | 1241 | <div class="page-header__controls"> | ||
528 | 1242 | <button class="button--base button--inline" data-ng-click="actionCancel(tab)">Cancel</button> | ||
529 | 1243 | <button class="button--inline" data-ng-class="tabs[tab].actionOption.name === 'delete' ? 'button--destructive' : 'button--positive'" data-ng-click="actionGo(tab)" data-ng-hide="hasActionsFailed(tab)"> | ||
530 | 1244 | <span data-ng-if="tabs[tab].actionOption.name === 'commission'">Commission {$ tabs[tab].selectedItems.length $} | ||
531 | 1245 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
532 | 1246 | </span> | ||
533 | 1247 | <span data-ng-if="tabs[tab].actionOption.name === 'test'">Test {$ tabs[tab].selectedItems.length $} | ||
534 | 1248 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'machine', 'other': 'machines'}"></span> | ||
535 | 1249 | </span> | ||
536 | 1250 | </button> | ||
537 | 1251 | <button class="button--secondary button--inline" data-ng-click="actionGo(tab)" data-ng-show="hasActionsFailed(tab)">Retry</button> | ||
538 | 1252 | </div> | ||
539 | 1253 | </section> | ||
540 | 1254 | |||
541 | 1255 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
542 | 1256 | <section class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="isActionError(tab)"> | ||
543 | 1257 | <p data-ng-hide="isDeployError(tab) || isSSHKeyError(tab)" | ||
544 | 1258 | class="page-header__message page-header__message--error ng-hide"> | ||
545 | 1259 | {$ tabs[tab].actionErrorCount $} | ||
546 | 1260 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'node', 'other': 'nodes'}"></span> | ||
547 | 1261 | cannot be {$ tabs[tab].actionOption.sentence $}. To proceed, update your selection. | ||
548 | 1262 | </p> | ||
549 | 1263 | <p class="page-header__message page-header__message--error ng-hide" data-ng-show="isDeployError(tab)"> | ||
550 | 1264 | {$ tabs[tab].selectedItems.length $} | ||
551 | 1265 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'node', 'other': 'nodes'}"></span> | ||
552 | 1266 | cannot be {$ tabs[tab].actionOption.sentence $}, because the required boot images have not been imported. To import boot images, visit the <a href="#/images">images page</a>. | ||
553 | 1267 | </p> | ||
554 | 1268 | <p class="page-header__message page-header__message--error ng-hide" data-ng-show="isSSHKeyError(tab)"> | ||
555 | 1269 | {$ tabs[tab].selectedItems.length $} | ||
556 | 1270 | <span data-ng-pluralize count="tabs[tab].selectedItems.length" when="{'one': 'node', 'other': 'nodes'}"></span> | ||
557 | 1271 | cannot be {$ tabs[tab].actionOption.sentence $}, because an SSH key has not been added to your account. To add an SSH key, visit <a href="account/prefs/">your account page</a>. | ||
558 | 1272 | </p> | ||
559 | 1273 | </section> | ||
560 | 1274 | <section class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="tabs[tab].actionProgress.showing_confirmation"> | ||
561 | 1275 | <p class="page-header__message page-header__message--warning"> | ||
562 | 1276 | {$ tabs[tab].actionProgress.affected_nodes $} of {$ tabs[tab].selectedItems.length $} are in a deployed state. Are you sure you want to continue to test hardware? | ||
563 | 1277 | </p> | ||
564 | 1278 | <div class="page-header__controls"> | ||
565 | 1279 | <button class="button--base button--inline" data-ng-click="actionCancel(tab)">No</button> | ||
566 | 1280 | <button class="button--secondary button--inline" data-ng-click="actionGo(tab)">Yes</button> | ||
567 | 1281 | </div> | ||
568 | 1282 | </section> | ||
569 | 1283 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
570 | 1284 | <section class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="hasActionsInProgress(tab) || hasActionsFailed(tab)"> | ||
571 | 1285 | <p class="page-header__message" data-ng-show="hasActionsInProgress(tab)"> | ||
572 | 1286 | <i class="icon icon--loading u-animation--spin"></i> | ||
573 | 1287 | {$ tabs[tab].actionProgress.completed $} of {$ tabs[tab].actionProgress.total $} | ||
574 | 1288 | nodes are transitioning to {$ tabs[tab].actionOption.sentence $}. | ||
575 | 1289 | </p> | ||
576 | 1290 | <p class="page-header__message page-header__message--error" | ||
577 | 1291 | data-ng-repeat="(error, nodes) in tabs[tab].actionProgress.errors"> | ||
578 | 1292 | The {$ tabs[tab].actionOption.title.toLowerCase() $} action for {$ nodes.length $} | ||
579 | 1293 | <span data-ng-pluralize count="nodes.length" when="{'one': 'node', 'other': 'nodes'}"></span> | ||
580 | 1294 | failed with error: {$ error $} | ||
581 | 1295 | </p> | ||
582 | 1296 | </section> | ||
583 | 1297 | </div> | ||
584 | 1298 | |||
585 | 1299 | </div> | ||
586 | 1300 | |||
587 | 1301 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
588 | 1302 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': addHardwareScope.viewable }" data-ng-controller="AddHardwareController"> | ||
589 | 1303 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
590 | 1304 | <section class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="showMachine()"> | ||
591 | 1305 | <h3 class="page-header__dropdown-title">Add machine</h3> | ||
592 | 1306 | <form class="form form--stack"> | ||
593 | 1307 | <fieldset class="form__fieldset six-col"> | ||
594 | 1308 | <div class="form__group"> | ||
595 | 1309 | <label for="machine-name" class="form__label two-col">Machine name</label> | ||
596 | 1310 | <div class="form__group-input three-col"> | ||
597 | 1311 | <input type="text" id="machine-name" placeholder="Choose a machine name (optional)" | ||
598 | 1312 | data-ng-model="machine.name"> | ||
599 | 1313 | </div> | ||
600 | 1314 | </div> | ||
601 | 1315 | <div class="form__group"> | ||
602 | 1316 | <label for="domain" class="form__group-label two-col">Domain</label> | ||
603 | 1317 | <div class="form__group-input three-col"> | ||
604 | 1318 | <select name="domain" id="domain" | ||
605 | 1319 | data-ng-model="machine.domain" | ||
606 | 1320 | data-ng-options="domain as domain.name for domain in domains"> | ||
607 | 1321 | <option value="" disabled>Choose a domain</option> | ||
608 | 1322 | </select> | ||
609 | 1323 | </div> | ||
610 | 1324 | </div> | ||
611 | 1325 | <div class="form__group"> | ||
612 | 1326 | <label for="architecture" class="form__group-label two-col">Architecture</label> | ||
613 | 1327 | <div class="form__group-input three-col"> | ||
614 | 1328 | <select name="architecture" id="architecture" | ||
615 | 1329 | data-ng-model="machine.architecture" | ||
616 | 1330 | data-ng-options="arch for arch in architectures"> | ||
617 | 1331 | <option value="" disabled>Choose an architecture</option> | ||
618 | 1332 | </select> | ||
619 | 1333 | </div> | ||
620 | 1334 | </div> | ||
621 | 1335 | <div class="form__group"> | ||
622 | 1336 | <label for="min_hwe_kernel" class="form__group-label two-col">Minimum Kernel</label> | ||
623 | 1337 | <div class="form__group-input three-col"> | ||
624 | 1338 | <select name="min_hwe_kernel" id="min_hwe_kernel" | ||
625 | 1339 | data-ng-model="machine.min_hwe_kernel" | ||
626 | 1340 | data-ng-options="hwe_kernel[0] as hwe_kernel[1] for hwe_kernel in hwe_kernels"> | ||
627 | 1341 | <option value="">No minimum kernel</option> | ||
628 | 1342 | </select> | ||
629 | 1343 | </div> | ||
630 | 1344 | </div> | ||
631 | 1345 | <div class="form__group"> | ||
632 | 1346 | <label for="zone4" class="form__group-label two-col">Zone</label> | ||
633 | 1347 | <select name="zone" id="zone4" class="three-col" | ||
634 | 1348 | data-ng-model="machine.zone" | ||
635 | 1349 | data-ng-options="zone as zone.name for zone in zones"> | ||
636 | 1350 | </select> | ||
637 | 1351 | </div> | ||
638 | 1352 | <div class="form__group" data-ng-repeat="mac in machine.macs"> | ||
639 | 1353 | <label for="mac-address" class="form__group-label two-col"><span data-ng-hide="mac !== machine.macs[0]">MAC Address</span> </label> | ||
640 | 1354 | <div class="form__group-input three-col"> | ||
641 | 1355 | <input type="text" id="mac-address" placeholder="00:00:00:00:00:00" | ||
642 | 1356 | maxlength="17" | ||
643 | 1357 | data-ng-class="{ 'has-error': mac.error }" | ||
644 | 1358 | data-ng-model="mac.mac" | ||
645 | 1359 | data-ng-pattern="macAddressRegex" | ||
646 | 1360 | data-ng-change="validateMac(mac)" | ||
647 | 1361 | mac-address> | ||
648 | 1362 | <span class="form__group-remove" title="Delete MAC" | ||
649 | 1363 | data-ng-hide="mac === machine.macs[0]" data-ng-click="removeMac(mac)"></span> | ||
650 | 1364 | </div> | ||
651 | 1365 | </div> | ||
652 | 1366 | <div class="form__group"> | ||
653 | 1367 | <div class="five-col"> | ||
654 | 1368 | <button class="button--secondary button--inline u-float--right" data-ng-click="addMac()">+ Add MAC Address</a> | ||
655 | 1369 | </div> | ||
656 | 1370 | </div> | ||
657 | 1371 | </fieldset> | ||
658 | 1372 | <fieldset class="form__fieldset six-col last-col" | ||
659 | 1373 | data-maas-power-parameters="power_types" | ||
660 | 1374 | data-ng-model="machine.power"> | ||
661 | 1375 | </fieldset> | ||
662 | 1376 | </form> | ||
663 | 1377 | </section> | ||
664 | 1378 | <section class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="showChassis()"> | ||
665 | 1379 | <h3 class="page-header__dropdown-title">Add chassis</h3> | ||
666 | 1380 | <form action="post" class="form form--stack"> | ||
667 | 1381 | <fieldset class="form__fieldset six-col" | ||
668 | 1382 | data-maas-power-parameters="chassisPowerTypes" | ||
669 | 1383 | data-ng-model="chassis.power"> | ||
670 | 1384 | </fieldset> | ||
671 | 1385 | <fieldset class="form__fieldset six-col last-col"> | ||
672 | 1386 | <div class="form__group"> | ||
673 | 1387 | <label for="domain2" class="form__group-label two-col">Domain</label> | ||
674 | 1388 | <div class="form__group-input three-col"> | ||
675 | 1389 | <select name="domain" id="domain2" | ||
676 | 1390 | data-ng-model="chassis.domain" | ||
677 | 1391 | data-ng-options="domain as domain.name for domain in domains"> | ||
678 | 1392 | </select> | ||
679 | 1393 | </div> | ||
680 | 1394 | </div> | ||
681 | 1395 | </fieldset> | ||
682 | 1396 | </form> | ||
683 | 1397 | </section> | ||
684 | 1398 | |||
685 | 1399 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
686 | 1400 | <section class="page-header__section twelve-col u-margin--bottom-none" data-ng-show="showMachine()"> | ||
687 | 1401 | <p class="page-header__message page-header__message--error ng-hide" data-ng-show="error">{$ error $}</p> | ||
688 | 1402 | <div class="page-header__controls"> | ||
689 | 1403 | <button class="button--base button--inline" data-ng-click="cancel()">Cancel</button> | ||
690 | 1404 | <button class="button--secondary button--inline" | ||
691 | 1405 | data-ng-disabled="machineHasError()" | ||
692 | 1406 | data-ng-click="saveMachine(true)">Save and add another</button> | ||
693 | 1407 | <button class="button--positive button--inline" | ||
694 | 1408 | data-ng-disabled="machineHasError()" | ||
695 | 1409 | data-ng-click="saveMachine(false)">Save machine</button> | ||
696 | 1410 | </div> | ||
697 | 1411 | </section> | ||
698 | 1412 | |||
699 | 1413 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
700 | 1414 | <section class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="showChassis()"> | ||
701 | 1415 | <p class="page-header__message page-header__message--error ng-hide" data-ng-show="error">{$ error $}</p> | ||
702 | 1416 | <div class="page-header__controls"> | ||
703 | 1417 | <button class="button--base button--inline" data-ng-click="cancel()">Cancel</button> | ||
704 | 1418 | <button class="button--secondary button--inline" | ||
705 | 1419 | data-ng-disabled="chassisHasErrors()" | ||
706 | 1420 | data-ng-click="saveChassis(true)">Save and add another</button> | ||
707 | 1421 | <button class="button--positive button--inline" | ||
708 | 1422 | data-ng-disabled="chassisHasErrors()" | ||
709 | 1423 | data-ng-click="saveChassis(false)">Save chassis</button> | ||
710 | 1424 | </div> | ||
711 | 1425 | </section> | ||
712 | 1426 | |||
713 | 1427 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
714 | 1428 | <section class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="architectures.length"> | ||
715 | 1429 | <p class="page-header__message page-header__message--error"> | ||
716 | 1430 | Cannot add {$ mode $} until boot images have been imported. To fix, visit the <a href="#/images">images page</a>. | ||
717 | 1431 | </p> | ||
718 | 1432 | </section> | ||
719 | 1433 | </div> | ||
720 | 1434 | |||
721 | 1435 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
722 | 1436 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': tabs.devices.actionOption }"> | ||
723 | 1437 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
724 | 1438 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-hide="isActionError('devices') || hasActionsInProgress('devices')"> | ||
725 | 1439 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
726 | 1440 | <form class="form form--inline u-display--inline"> | ||
727 | 1441 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs.devices.actionOption.name === 'set-zone'"> | ||
728 | 1442 | <div class="form__group"> | ||
729 | 1443 | <label class="form__group-label" for="zone1">Set zone</label> | ||
730 | 1444 | <select name="zone" id="zone1" | ||
731 | 1445 | data-ng-model="tabs.devices.zoneSelection" | ||
732 | 1446 | data-ng-options="zone as zone.name for zone in zones"> | ||
733 | 1447 | <option value="" disabled="disabled">Choose a zone</option> | ||
734 | 1448 | </select> | ||
735 | 1449 | </div> | ||
736 | 1450 | </fieldset> | ||
737 | 1451 | <div class="page-header__controls"> | ||
738 | 1452 | <button class="button--base button--inline" data-ng-click="actionCancel('devices')">Cancel</button> | ||
739 | 1453 | <button class="button--positive button--inline" data-ng-click="actionGo('devices')"> | ||
740 | 1454 | <span data-ng-if="tabs.devices.actionOption.name === 'set-zone'">Set zone for {$ tabs.devices.selectedItems.length $} | ||
741 | 1455 | <span data-ng-pluralize count="tabs.devices.selectedItems.length" when="{'one': 'device', 'other': 'devices'}"></span> | ||
742 | 1456 | </span> | ||
743 | 1457 | <span data-ng-if="tabs.devices.actionOption.name === 'delete'">Delete {$ tabs.devices.selectedItems.length $} | ||
744 | 1458 | <span data-ng-pluralize count="tabs.devices.selectedItems.length" when="{'one': 'device', 'other': 'devices'}"></span> | ||
745 | 1459 | </span> | ||
746 | 1460 | </button> | ||
747 | 1461 | </div> | ||
748 | 1462 | </form> | ||
749 | 1463 | </div> | ||
750 | 1464 | |||
751 | 1465 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
752 | 1466 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="isActionError('devices')"> | ||
753 | 1467 | <p class="page-header__message page-header__message--error"> | ||
754 | 1468 | {$ tabs.devices.actionErrorCount $} | ||
755 | 1469 | <span data-ng-pluralize count="tabs.devices.selectedItems.length" when="{'one': 'device', 'other': 'devices'}"></span> | ||
756 | 1470 | cannot be {$ tabs.devices.actionOption.sentence $}. To proceed, update your selection. | ||
757 | 1471 | </p> | ||
758 | 1472 | </div> | ||
759 | 1473 | |||
760 | 1474 | <!-- XXX blake_r 2015-05-07 - Need to add e2e test. --> | ||
761 | 1475 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="hasActionsInProgress('devices') || hasActionsFailed('devices')"> | ||
762 | 1476 | <p class="page-header__message" data-ng-show="hasActionsInProgress('devices')"> | ||
763 | 1477 | <i class="icon icon--loading u-animation--spin"></i> | ||
764 | 1478 | {$ tabs.devices.actionProgress.completed $} of {$ tabs.devices.actionProgress.total $} | ||
765 | 1479 | devices have been {$ tabs.devices.actionOption.sentence $}. | ||
766 | 1480 | </p> | ||
767 | 1481 | <p class="page-header__message page-header__message--error" | ||
768 | 1482 | data-ng-repeat="(error, devices) in tabs.devices.actionProgress.errors"> | ||
769 | 1483 | The {$ tabs.devices.actionOption.title.toLowerCase() $} action for {$ devices.length $} | ||
770 | 1484 | <span data-ng-pluralize count="devices.length" when="{'one': 'device', 'other': 'devices'}"></span> | ||
771 | 1485 | failed with error: {$ error $} | ||
772 | 1486 | </p> | ||
773 | 1487 | </div> | ||
774 | 1488 | </div> | ||
775 | 1489 | |||
776 | 1490 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
777 | 1491 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': addDeviceScope.viewable }" data-ng-controller="AddDeviceController"> | ||
778 | 1492 | <section class="page-header__section twelve-col u-margin--bottom-none"> | ||
779 | 1493 | <h3 class="page-header__dropdown-title">Add device</h3> | ||
780 | 1494 | <form class="form form--stack"> | ||
781 | 1495 | <fieldset class="form__fieldset six-col"> | ||
782 | 1496 | <div class="form__group"> | ||
783 | 1497 | <label for="device-name" class="form__group-label two-col">Name</label> | ||
784 | 1498 | <div class="form__group-input three-col"> | ||
785 | 1499 | <input type="text" id="device-name" placeholder="Name your device" | ||
786 | 1500 | data-ng-model="device.name" | ||
787 | 1501 | data-ng-class="{ 'has-error': nameHasError() }"> | ||
788 | 1502 | </div> | ||
789 | 1503 | |||
790 | 1504 | </div> | ||
791 | 1505 | <div class="form__group"> | ||
792 | 1506 | <label for="domain3" class="form__group-label two-col">Domain</label> | ||
793 | 1507 | <div class="form__group-input three-col"> | ||
794 | 1508 | <select name="domain" id="domain3" | ||
795 | 1509 | data-ng-model="device.domain" | ||
796 | 1510 | data-ng-options="domain as domain.name for domain in domains"> | ||
797 | 1511 | </select> | ||
798 | 1512 | </div> | ||
799 | 1513 | </div> | ||
800 | 1514 | </fieldset> | ||
801 | 1515 | </form> | ||
802 | 1516 | <table> | ||
803 | 1517 | <thead> | ||
804 | 1518 | <tr> | ||
805 | 1519 | <th class="table-col--20">MAC address</th> | ||
806 | 1520 | <th class="table-col--20">IP assignment</th> | ||
807 | 1521 | <th class="table-col--20">Subnet</th> | ||
808 | 1522 | <th class="table-col--35">IP address</th> | ||
809 | 1523 | <th class="table-col--5"></th> | ||
810 | 1524 | </tr> | ||
811 | 1525 | </thead> | ||
812 | 1526 | <tbody vs-repeat vs-scroll-parent="window"> | ||
813 | 1527 | <tr data-ng-repeat="interface in device.interfaces"> | ||
814 | 1528 | <td class="table-col--20" aria-label="MAC address"> | ||
815 | 1529 | <input type="text" id="mac-address1" placeholder="00:00:00:00:00:00" | ||
816 | 1530 | data-ng-model="interface.mac" | ||
817 | 1531 | data-ng-class="{ 'has-error': macHasError(interface) }"> | ||
818 | 1532 | </td> | ||
819 | 1533 | <td class="table-col--20" aria-label="IP assignment"> | ||
820 | 1534 | <select name="ip-assignment" id="ip-assignment" | ||
821 | 1535 | data-ng-model="interface.ipAssignment" | ||
822 | 1536 | data-ng-options="assigment.title for assigment in ipAssignments"> | ||
823 | 1537 | <option value="" disabled selected>Select IP assignment</option> | ||
824 | 1538 | </select> | ||
825 | 1539 | </td> | ||
826 | 1540 | <td class="table-col--20" aria-label="Subnet"> | ||
827 | 1541 | <select name="subnet" id="subnet" | ||
828 | 1542 | data-ng-model="interface.subnetId" | ||
829 | 1543 | data-ng-options="subnet.id as subnet.name for subnet in subnets" | ||
830 | 1544 | data-ng-show="interface.ipAssignment.name === 'static'"> | ||
831 | 1545 | <option value="" disabled selected>Select subnet</option> | ||
832 | 1546 | </select> | ||
833 | 1547 | </td> | ||
834 | 1548 | <td class="table-col--35" aria-label="IP address"> | ||
835 | 1549 | <input type="text" id="ip-address" placeholder="000.000.000.000" | ||
836 | 1550 | data-ng-model="interface.ipAddress" | ||
837 | 1551 | data-ng-class="{ 'has-error': ipHasError(interface) }" | ||
838 | 1552 | data-ng-show="interface.ipAssignment.name === 'external'"> | ||
839 | 1553 | <input type="text" id="ip-address" | ||
840 | 1554 | data-ng-model="interface.ipAddress" | ||
841 | 1555 | data-ng-class="{ 'has-error': ipHasError(interface) }" | ||
842 | 1556 | data-ng-show="interface.ipAssignment.name === 'static'"> | ||
843 | 1557 | </td> | ||
844 | 1558 | <td class="table-col--5 u-u-align---right table--mobile-controls"> | ||
845 | 1559 | <!-- space needed to set correct height --> | ||
846 | 1560 | <span data-ng-show="isPrimaryInterface(interface)"> </span> | ||
847 | 1561 | <a title="Delete" class="icon icon--remove u-display--desktop" | ||
848 | 1562 | data-ng-click="deleteInterface(interface)" | ||
849 | 1563 | data-ng-hide="isPrimaryInterface(interface)">delete</a> | ||
850 | 1564 | <button class="button--secondary u-display--mobile" | ||
851 | 1565 | data-ng-click="deleteInterface(interface)" | ||
852 | 1566 | data-ng-hide="isPrimaryInterface(interface)">delete</a> | ||
853 | 1567 | </td> | ||
854 | 1568 | </tr> | ||
855 | 1569 | </tbody> | ||
856 | 1570 | </table> | ||
857 | 1571 | <button class="button--secondary button--inline" data-ng-click="addInterface()">+ Add another interface</button> | ||
858 | 1572 | </section> | ||
859 | 1573 | <section class="page-header__section twelve-col u-margin--bottom-none twelve-col u-margin--bottom-none"> | ||
860 | 1574 | <form class="form form--inline"> | ||
861 | 1575 | <p class="page-header__message page-header__message--error ng-hide" data-ng-show="error">{$ error $}</p> | ||
862 | 1576 | <div class="page-header__controls"> | ||
863 | 1577 | <button class="button--base button--inline" data-ng-click="cancel()">Cancel</button> | ||
864 | 1578 | <button class="button--secondary button--inline" | ||
865 | 1579 | data-ng-class="{ disabled: deviceHasError() }" | ||
866 | 1580 | data-ng-click="save(true)">Save and add another</button> | ||
867 | 1581 | <button class="button--positive button--inline" | ||
868 | 1582 | data-ng-class="{ disabled: deviceHasError() }" | ||
869 | 1583 | data-ng-click="save(false)">Save device</button> | ||
870 | 1584 | </div> | ||
871 | 1585 | </form> | ||
872 | 1586 | </section> | ||
873 | 1587 | </div> | ||
874 | 1588 | |||
875 | 1589 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
876 | 1590 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': tabs.controllers.actionOption }"> | ||
877 | 1591 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
878 | 1592 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-hide="isActionError('controllers') || hasActionsInProgress('controllers')"> | ||
879 | 1593 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
880 | 1594 | <form class="form form--inline u-display--inline"> | ||
881 | 1595 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs.controllers.actionOption.name === 'set-zone'"> | ||
882 | 1596 | <div class="form__group"> | ||
883 | 1597 | <label for="zone2" class="form__group-label">Select Zone</label> | ||
884 | 1598 | <div class="form__group-input"> | ||
885 | 1599 | <select name="zone" id="zone2" | ||
886 | 1600 | data-ng-model="tabs.controllers.zoneSelection" | ||
887 | 1601 | data-ng-options="zone as zone.name for zone in zones"> | ||
888 | 1602 | <option value="" disabled="disabled">Choose a zone</option> | ||
889 | 1603 | </select> | ||
890 | 1604 | </div> | ||
891 | 1605 | </div> | ||
892 | 1606 | </fieldset> | ||
893 | 1607 | <fieldset class="form__fieldset ng-hide" data-ng-show="tabs.controllers.actionOption.name === 'test'"> | ||
894 | 1608 | <div class="form__group"> | ||
895 | 1609 | <input class="form__group-label" id="enable_SSH" type="checkbox" | ||
896 | 1610 | data-ng-model="tabs.controllers.commissionOptions.enableSSH"> | ||
897 | 1611 | <label class="checkbox-label" for="enable_SSH">Allow SSH access and prevent machine from powering off</label> | ||
898 | 1612 | </div> | ||
899 | 1613 | </fieldset> | ||
900 | 1614 | </form> | ||
901 | 1615 | <div class="page-header__controls" data-ng-if="tabs.controllers.actionOption.name !== 'test'"> | ||
902 | 1616 | <button class="button--base button--inline" data-ng-click="actionCancel('controllers')">Cancel</button> | ||
903 | 1617 | <button class="button--positive button--inline" data-ng-click="actionGo('controllers')"> | ||
904 | 1618 | <span data-ng-if="tabs.controllers.actionOption.name === 'set-zone'">Set zone for {$ tabs.controllers.selectedItems.length $} | ||
905 | 1619 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
906 | 1620 | </span> | ||
907 | 1621 | <span data-ng-if="tabs.controllers.actionOption.name === 'on'">Power on {$ tabs.controllers.selectedItems.length $} | ||
908 | 1622 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
909 | 1623 | </span> | ||
910 | 1624 | <span data-ng-if="tabs.controllers.actionOption.name === 'off'">Power off {$ tabs.controllers.selectedItems.length $} | ||
911 | 1625 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
912 | 1626 | </span> | ||
913 | 1627 | <span data-ng-if="tabs.controllers.actionOption.name === 'delete'">Delete {$ tabs.controllers.selectedItems.length $} | ||
914 | 1628 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
915 | 1629 | </span> | ||
916 | 1630 | <span data-ng-if="tabs.controllers.actionOption.name === 'import-images'">Import images for {$ tabs.controllers.selectedItems.length $} | ||
917 | 1631 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
918 | 1632 | </span> | ||
919 | 1633 | </button> | ||
920 | 1634 | </div> | ||
921 | 1635 | </div> | ||
922 | 1636 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-hide="isActionError('controllers') || hasActionsInProgress('controllers')" data-ng-if="tabs.controllers.actionOption.name === 'test'"> | ||
923 | 1637 | <form class="form form--stack"> | ||
924 | 1638 | <fieldset class="form__fieldset eight-col u-margin--bottom-small"> | ||
925 | 1639 | <div class="form__group"> | ||
926 | 1640 | <label for="testing-scripts">Hardware Tests</label> | ||
927 | 1641 | <span id="testing-scripts" data-maas-script-select="script" data-script-type="2" data-ng-model="tabs.nodes.testSelection" class="tags--inline"></span> | ||
928 | 1642 | </div> | ||
929 | 1643 | </fieldset> | ||
930 | 1644 | </form> | ||
931 | 1645 | </div> | ||
932 | 1646 | <div class="page-header__section twelve-col u-margin--bottom-none" data-ng-hide="isActionError('controllers') || hasActionsInProgress('controllers')" data-ng-if="tabs.controllers.actionOption.name === 'test'"> | ||
933 | 1647 | <div class="page-header__controls"> | ||
934 | 1648 | <button class="button--base button--inline" data-ng-click="actionCancel('controllers')">Cancel</button> | ||
935 | 1649 | <button class="button--positive button--inline" data-ng-click="actionGo('controllers')"> | ||
936 | 1650 | <span>Test {$ tabs.controllers.selectedItems.length $} | ||
937 | 1651 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
938 | 1652 | </span> | ||
939 | 1653 | </button> | ||
940 | 1654 | </div> | ||
941 | 1655 | </div> | ||
942 | 1656 | |||
943 | 1657 | <!-- XXX blake_r 2015-04-02 - Need to add e2e test. --> | ||
944 | 1658 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="isActionError('controllers')"> | ||
945 | 1659 | <form class="form form--inline"> | ||
946 | 1660 | <p class="page-header__message page-header__message--error"> | ||
947 | 1661 | {$ tabs.controllers.actionErrorCount $} | ||
948 | 1662 | <span data-ng-pluralize count="tabs.controllers.selectedItems.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
949 | 1663 | cannot be {$ tabs.controllers.actionOption.sentence $}. To proceed, update your selection. | ||
950 | 1664 | </p> | ||
951 | 1665 | </form> | ||
952 | 1666 | </div> | ||
953 | 1667 | |||
954 | 1668 | <!-- XXX blake_r 2015-05-07 - Need to add e2e test. --> | ||
955 | 1669 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="hasActionsInProgress('controllers') || hasActionsFailed('controllers')"> | ||
956 | 1670 | <form class="form form--inline"> | ||
957 | 1671 | <p class="page-header__message" data-ng-show="hasActionsInProgress('controllers')"> | ||
958 | 1672 | <i class="icon icon--loading u-animation--spin u-margin--right-small"></i> | ||
959 | 1673 | {$ tabs.controllers.actionProgress.completed $} of {$ tabs.controllers.actionProgress.total $} | ||
960 | 1674 | controllers have been {$ tabs.controllers.actionOption.sentence $}. | ||
961 | 1675 | </p> | ||
962 | 1676 | <p class="page-header__message page-header__message--error" | ||
963 | 1677 | data-ng-repeat="(error, controllers) in tabs.controllers.actionProgress.errors"> | ||
964 | 1678 | The {$ tabs.controllers.actionOption.title.toLowerCase() $} action for {$ controllers.length $} | ||
965 | 1679 | <span data-ng-pluralize count="controllers.length" when="{'one': 'controller', 'other': 'controllers'}"></span> | ||
966 | 1680 | failed with error: {$ error $} | ||
967 | 1681 | </p> | ||
968 | 1682 | </form> | ||
969 | 1683 | </div> | ||
970 | 1684 | </div> | ||
971 | 1685 | |||
972 | 1686 | <div class="page-header__dropdown" data-ng-class="{ 'is-open': tabs.controllers.addController }"> | ||
973 | 1687 | <!-- XXX blake_r 2015-05-07 - Need to add e2e test. --> | ||
974 | 1688 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="tabs.controllers.addController"> | ||
975 | 1689 | <h3 class="page-header__dropdown-title">Add rack controller</h3> | ||
976 | 1690 | <pre class="u-margin--none"> | ||
977 | 1691 | <code># To add a new rack controller, SSH into the rack controller. | ||
978 | 1692 | # Install the maas-rack-controller package. | ||
979 | 1693 | sudo apt install maas-rack-controller | ||
980 | 1694 | # Register the rack controller with this MAAS. If the rack controller (and machines) | ||
981 | 1695 | # don't have access to the URL, use a different IP address to allow connection. | ||
982 | 1696 | sudo maas-rack register --url {$ tabs.controllers.registerUrl $} --secret {$ tabs.controllers.registerSecret $}</code> | ||
983 | 1697 | </pre> | ||
984 | 1698 | </div> | ||
985 | 1699 | <div class="page-header__section twelve-col u-margin--bottom-none ng-hide" data-ng-show="tabs.controllers.addController"> | ||
986 | 1700 | <form class="form form--inline"> | ||
987 | 1701 | <div class="page-header__controls"> | ||
988 | 1702 | <button class="button--secondary button--inline" | ||
989 | 1703 | data-ng-click="tabs.controllers.addController = false">Close</button> | ||
990 | 1704 | </div> | ||
991 | 1705 | </form> | ||
992 | 1706 | </div> | ||
993 | 1707 | </div> | ||
994 | 1708 | </div> | ||
995 | 1709 | </header> | ||
996 | 1710 | <div sticky media-query="min-width: 769px" offset="89" class="page-navigation" data-ng-class="{ 'u-visibility--hidden': tabs.nodes.actionOption || addHardwareScope.viewable || tabs.devices.actionOption || addDeviceScope.viewable || tabs.controllers.actionOption || tabs.controllers.addController }"> | ||
997 | 1711 | <div class="wrapper--inner"> | ||
998 | 1712 | <nav class="page-navigation__links"> | ||
999 | 1713 | <button class="page-navigation__link tooltip tooltip--right" | ||
1000 | 1714 | aria-label="A deployable node managed by MAAS." | ||
1001 | 1715 | data-ng-class="{ 'is-active': currentpage === 'nodes'}" | ||
1002 | 1716 | data-ng-click="toggleTab('nodes')">{$ nodes.length $} <ng-pluralize count="nodes.length" when="{'one': 'Machine', 'other': 'Machines'}"></ng-pluralize></button> | ||
1003 | 1717 | <button class="page-navigation__link tooltip" | ||
1004 | 1718 | aria-label="A node known to MAAS, but is not deployable." | ||
1005 | 1719 | data-ng-class="{ 'is-active': currentpage === 'devices'}" | ||
1006 | 1720 | data-ng-click="toggleTab('devices')">{$ devices.length $} <ng-pluralize count="devices.length" when="{'one': 'Device', 'other': 'Devices'}"></ng-pluralize></button> | ||
1007 | 1721 | <button class="page-navigation__link tooltip" | ||
1008 | 1722 | data-ng-if="isSuperUser()" | ||
1009 | 1723 | aria-label="A node that provides MAAS services." | ||
1010 | 1724 | data-ng-class="{ 'is-active': currentpage === 'controllers'}" | ||
1011 | 1725 | data-ng-click="toggleTab('controllers')">{$ controllers.length $} <ng-pluralize count="controllers.length" when="{'one': 'Controller', 'other': 'Controllers'}"></ng-pluralize></button> | ||
1012 | 1726 | <button class="page-navigation__link tooltip" | ||
1013 | 1727 | data-ng-if="showswitches" | ||
1014 | 1728 | aria-label="A node that is a network switch." | ||
1015 | 1729 | data-ng-class="{ 'is-active': currentpage === 'switches'}" | ||
1016 | 1730 | data-ng-click="toggleTab('switches')">{$ switches.length $} <ng-pluralize count="switches.length" when="{'one': 'Switch', 'other': 'Switches'}"></ng-pluralize></button> | ||
1017 | 1731 | </nav> | ||
1018 | 1732 | </div> | ||
1019 | 1733 | </div> | ||
1020 | 1734 | <div class="u-padding--top row"> | ||
1021 | 1735 | <div class="wrapper--inner"> | ||
1022 | 1736 | <maas-notifications></maas-notifications> | ||
1023 | 1737 | <aside class="three-col"> | ||
1024 | 1738 | <div class="accordion maas-accordion ng-hide" data-ng-show="currentpage === 'nodes'" | ||
1025 | 1739 | data-ng-class="{ 'is-disabled': tabs.nodes.actionOption }"> | ||
1026 | 1740 | <h3 class="accordion__title" | ||
1027 | 1741 | data-ng-class="{'is-active': isActive}" | ||
1028 | 1742 | data-ng-init="isActive = false" | ||
1029 | 1743 | data-ng-click="isActive = !isActive">Filter by</h3> | ||
1030 | 1744 | <div class="accordion__content"> | ||
1031 | 1745 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
1032 | 1746 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.status.length"> | ||
1033 | 1747 | <button class="accordion__tab-title maas-accordion-tab is-active">Status</button> | ||
1034 | 1748 | <div class="accordion__tab-content"> | ||
1035 | 1749 | <ul class="accordion__tab-list"> | ||
1036 | 1750 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
1037 | 1751 | <li class="accordion__tab-item" data-ng-repeat="status in tabs.nodes.metadata.status | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('status', status.name, 'nodes') }"> | ||
1038 | 1752 | <button class="accordion__tab-link" data-ng-click="toggleFilter('status', status.name, 'nodes')">{$ status.name $} ({$ status.count $})</button> | ||
1039 | 1753 | </li> | ||
1040 | 1754 | </ul> | ||
1041 | 1755 | </div> | ||
1042 | 1756 | </div> | ||
1043 | 1757 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.owner.length"> | ||
1044 | 1758 | <button class="accordion__tab-title maas-accordion-tab">Owner</button> | ||
1045 | 1759 | <div class="accordion__tab-content"> | ||
1046 | 1760 | <ul class="accordion__tab-list"> | ||
1047 | 1761 | <li class="accordion__tab-item" data-ng-repeat="owner in tabs.nodes.metadata.owner | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('owner', owner.name, 'nodes') }"> | ||
1048 | 1762 | <button class="accordion__tab-link" data-ng-click="toggleFilter('owner', owner.name, 'nodes')">{$ owner.name $} ({$ owner.count $})</button> | ||
1049 | 1763 | </li> | ||
1050 | 1764 | </ul> | ||
1051 | 1765 | </div> | ||
1052 | 1766 | </div> | ||
1053 | 1767 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.architecture.length"> | ||
1054 | 1768 | <button class="accordion__tab-title maas-accordion-tab">Architectures</button> | ||
1055 | 1769 | <div class="accordion__tab-content"> | ||
1056 | 1770 | <ul class="accordion__tab-list"> | ||
1057 | 1771 | <li class="accordion__tab-item" data-ng-repeat="architecture in tabs.nodes.metadata.architecture | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('architecture', architecture.name, 'nodes') }"> | ||
1058 | 1772 | <button class="accordion__tab-link" data-ng-click="toggleFilter('architecture', architecture.name, 'nodes')"><span data-maas-release-name="architecture.name"></span> ({$ architecture.count $})</button> | ||
1059 | 1773 | </li> | ||
1060 | 1774 | </ul> | ||
1061 | 1775 | </div> | ||
1062 | 1776 | </div> | ||
1063 | 1777 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.release.length"> | ||
1064 | 1778 | <button class="accordion__tab-title maas-accordion-tab">OS/Release</button> | ||
1065 | 1779 | <div class="accordion__tab-content"> | ||
1066 | 1780 | <ul class="accordion__tab-list"> | ||
1067 | 1781 | <li class="accordion__tab-item" data-ng-repeat="release in tabs.nodes.metadata.release | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('release', release.name, 'nodes') }"> | ||
1068 | 1782 | <button class="accordion__tab-link" data-ng-click="toggleFilter('release', release.name, 'nodes')"><span data-maas-release-name="release.name"></span> ({$ release.count $})</button> | ||
1069 | 1783 | </li> | ||
1070 | 1784 | </ul> | ||
1071 | 1785 | </div> | ||
1072 | 1786 | </div> | ||
1073 | 1787 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.tags.length"> | ||
1074 | 1788 | <button class="accordion__tab-title maas-accordion-tab">Tags</button> | ||
1075 | 1789 | <div class="accordion__tab-content"> | ||
1076 | 1790 | <ul class="accordion__tab-list"> | ||
1077 | 1791 | <li class="accordion__tab-item" data-ng-repeat="tag in tabs.nodes.metadata.tags | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('tags', tag.name, 'nodes') }"> | ||
1078 | 1792 | <button class="accordion__tab-link" data-ng-click="toggleFilter('tags', tag.name, 'nodes')">{$ tag.name $} ({$ tag.count $})</button> | ||
1079 | 1793 | </li> | ||
1080 | 1794 | </ul> | ||
1081 | 1795 | </div> | ||
1082 | 1796 | </div> | ||
1083 | 1797 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.storage_tags.length"> | ||
1084 | 1798 | <button class="accordion__tab-title maas-accordion-tab">Storage Tags</button> | ||
1085 | 1799 | <div class="accordion__tab-content"> | ||
1086 | 1800 | <ul class="accordion__tab-list"> | ||
1087 | 1801 | <li class="accordion__tab-item" data-ng-repeat="tag in tabs.nodes.metadata.storage_tags | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('storage_tags', tag.name, 'nodes') }"> | ||
1088 | 1802 | <button class="accordion__tab-link" data-ng-click="toggleFilter('storage_tags', tag.name, 'nodes')">{$ tag.name $} ({$ tag.count $})</button> | ||
1089 | 1803 | </li> | ||
1090 | 1804 | </ul> | ||
1091 | 1805 | </div> | ||
1092 | 1806 | </div> | ||
1093 | 1807 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.subnets.length"> | ||
1094 | 1808 | <button class="accordion__tab-title maas-accordion-tab">Subnets</button> | ||
1095 | 1809 | <div class="accordion__tab-content"> | ||
1096 | 1810 | <ul class="accordion__tab-list"> | ||
1097 | 1811 | <li class="accordion__tab-item" data-ng-repeat="subnet in tabs.nodes.metadata.subnets | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('subnets', subnet.name, 'nodes') }"> | ||
1098 | 1812 | <button class="accordion__tab-link" data-ng-click="toggleFilter('subnets', subnet.name, 'nodes')">{$ subnet.name $} ({$ subnet.count $})</button> | ||
1099 | 1813 | </li> | ||
1100 | 1814 | </ul> | ||
1101 | 1815 | </div> | ||
1102 | 1816 | </div> | ||
1103 | 1817 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.fabrics.length"> | ||
1104 | 1818 | <button class="accordion__tab-title maas-accordion-tab">Fabrics</button> | ||
1105 | 1819 | <div class="accordion__tab-content"> | ||
1106 | 1820 | <ul class="accordion__tab-list"> | ||
1107 | 1821 | <li class="accordion__tab-item" data-ng-repeat="fabric in tabs.nodes.metadata.fabrics | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('fabrics', fabric.name, 'nodes') }"> | ||
1108 | 1822 | <button class="accordion__tab-link" data-ng-click="toggleFilter('fabrics', fabric.name, 'nodes')">{$ fabric.name $} ({$ fabric.count $})</button> | ||
1109 | 1823 | </li> | ||
1110 | 1824 | </ul> | ||
1111 | 1825 | </div> | ||
1112 | 1826 | </div> | ||
1113 | 1827 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.spaces.length"> | ||
1114 | 1828 | <button class="accordion__tab-title maas-accordion-tab">Spaces</button> | ||
1115 | 1829 | <div class="accordion__tab-content"> | ||
1116 | 1830 | <ul class="accordion__tab-list"> | ||
1117 | 1831 | <li class="accordion__tab-item" data-ng-repeat="space in tabs.nodes.metadata.spaces | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('spaces', space.name, 'nodes') }"> | ||
1118 | 1832 | <button class="accordion__tab-link" data-ng-click="toggleFilter('spaces', space.name, 'nodes')">{$ space.name $} ({$ space.count $})</button> | ||
1119 | 1833 | </li> | ||
1120 | 1834 | </ul> | ||
1121 | 1835 | </div> | ||
1122 | 1836 | </div> | ||
1123 | 1837 | <div class="ng-hide accordion__tab" data-ng-show="tabs.nodes.metadata.zone.length"> | ||
1124 | 1838 | <button class="accordion__tab-title maas-accordion-tab">Zones</button> | ||
1125 | 1839 | <div class="accordion__tab-content"> | ||
1126 | 1840 | <ul class="accordion__tab-list"> | ||
1127 | 1841 | <li class="accordion__tab-item" data-ng-repeat="zone in tabs.nodes.metadata.zone | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('zone', zone.name, 'nodes') }"> | ||
1128 | 1842 | <button class="accordion__tab-link" data-ng-click="toggleFilter('zone', zone.name, 'nodes')">{$ zone.name $} ({$ zone.count $})</button> | ||
1129 | 1843 | </li> | ||
1130 | 1844 | </ul> | ||
1131 | 1845 | </div> | ||
1132 | 1846 | </div> | ||
1133 | 1847 | </div> | ||
1134 | 1848 | </div> | ||
1135 | 1849 | <div class="accordion three-col maas-accordion ng-hide" data-ng-show="currentpage === 'devices'" | ||
1136 | 1850 | data-ng-class="{ 'is-disabled': tabs.devices.actionOption }"> | ||
1137 | 1851 | <h3 class="accordion__title">Filter by</h3> | ||
1138 | 1852 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1139 | 1853 | <div class="ng-hide accordion__tab" data-ng-show="tabs.devices.metadata.owner.length"> | ||
1140 | 1854 | <button class="accordion__tab-title maas-accordion-tab active">Owner</button> | ||
1141 | 1855 | <div class="accordion__tab-content"> | ||
1142 | 1856 | <ul class="accordion__tab-list"> | ||
1143 | 1857 | <li class="accordion__tab-item" data-ng-repeat="owner in tabs.devices.metadata.owner | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('owner', owner.name, 'devices') }"> | ||
1144 | 1858 | <button class="accordion__tab-link" data-ng-click="toggleFilter('owner', owner.name, 'devices')">{$ owner.name $} ({$ owner.count $})</button> | ||
1145 | 1859 | </li> | ||
1146 | 1860 | </ul> | ||
1147 | 1861 | </div> | ||
1148 | 1862 | </div> | ||
1149 | 1863 | <div class="ng-hide accordion__tab" data-ng-show="tabs.devices.metadata.tags.length"> | ||
1150 | 1864 | <button class="accordion__tab-title maas-accordion-tab">Tags</button> | ||
1151 | 1865 | <div class="accordion__tab-content"> | ||
1152 | 1866 | <ul class="accordion__tab-list"> | ||
1153 | 1867 | <li class="accordion__tab-item" data-ng-repeat="tag in tabs.devices.metadata.tags | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('tags', tag.name, 'devices') }"> | ||
1154 | 1868 | <button class="accordion__tab-link" data-ng-click="toggleFilter('tags', tag.name, 'devices')">{$ tag.name $} ({$ tag.count $})</button> | ||
1155 | 1869 | </li> | ||
1156 | 1870 | </ul> | ||
1157 | 1871 | </div> | ||
1158 | 1872 | </div> | ||
1159 | 1873 | <div class="ng-hide accordion__tab" data-ng-show="tabs.devices.metadata.zone.length"> | ||
1160 | 1874 | <button class="accordion__tab-title maas-accordion-tab">Zones</button> | ||
1161 | 1875 | <div class="accordion__tab-content"> | ||
1162 | 1876 | <ul class="accordion__tab-list"> | ||
1163 | 1877 | <li class="accordion__tab-item" data-ng-repeat="zone in tabs.devices.metadata.zone | orderBy:['name', '-count']" data-ng-class="{ 'is-active': isFilterActive('zone', zone.name, 'devices') }"> | ||
1164 | 1878 | <button class="accordion__tab-link" data-ng-click="toggleFilter('zone', zone.name, 'devices')">{$ zone.name $} ({$ zone.count $})</button> | ||
1165 | 1879 | </li> | ||
1166 | 1880 | </ul> | ||
1167 | 1881 | </div> | ||
1168 | 1882 | </div> | ||
1169 | 1883 | </div> | ||
1170 | 1884 | </aside> | ||
1171 | 1885 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
1172 | 1886 | <div class="nine-col last-col ng-hide" data-ng-show="currentpage === 'nodes'"> | ||
1173 | 1887 | <form> | ||
1174 | 1888 | <div id="search-bar" class="search nine-col"> | ||
1175 | 1889 | <!-- XXX ricgard 2016-06-16 - Need to add e2e test. --> | ||
1176 | 1890 | <input | ||
1177 | 1891 | type="search" placeholder="Search nodes" class="search__input" | ||
1178 | 1892 | data-ng-model="tabs.nodes.search" data-ng-change="updateFilters('nodes')" | ||
1179 | 1893 | data-ng-class="{ error: !tabs.nodes.searchValid }" | ||
1180 | 1894 | data-ng-disabled="tabs.nodes.actionOption" /> | ||
1181 | 1895 | <input type="reset" class="search__submit" | ||
1182 | 1896 | data-ng-class="{ 'search__submit--close': tabs.nodes.search.length > 0 }" | ||
1183 | 1897 | data-ng-click="clearSearch('nodes')" /> | ||
1184 | 1898 | </div> | ||
1185 | 1899 | <maas-machines-table id="nodes-listing" search="tabs.nodes.search" ng-disabled="hasActionsInProgress('nodes')" | ||
1186 | 1900 | machine-has-error="!supportsAction($machine, 'nodes')" on-listing-change="onNodeListingChanged($machines, 'nodes')" | ||
1187 | 1901 | on-check-all="toggleCheckAll('nodes')" on-check="toggleChecked($machine, 'nodes')"></maas-machines-table> | ||
1188 | 1902 | </form> | ||
1189 | 1903 | </div> | ||
1190 | 1904 | <div class="nine-col last-col" class="ng-hide" data-ng-show="currentpage === 'devices'"> | ||
1191 | 1905 | <div class="search nine-col"> | ||
1192 | 1906 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1193 | 1907 | <input | ||
1194 | 1908 | type="search" placeholder="Search devices" class="search__input" | ||
1195 | 1909 | data-ng-model="tabs.devices.search" data-ng-change="updateFilters('devices')" | ||
1196 | 1910 | data-ng-class="{ error: !tabs.devices.searchValid }" | ||
1197 | 1911 | data-ng-disabled="tabs.devices.actionOption" /> | ||
1198 | 1912 | <input type="reset" class="search__submit" | ||
1199 | 1913 | data-ng-class="{ 'search__submit--close': tabs.devices.search.length > 0 }" | ||
1200 | 1914 | data-ng-click="clearSearch('devices')" /> | ||
1201 | 1915 | </div> | ||
1202 | 1916 | <table> | ||
1203 | 1917 | <thead> | ||
1204 | 1918 | <tr> | ||
1205 | 1919 | <th class="table-col--3"> | ||
1206 | 1920 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1207 | 1921 | <input type="checkbox" class="checkbox" data-ng-click="toggleCheckAll('devices')" data-ng-checked="tabs.devices.allViewableChecked" id="check-all-devices" data-ng-disabled="hasActionsInProgress('devices')" /> | ||
1208 | 1922 | <label for="check-all-devices" class="checkbox-label"></label> | ||
1209 | 1923 | </th> | ||
1210 | 1924 | <th class="table-col--24"> | ||
1211 | 1925 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1212 | 1926 | <a href="" data-ng-click="sortTable('fqdn', 'devices')" data-ng-class="{'is-sorted': tabs.devices.predicate === 'fqdn', 'sort-asc': tabs.devices.reverse === false, 'sort-desc': tabs.devices.reverse === true}"> | ||
1213 | 1927 | <span title="Fully Qualified Domain Name">FQDN</span> | ||
1214 | 1928 | </a> | ||
1215 | 1929 | </th> | ||
1216 | 1930 | <th class="table-col--25"> | ||
1217 | 1931 | <a href="" data-ng-click="sortTable('primary_mac', 'devices')" data-ng-class="{'is-sorted': tabs.devices.predicate === 'primary_mac', 'sort-asc': tabs.devices.reverse === false, 'sort-desc': tabs.devices.reverse === true}"> | ||
1218 | 1932 | <span title="Media Access Control addresses">MAC</span> | ||
1219 | 1933 | </a> | ||
1220 | 1934 | </th> | ||
1221 | 1935 | <th class="table-col--15"> | ||
1222 | 1936 | <a href="" data-ng-click="sortTable('ip_assignment', 'devices')" data-ng-class="{'is-sorted': tabs.devices.predicate === 'ip_assignment', 'sort-asc': tabs.devices.reverse === false, 'sort-desc': tabs.devices.reverse === true}">IP Assignment</a> | ||
1223 | 1937 | </th> | ||
1224 | 1938 | <th class="table-col--20"> | ||
1225 | 1939 | <a href="" data-ng-click="sortTable('ip_address', 'devices')" data-ng-class="{'is-sorted': tabs.devices.predicate === 'ip_address', 'sort-asc': tabs.devices.reverse === false, 'sort-desc': tabs.devices.reverse === true}">IP Address</a> | ||
1226 | 1940 | </th> | ||
1227 | 1941 | <th class="table-col--12"> | ||
1228 | 1942 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1229 | 1943 | <a href="" data-ng-click="sortTable('owner', 'devices')" data-ng-class="{'is-sorted': tabs.devices.predicate === 'owner', 'sort-asc': tabs.devices.reverse === false, 'sort-desc': tabs.devices.reverse === true}">Owner</a> | ||
1230 | 1944 | </th> | ||
1231 | 1945 | </tr> | ||
1232 | 1946 | </thead> | ||
1233 | 1947 | <tbody vs-repeat vs-scroll-parent="window"> | ||
1234 | 1948 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. This really needs lots of tests. --> | ||
1235 | 1949 | <tr | ||
1236 | 1950 | data-ng-repeat="device in tabs.devices.filtered_items = (devices | nodesFilter:tabs.devices.search | orderBy:tabs.devices.predicate:tabs.devices.reverse) track by device.system_id" | ||
1237 | 1951 | data-ng-class="{ 'table--error': !supportsAction(device, 'devices'), selected: device.$selected }"> | ||
1238 | 1952 | <td class="table-col--3" aria-label="Select device"> | ||
1239 | 1953 | <input type="checkbox" class="checkbox" data-ng-click="toggleChecked(device, 'devices')" data-ng-checked="device.$selected" id="{$ device.fqdn $}" data-ng-disabled="hasActionsInProgress('devices')"/> | ||
1240 | 1954 | <label for="{$ device.fqdn $}" class="checkbox-label"></label> | ||
1241 | 1955 | </td> | ||
1242 | 1956 | <td class="table-col--24" aria-label="FQDN"> | ||
1243 | 1957 | <a href="#/node/device/{$ device.system_id $}">{$ device.fqdn $}</a> | ||
1244 | 1958 | </td> | ||
1245 | 1959 | <td class="table-col--25" aria-label="MAC"> | ||
1246 | 1960 | {$ device.primary_mac $} | ||
1247 | 1961 | <span class="extra-macs" data-ng-show="device.extra_macs.length">(+{$ device.extra_macs.length $})</span> | ||
1248 | 1962 | </td> | ||
1249 | 1963 | <td class="table-col--15" aria-label="IP Assignment">{$ getDeviceIPAssignment(device.ip_assignment) $}</td> | ||
1250 | 1964 | <td class="table-col--20" aria-label="IP Address">{$ device.ip_address $}</td> | ||
1251 | 1965 | <td class="table-col--12" aria-label="Owner">{$ device.owner $}</td> | ||
1252 | 1966 | </tr> | ||
1253 | 1967 | </tbody> | ||
1254 | 1968 | </table> | ||
1255 | 1969 | </div> | ||
1256 | 1970 | <div class="twelve-col last-col" class="ng-hide" data-ng-show="currentpage === 'controllers'"> | ||
1257 | 1971 | <div class="search twelve-col"> | ||
1258 | 1972 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1259 | 1973 | <input | ||
1260 | 1974 | type="search" placeholder="Search controllers" class="search__input" | ||
1261 | 1975 | data-ng-model="tabs.controllers.search" data-ng-change="updateFilters('controllers')" | ||
1262 | 1976 | data-ng-class="{ error: !tabs.controllers.searchValid }" | ||
1263 | 1977 | data-ng-disabled="tabs.controllers.actionOption" /> | ||
1264 | 1978 | <input type="submit" class="search__submit" | ||
1265 | 1979 | data-ng-class="{ 'search__submit--close': tabs.controllers.search.length > 0 }" | ||
1266 | 1980 | data-ng-click="clearSearch('controllers')" /> | ||
1267 | 1981 | </div> | ||
1268 | 1982 | <table> | ||
1269 | 1983 | <thead> | ||
1270 | 1984 | <tr> | ||
1271 | 1985 | <th class="table-col--2"> | ||
1272 | 1986 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1273 | 1987 | <input type="checkbox" class="checkbox" data-ng-click="toggleCheckAll('controllers')" data-ng-checked="tabs.controllers.allViewableChecked" id="check-all-controllers" data-ng-disabled="hasActionsInProgress('controllers')" /> | ||
1274 | 1988 | <label for="check-all-controllers" class="checkbox-label"></label> | ||
1275 | 1989 | </th> | ||
1276 | 1990 | <th class="table-col--19"> | ||
1277 | 1991 | <a href="" data-ng-click="sortTable('fqdn', 'controllers')" data-ng-class="{'is-sorted': tabs.controllers.predicate === 'fqdn', 'sort-asc': tabs.controllers.reverse === false, 'sort-desc': tabs.controllers.reverse === true}"> | ||
1278 | 1992 | <span title="Fully Qualified Domain Name">Name</span> | ||
1279 | 1993 | </a> | ||
1280 | 1994 | </th> | ||
1281 | 1995 | <th class="table-col--4 u-align--center"> | ||
1282 | 1996 | <span title="Status">Status</span> | ||
1283 | 1997 | </th> | ||
1284 | 1998 | <th class="table-col--15"> | ||
1285 | 1999 | <a href="" data-ng-click="sortTable('node_type_display', 'controllers')" data-ng-class="{'is-sorted': tabs.controllers.predicate === 'node_type_display', 'sort-asc': tabs.controllers.reverse === false, 'sort-desc': tabs.controllers.reverse === true}"> | ||
1286 | 2000 | <span title="Controller Type">Type</span> | ||
1287 | 2001 | </a> | ||
1288 | 2002 | </th> | ||
1289 | 2003 | <th class="table-col--10"> | ||
1290 | 2004 | <a href="" data-ng-click="sortTable('node_type_display', 'controllers')" data-ng-class="{'is-sorted': tabs.controllers.predicate === 'version', 'sort-asc': tabs.controllers.reverse === false, 'sort-desc': tabs.controllers.reverse === true}"> | ||
1291 | 2005 | <span title="Version">Version</span> | ||
1292 | 2006 | </a> | ||
1293 | 2007 | </th> | ||
1294 | 2008 | <th class="table-col--15"> | ||
1295 | 2009 | <a href="" data-ng-click="sortTable('updated', 'controllers')" data-ng-class="{'is-sorted': tabs.controllers.predicate === 'updated', 'sort-asc': tabs.controllers.reverse === false, 'sort-desc': tabs.controllers.reverse === true}">Last Image Sync</a> | ||
1296 | 2010 | </th> | ||
1297 | 2011 | <th class="table-col--15"> | ||
1298 | 2012 | <a href="" data-ng-click="sortTable('updated', 'controllers')" data-ng-class="{'is-sorted': tabs.controllers.predicate === 'updated', 'sort-asc': tabs.controllers.reverse === false, 'sort-desc': tabs.controllers.reverse === true}">Images Status</a> | ||
1299 | 2013 | </th> | ||
1300 | 2014 | </tr> | ||
1301 | 2015 | </thead> | ||
1302 | 2016 | <tbody vs-repeat vs-scroll-parent="window"> | ||
1303 | 2017 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. This really needs lots of tests. --> | ||
1304 | 2018 | <tr | ||
1305 | 2019 | data-ng-repeat="controller in tabs.controllers.filtered_items = (controllers | nodesFilter:tabs.controllers.search | orderBy:tabs.controllers.predicate:tabs.controllers.reverse) track by controller.system_id" | ||
1306 | 2020 | data-ng-class="{ 'table--error': !supportsAction(controller, 'controllers'), selected: controller.$selected }"> | ||
1307 | 2021 | <td class="table-col--2" aria-label="Select controller"> | ||
1308 | 2022 | <input type="checkbox" class="checkbox" data-ng-click="toggleChecked(controller, 'controllers')" data-ng-checked="controller.$selected" id="{$ controller.fqdn $}" data-ng-disabled="hasActionsInProgress('controllers')"/> | ||
1309 | 2023 | <label for="{$ controller.fqdn $}" class="checkbox-label"></label> | ||
1310 | 2024 | </td> | ||
1311 | 2025 | <td class="table-col--19" aria-label="FQDN"> | ||
1312 | 2026 | <a href="#/node/controller/{$ controller.system_id $}">{$ controller.fqdn $}</a> | ||
1313 | 2027 | </td> | ||
1314 | 2028 | <td class="table-col--4 u-align--center" data-maas-controller-status="controller" data-maas-services="services" aria-label="Status"></td> | ||
1315 | 2029 | <td class="table-col--15" aria-label="Type">{$ controller.node_type_display $}</td> | ||
1316 | 2030 | <td class="table-col--10" aria-label="Version"> | ||
1317 | 2031 | <div data-ng-show="controller.version"> | ||
1318 | 2032 | {$ controller.version__short $} | ||
1319 | 2033 | </div> | ||
1320 | 2034 | <div data-ng-show="!controller.version" class="u-text--subtle"> | ||
1321 | 2035 | Unknown | ||
1322 | 2036 | <i class="icon icon--info u-margin--left-tiny tooltip" | ||
1323 | 2037 | aria-label="Less than 2.3.0"></i> | ||
1324 | 2038 | </div> | ||
1325 | 2039 | </td> | ||
1326 | 2040 | <td class="table-col--15" aria-label="Last image sync">{$ controller.last_image_sync || 'Never' $}</td> | ||
1327 | 2041 | <td class="table-col--15" aria-label="Image status"> | ||
1328 | 2042 | <maas-controller-image-status system-id="controller.system_id"></maas-controller-image-status> | ||
1329 | 2043 | </td> | ||
1330 | 2044 | </tr> | ||
1331 | 2045 | </tbody> | ||
1332 | 2046 | </table> | ||
1333 | 2047 | </div> | ||
1334 | 2048 | <div class="twelve-col last-col" class="ng-hide" data-ng-show="currentpage === 'switches'"> | ||
1335 | 2049 | <div class="search twelve-col"> | ||
1336 | 2050 | <!-- XXX rvba 2015-02-25 - Need to add e2e test. --> | ||
1337 | 2051 | <input | ||
1338 | 2052 | type="search" placeholder="Search switches" class="search__input" | ||
1339 | 2053 | data-ng-model="tabs.switches.search" data-ng-change="updateFilters('switches')" | ||
1340 | 2054 | data-ng-class="{ error: !tabs.switches.searchValid }" | ||
1341 | 2055 | data-ng-disabled="tabs.switches.actionOption" /> | ||
1342 | 2056 | <input type="submit" class="search__submit" | ||
1343 | 2057 | data-ng-class="{ 'search__submit--close': tabs.switches.search.length > 0 }" | ||
1344 | 2058 | data-ng-click="clearSearch('switches')" /> | ||
1345 | 2059 | </div> | ||
1346 | 2060 | <maas-switches-table id="switches-listing" search="tabs.switches.search" ng-disabled="hasActionsInProgress('switches')" | ||
1347 | 2061 | switch-has-error="!supportsAction($switch_, 'switches')" on-listing-change="onNodeListingChanged($switches, 'switches')" | ||
1348 | 2062 | on-check-all="toggleCheckAll('switches')" on-check="toggleChecked($switch_, 'switches')"></maas-switches-table> | ||
1349 | 2063 | </div> | ||
1350 | 2064 | </div> | ||
1351 | 2065 | </div> | ||
1352 | 2066 | >>>>>>> src/maasserver/static/partials/nodes-list.html | ||
1353 | diff --git a/src/maasserver/static/partials/script-results-list.html b/src/maasserver/static/partials/script-results-list.html | |||
1354 | index bfadd34..60ad83a 100644 | |||
1355 | --- a/src/maasserver/static/partials/script-results-list.html | |||
1356 | +++ b/src/maasserver/static/partials/script-results-list.html | |||
1357 | @@ -4,6 +4,7 @@ | |||
1358 | 4 | <p class="u-text--loading"><i class="p-icon--spinner u-animation--spin"></i> Loading...</p> | 4 | <p class="u-text--loading"><i class="p-icon--spinner u-animation--spin"></i> Loading...</p> |
1359 | 5 | </div> | 5 | </div> |
1360 | 6 | </div> | 6 | </div> |
1361 | 7 | <<<<<<< src/maasserver/static/partials/script-results-list.html | ||
1362 | 7 | <div class="row"> | 8 | <div class="row"> |
1363 | 8 | <div data-ng-repeat="hardware_type in results"> | 9 | <div data-ng-repeat="hardware_type in results"> |
1364 | 9 | <div data-ng-if="resultsLoaded && (hardware_type.results | json) != '{}'"> | 10 | <div data-ng-if="resultsLoaded && (hardware_type.results | json) != '{}'"> |
1365 | @@ -47,12 +48,59 @@ | |||
1366 | 47 | <button class="p-contextual-menu__link" aria-label="View previous {$ result.result_section $}" data-ng-if="!result.showing_history" data-ng-click="toggleMenu(); loadHistory(result)">View previous {$ result.result_section $}</button> | 48 | <button class="p-contextual-menu__link" aria-label="View previous {$ result.result_section $}" data-ng-if="!result.showing_history" data-ng-click="toggleMenu(); loadHistory(result)">View previous {$ result.result_section $}</button> |
1367 | 48 | <button class="p-contextual-menu__link" aria-label="Hide previous {$ result.result_section $}" data-ng-if="result.showing_history" data-ng-click="toggleMenu(); result.showing_results = false; result.showing_history = false">Hide previous {$ result.result_section $}</button> | 49 | <button class="p-contextual-menu__link" aria-label="Hide previous {$ result.result_section $}" data-ng-if="result.showing_history" data-ng-click="toggleMenu(); result.showing_results = false; result.showing_history = false">Hide previous {$ result.result_section $}</button> |
1368 | 49 | </div> | 50 | </div> |
1369 | 51 | ======= | ||
1370 | 52 | <div data-ng-repeat="hardware_type in results"> | ||
1371 | 53 | <div data-ng-if="resultsLoaded && (hardware_type.results | json) != '{}'"> | ||
1372 | 54 | <h2 data-ng-if="hardware_type.title !== 'null'">{$ hardware_type.title $}</h2> | ||
1373 | 55 | <div data-ng-repeat="(title, results) in hardware_type.results"> | ||
1374 | 56 | <h3 data-ng-if="title !== 'null'">{$ title $}</h3> | ||
1375 | 57 | <section class="table u-margin--bottom"> | ||
1376 | 58 | <header class="table__head"> | ||
1377 | 59 | <div class="table__row"> | ||
1378 | 60 | <div class="table__header table-col--2 u-padding--left-none"></div> | ||
1379 | 61 | <div class="table__header table-col--24">Name</div> | ||
1380 | 62 | <div class="table__header table-col--22">Tags</div> | ||
1381 | 63 | <div class="table__header table-col--15">Runtime</div> | ||
1382 | 64 | <div class="table__header table-col--20">Date</div> | ||
1383 | 65 | <div class="table__header table-col--12">Result</div> | ||
1384 | 66 | <div class="table__header table-col--5 u-align--right">Actions</div> | ||
1385 | 67 | </div> | ||
1386 | 68 | </header> | ||
1387 | 69 | <main class="table__body"> | ||
1388 | 70 | <div data-ng-repeat="result in results"> | ||
1389 | 71 | <div class="table__row" data-ng-class="{'is-active': result.showing_results || result.showing_history}"> | ||
1390 | 72 | <div class="table__data table-col--2 u-padding--left-none" aria-label="Status"> | ||
1391 | 73 | <span data-maas-script-status="script-status" data-script-status="result.status"></span> | ||
1392 | 74 | </div> | ||
1393 | 75 | <div class="table__data table-col--24" data-ng-click="result.showing_results = !result.showing_results" aria-label="Name"> | ||
1394 | 76 | {$ result.name $} | ||
1395 | 77 | <button class="icon u-margin--top-tiny u-float--right" data-ng-class="{'icon--open': !result.showing_results, 'icon--close': result.showing_results}" data-ng-if="!result.showing_history"></button> | ||
1396 | 78 | </div> | ||
1397 | 79 | <div class="table__data table-col--22" aria-label="Tags"><span data-ng-hide="result.showing_history">{$ result.tags $}</span></div> | ||
1398 | 80 | <div class="table__data table-col--15" aria-label="Runtime"><span data-ng-hide="result.showing_history" data-maas-script-run-time="script-runtime" data-start-time="result.starttime" data-run-time="{{result.runtime}}" data-estimated-run-time="{{result.estimated_runtime}}" data-script-status="result.status"></span></div> | ||
1399 | 81 | <div class="table__data table-col--20" aria-label="Date"><span data-ng-hide="result.showing_history">{$ result.updated $}</span></div> | ||
1400 | 82 | <div class="table__data table-col--12" aria-label="Status"> | ||
1401 | 83 | <span data-ng-hide="result.showing_history"> | ||
1402 | 84 | <!-- Only link to the testing result when we've received it. This is indicated with status 2(passed), 3(failed), 4(timedout), 6(degraded), 8(failed installing)--> | ||
1403 | 85 | {$ result.status_name $} <a data-ng-if="result.status === 2 || result.status === 3 || result.status === 4 || result.status === 6 || result.status === 8" href="#/node/{$ type_name $}/{$ node.system_id $}/{$ section.area $}/{$ result.id $}">View log</a> | ||
1404 | 86 | </span> | ||
1405 | 87 | </div> | ||
1406 | 88 | <div class="table__data table-col--5 table--mobile-controls"> | ||
1407 | 89 | <div class="table__controls u-align--right" toggle-ctrl> | ||
1408 | 90 | <button class="table__controls-toggle" data-ng-click="toggleMenu()">View actions</button> | ||
1409 | 91 | <div class="table__controls-menu ng-hide" role="menu" data-ng-show="isToggled"> | ||
1410 | 92 | <button class="table__controls-action" aria-label="View metrics" data-ng-if="!result.showing_results" data-ng-click="toggleMenu(); result.showing_history = false; result.showing_results = true">View metrics</button> | ||
1411 | 93 | <button class="table__controls-action" aria-label="Hide metrics" data-ng-if="result.showing_results" data-ng-click="toggleMenu(); result.showing_history = false; result.showing_results = false">Hide metrics</button> | ||
1412 | 94 | <button class="table__controls-action" aria-label="View previous {$ result.result_section $}" data-ng-if="!result.showing_history" data-ng-click="toggleMenu(); result.showing_results = false; result.showing_history = true">View previous {$ result.result_section $}</button> | ||
1413 | 95 | <button class="table__controls-action" aria-label="Hide previous {$ result.result_section $}" data-ng-if="result.showing_history" data-ng-click="toggleMenu(); result.showing_results = false; result.showing_history = false">Hide previous {$ result.result_section $}</button> | ||
1414 | 96 | >>>>>>> src/maasserver/static/partials/script-results-list.html | ||
1415 | 50 | </div> | 97 | </div> |
1416 | 51 | </td> | 98 | </td> |
1417 | 52 | <td class="p-table-expanding__panel col-12" aria-label="results" data-ng-if="result.showing_results && !result.showing_history"> | 99 | <td class="p-table-expanding__panel col-12" aria-label="results" data-ng-if="result.showing_results && !result.showing_history"> |
1418 | 53 | <div class="row"> | 100 | <div class="row"> |
1419 | 54 | <div class="col-12" data-ng-if="result.results.length === 0">No metrics provided</div> | 101 | <div class="col-12" data-ng-if="result.results.length === 0">No metrics provided</div> |
1420 | 55 | </div> | 102 | </div> |
1421 | 103 | <<<<<<< src/maasserver/static/partials/script-results-list.html | ||
1422 | 56 | <div class="row" data-ng-if="result.results"> | 104 | <div class="row" data-ng-if="result.results"> |
1423 | 57 | <dl data-ng-repeat="item in result.results"> | 105 | <dl data-ng-repeat="item in result.results"> |
1424 | 58 | <dt class="p-tooltip p-tooltip--top-center"> | 106 | <dt class="p-tooltip p-tooltip--top-center"> |
1425 | @@ -66,6 +114,34 @@ | |||
1426 | 66 | <td class="p-table-expanding__panel col-12" aria-label="loading history" data-ng-if="result.loading_history"> | 114 | <td class="p-table-expanding__panel col-12" aria-label="loading history" data-ng-if="result.loading_history"> |
1427 | 67 | <div class="col-12"> | 115 | <div class="col-12"> |
1428 | 68 | <p class="u-text--loading"><i class="p-icon--spinner u-animation--spin"></i> Loading...</p> | 116 | <p class="u-text--loading"><i class="p-icon--spinner u-animation--spin"></i> Loading...</p> |
1429 | 117 | ======= | ||
1430 | 118 | </div> | ||
1431 | 119 | </div> | ||
1432 | 120 | |||
1433 | 121 | <div class="table__dropdown" aria-label="history" data-ng-if="result.showing_history"> | ||
1434 | 122 | <div class="table__row is-active"> | ||
1435 | 123 | <div class="table__data table-col--100"> | ||
1436 | 124 | <section class="table u-margin--bottom"> | ||
1437 | 125 | <main class="table__body"> | ||
1438 | 126 | <div class="table__row is-active u-border--none" data-ng-repeat="item in result.history_list"> | ||
1439 | 127 | <div class="table__data table-col--2 u-padding--left-none" aria-label="Status"> | ||
1440 | 128 | <span data-maas-script-status="script-status" data-script-status="item.status"></span> | ||
1441 | 129 | </div> | ||
1442 | 130 | <div class="table__data table-col--24" aria-label="Name">{$ result.name $}</div> | ||
1443 | 131 | <div class="table__data table-col--24" aria-label="Tags">{$ result.tags $}</div> | ||
1444 | 132 | <div class="table__data table-col--15" aria-label="Runtime"><span data-maas-script-run-time="script-runtime" data-start-time="item.starttime" data-run-time="{{item.runtime}}" data-estimated-run-time="{{item.estimated_runtime}}" data-script-status="item.status"></span></div> | ||
1445 | 133 | <div class="table__data table-col--20" aria-label="Date">{$ item.updated $}</div> | ||
1446 | 134 | <div class="table__data table-col--10" aria-label="Status"> | ||
1447 | 135 | <!-- Only link to the testing result when we've received it. This is indicated with status 2(passed), 3(failed), 4(timedout), 6(degraded), 8(failed installing)--> | ||
1448 | 136 | {$ item.status_name $} <a data-ng-if="item.status === 2 || item.status === 3 || item.status === 4 || item.status === 6 || item.status === 8" href="#/node/{$ type_name $}/{$ node.system_id $}/{$ section.area $}/{$ item.id $}">View log</a> | ||
1449 | 137 | </div> | ||
1450 | 138 | </div> | ||
1451 | 139 | </main> | ||
1452 | 140 | </section> | ||
1453 | 141 | <p class="u-align--center u-margin--bottom"> | ||
1454 | 142 | <button class="button--secondary button--inline" data-ng-click="result.showing_history = false">Hide previous {$ result.result_section $}</button> | ||
1455 | 143 | </p> | ||
1456 | 144 | >>>>>>> src/maasserver/static/partials/script-results-list.html | ||
1457 | 69 | </div> | 145 | </div> |
1458 | 70 | </div> | 146 | </div> |
1459 | 71 | <td class="p-table-expanding__panel col-12" aria-label="history" data-ng-if="result.showing_history"> | 147 | <td class="p-table-expanding__panel col-12" aria-label="history" data-ng-if="result.showing_history"> |
1460 | diff --git a/src/maasserver/tests/test_bootsources.py b/src/maasserver/tests/test_bootsources.py | |||
1461 | index a83c9c1..3629529 100644 | |||
1462 | --- a/src/maasserver/tests/test_bootsources.py | |||
1463 | +++ b/src/maasserver/tests/test_bootsources.py | |||
1464 | @@ -44,7 +44,10 @@ from maasserver.testing.testcase import ( | |||
1465 | 44 | ) | 44 | ) |
1466 | 45 | from maasserver.tests.test_bootresources import SimplestreamsEnvFixture | 45 | from maasserver.tests.test_bootresources import SimplestreamsEnvFixture |
1467 | 46 | from maasserver.utils import get_maas_user_agent | 46 | from maasserver.utils import get_maas_user_agent |
1468 | 47 | <<<<<<< src/maasserver/tests/test_bootsources.py | ||
1469 | 47 | from maastesting.djangotestcase import count_queries | 48 | from maastesting.djangotestcase import count_queries |
1470 | 49 | ======= | ||
1471 | 50 | >>>>>>> src/maasserver/tests/test_bootsources.py | ||
1472 | 48 | from maastesting.matchers import MockCalledOnceWith | 51 | from maastesting.matchers import MockCalledOnceWith |
1473 | 49 | from provisioningserver.config import DEFAULT_IMAGES_URL | 52 | from provisioningserver.config import DEFAULT_IMAGES_URL |
1474 | 50 | from provisioningserver.import_images import ( | 53 | from provisioningserver.import_images import ( |
1475 | diff --git a/src/maasserver/triggers/tests/test_websocket_listener.py b/src/maasserver/triggers/tests/test_websocket_listener.py | |||
1476 | index 6297f0e..5ba464b 100644 | |||
1477 | --- a/src/maasserver/triggers/tests/test_websocket_listener.py | |||
1478 | +++ b/src/maasserver/triggers/tests/test_websocket_listener.py | |||
1479 | @@ -1714,8 +1714,13 @@ class TestIPRangeListener( | |||
1480 | 1714 | self.create_subnet, {'cidr': str(network)}) | 1714 | self.create_subnet, {'cidr': str(network)}) |
1481 | 1715 | params = { | 1715 | params = { |
1482 | 1716 | 'subnet': subnet, | 1716 | 'subnet': subnet, |
1483 | 1717 | <<<<<<< src/maasserver/triggers/tests/test_websocket_listener.py | ||
1484 | 1717 | 'start_ip': IPAddress(network.first + 2), | 1718 | 'start_ip': IPAddress(network.first + 2), |
1485 | 1718 | 'end_ip': IPAddress(network.last - 1)} | 1719 | 'end_ip': IPAddress(network.last - 1)} |
1486 | 1720 | ======= | ||
1487 | 1721 | 'start_ip': str(IPAddress(network.first + 2)), | ||
1488 | 1722 | 'end_ip': str(IPAddress(network.last - 1))} | ||
1489 | 1723 | >>>>>>> src/maasserver/triggers/tests/test_websocket_listener.py | ||
1490 | 1719 | yield listener.startService() | 1724 | yield listener.startService() |
1491 | 1720 | try: | 1725 | try: |
1492 | 1721 | iprange = yield deferToDatabase( | 1726 | iprange = yield deferToDatabase( |
1493 | diff --git a/src/provisioningserver/import_images/boot_resources.py b/src/provisioningserver/import_images/boot_resources.py | |||
1494 | index f985df6..0a5b3c2 100644 | |||
1495 | --- a/src/provisioningserver/import_images/boot_resources.py | |||
1496 | +++ b/src/provisioningserver/import_images/boot_resources.py | |||
1497 | @@ -9,6 +9,7 @@ __all__ = [ | |||
1498 | 9 | ] | 9 | ] |
1499 | 10 | 10 | ||
1500 | 11 | from argparse import ArgumentParser | 11 | from argparse import ArgumentParser |
1501 | 12 | import copy | ||
1502 | 12 | import errno | 13 | import errno |
1503 | 13 | from io import StringIO | 14 | from io import StringIO |
1504 | 14 | import os | 15 | import os |
1505 | @@ -41,6 +42,18 @@ from provisioningserver.utils.fs import ( | |||
1506 | 41 | read_text_file, | 42 | read_text_file, |
1507 | 42 | tempdir, | 43 | tempdir, |
1508 | 43 | ) | 44 | ) |
1509 | 45 | <<<<<<< src/provisioningserver/import_images/boot_resources.py | ||
1510 | 46 | ======= | ||
1511 | 47 | from provisioningserver.utils.service_monitor import ServiceActionError | ||
1512 | 48 | from provisioningserver.utils.shell import ( | ||
1513 | 49 | call_and_check, | ||
1514 | 50 | ExternalProcessError, | ||
1515 | 51 | ) | ||
1516 | 52 | from provisioningserver.utils.snappy import ( | ||
1517 | 53 | get_snap_data_path, | ||
1518 | 54 | running_in_snap, | ||
1519 | 55 | ) | ||
1520 | 56 | >>>>>>> src/provisioningserver/import_images/boot_resources.py | ||
1521 | 44 | from twisted.internet.defer import inlineCallbacks | 57 | from twisted.internet.defer import inlineCallbacks |
1522 | 45 | from twisted.python.filepath import FilePath | 58 | from twisted.python.filepath import FilePath |
1523 | 46 | 59 | ||
1524 | @@ -109,6 +122,54 @@ def write_snapshot_metadata(snapshot, meta_file_content): | |||
1525 | 109 | atomic_write(meta_file_content.encode("ascii"), meta_file, mode=0o644) | 122 | atomic_write(meta_file_content.encode("ascii"), meta_file, mode=0o644) |
1526 | 110 | 123 | ||
1527 | 111 | 124 | ||
1528 | 125 | <<<<<<< src/provisioningserver/import_images/boot_resources.py | ||
1529 | 126 | ======= | ||
1530 | 127 | def write_targets_conf(snapshot): | ||
1531 | 128 | """Write "maas.tgt" file.""" | ||
1532 | 129 | targets_conf = os.path.join(snapshot, 'maas.tgt') | ||
1533 | 130 | targets_conf_content = compose_targets_conf(snapshot) | ||
1534 | 131 | atomic_write(targets_conf_content, targets_conf, mode=0o644) | ||
1535 | 132 | |||
1536 | 133 | |||
1537 | 134 | def update_targets_conf(snapshot): | ||
1538 | 135 | """Runs tgt-admin to update the new targets from "maas.tgt".""" | ||
1539 | 136 | # Ensure that tgt is running before tgt-admin is used. | ||
1540 | 137 | try: | ||
1541 | 138 | service_monitor.ensureService("tgt").wait(30) | ||
1542 | 139 | except ServiceActionError: | ||
1543 | 140 | msg = "Unable to start tgt" | ||
1544 | 141 | try_send_rack_event(EVENT_TYPES.RACK_IMPORT_WARNING, msg) | ||
1545 | 142 | maaslog.warning(msg) | ||
1546 | 143 | return | ||
1547 | 144 | |||
1548 | 145 | # Update the tgt config. | ||
1549 | 146 | targets_conf = os.path.join(snapshot, 'maas.tgt') | ||
1550 | 147 | |||
1551 | 148 | # The targets_conf may not exist in the event the BootSource is broken | ||
1552 | 149 | # and images havn't been imported yet. This fixes LP:1655721 | ||
1553 | 150 | if not os.path.exists(targets_conf): | ||
1554 | 151 | return | ||
1555 | 152 | |||
1556 | 153 | try: | ||
1557 | 154 | env = copy.deepcopy(os.environ) | ||
1558 | 155 | # LP:1718706 - When TGT is run in a snap the socket is stored in the | ||
1559 | 156 | # SNAP_DATA path. Define it before calling tgt-admin otherwise the | ||
1560 | 157 | # standard path is used and the call will fail. | ||
1561 | 158 | if running_in_snap(): | ||
1562 | 159 | env['TGT_IPC_SOCKET'] = os.path.join( | ||
1563 | 160 | get_snap_data_path(), 'tgtd-socket') | ||
1564 | 161 | call_and_check(sudo([ | ||
1565 | 162 | get_path('/usr/sbin/tgt-admin'), | ||
1566 | 163 | '--conf', targets_conf, | ||
1567 | 164 | '--update', 'ALL', | ||
1568 | 165 | ]), env=env) | ||
1569 | 166 | except ExternalProcessError as e: | ||
1570 | 167 | msg = "Unable to update TGT config: %s" % e | ||
1571 | 168 | try_send_rack_event(EVENT_TYPES.RACK_IMPORT_WARNING, msg) | ||
1572 | 169 | maaslog.warning(msg) | ||
1573 | 170 | |||
1574 | 171 | |||
1575 | 172 | >>>>>>> src/provisioningserver/import_images/boot_resources.py | ||
1576 | 112 | def read_sources(sources_yaml): | 173 | def read_sources(sources_yaml): |
1577 | 113 | """Read boot resources config file. | 174 | """Read boot resources config file. |
1578 | 114 | 175 | ||
1579 | diff --git a/src/provisioningserver/import_images/tests/test_boot_resources.py b/src/provisioningserver/import_images/tests/test_boot_resources.py | |||
1580 | index 28635e7..31fa955 100644 | |||
1581 | --- a/src/provisioningserver/import_images/tests/test_boot_resources.py | |||
1582 | +++ b/src/provisioningserver/import_images/tests/test_boot_resources.py | |||
1583 | @@ -43,7 +43,18 @@ from provisioningserver.testing.config import ( | |||
1584 | 43 | BootSourcesFixture, | 43 | BootSourcesFixture, |
1585 | 44 | ClusterConfigurationFixture, | 44 | ClusterConfigurationFixture, |
1586 | 45 | ) | 45 | ) |
1587 | 46 | <<<<<<< src/provisioningserver/import_images/tests/test_boot_resources.py | ||
1588 | 46 | from provisioningserver.utils.fs import write_text_file | 47 | from provisioningserver.utils.fs import write_text_file |
1589 | 48 | ======= | ||
1590 | 49 | from provisioningserver.utils.fs import ( | ||
1591 | 50 | tempdir, | ||
1592 | 51 | write_text_file, | ||
1593 | 52 | ) | ||
1594 | 53 | from provisioningserver.utils.service_monitor import ServiceActionError | ||
1595 | 54 | from provisioningserver.utils.shell import ExternalProcessError | ||
1596 | 55 | from testtools.content import Content | ||
1597 | 56 | from testtools.content_type import UTF8_TEXT | ||
1598 | 57 | >>>>>>> src/provisioningserver/import_images/tests/test_boot_resources.py | ||
1599 | 47 | from testtools.matchers import ( | 58 | from testtools.matchers import ( |
1600 | 48 | DirExists, | 59 | DirExists, |
1601 | 49 | FileExists, | 60 | FileExists, |
1602 | @@ -477,6 +488,87 @@ class TestMain(MAASTestCase): | |||
1603 | 477 | boot_resources.NoConfigFile, | 488 | boot_resources.NoConfigFile, |
1604 | 478 | boot_resources.main, self.make_args(sources="", sources_file="")) | 489 | boot_resources.main, self.make_args(sources="", sources_file="")) |
1605 | 479 | 490 | ||
1606 | 491 | <<<<<<< src/provisioningserver/import_images/tests/test_boot_resources.py | ||
1607 | 492 | ======= | ||
1608 | 493 | def test_update_targets_conf_ensures_tgt_service(self): | ||
1609 | 494 | mock_ensureService = self.patch( | ||
1610 | 495 | boot_resources.service_monitor, "ensureService") | ||
1611 | 496 | self.patch(boot_resources, "call_and_check") | ||
1612 | 497 | boot_resources.update_targets_conf(factory.make_name("snapshot")) | ||
1613 | 498 | self.assertThat(mock_ensureService, MockCalledOnceWith("tgt")) | ||
1614 | 499 | |||
1615 | 500 | def test_update_targets_conf_logs_tgt_service_check_error(self): | ||
1616 | 501 | # Regression test for LP:1735025 | ||
1617 | 502 | mock_ensureService = self.patch( | ||
1618 | 503 | boot_resources.service_monitor, "ensureService") | ||
1619 | 504 | mock_ensureService.side_effect = ServiceActionError() | ||
1620 | 505 | mock_try_send_rack_event = self.patch( | ||
1621 | 506 | boot_resources, 'try_send_rack_event') | ||
1622 | 507 | mock_maaslog = self.patch(boot_resources.maaslog, 'warning') | ||
1623 | 508 | boot_resources.update_targets_conf(factory.make_name("snapshot")) | ||
1624 | 509 | self.assertThat(mock_try_send_rack_event, MockCalledOnce()) | ||
1625 | 510 | self.assertThat(mock_maaslog, MockCalledOnce()) | ||
1626 | 511 | |||
1627 | 512 | def test_update_targets_conf_logs_error(self): | ||
1628 | 513 | self.patch(boot_resources.service_monitor, "ensureService") | ||
1629 | 514 | mock_try_send_rack_event = self.patch( | ||
1630 | 515 | boot_resources, 'try_send_rack_event') | ||
1631 | 516 | mock_maaslog = self.patch(boot_resources.maaslog, 'warning') | ||
1632 | 517 | self.patch(boot_resources.os.path, 'exists').return_value = True | ||
1633 | 518 | self.patch(boot_resources, 'call_and_check').side_effect = ( | ||
1634 | 519 | ExternalProcessError( | ||
1635 | 520 | returncode=2, cmd=('tgt-admin',), output='error')) | ||
1636 | 521 | snapshot = factory.make_name("snapshot") | ||
1637 | 522 | boot_resources.update_targets_conf(snapshot) | ||
1638 | 523 | self.assertThat(mock_try_send_rack_event, MockCalledOnce()) | ||
1639 | 524 | self.assertThat(mock_maaslog, MockCalledOnce()) | ||
1640 | 525 | self.assertThat( | ||
1641 | 526 | boot_resources.call_and_check, | ||
1642 | 527 | MockCalledOnceWith([ | ||
1643 | 528 | 'sudo', '-n', '/usr/sbin/tgt-admin', | ||
1644 | 529 | '--conf', os.path.join(snapshot, 'maas.tgt'), | ||
1645 | 530 | '--update', 'ALL'], env=os.environ)) | ||
1646 | 531 | |||
1647 | 532 | def test_update_targets_only_runs_when_conf_exists(self): | ||
1648 | 533 | # Regression test for LP:1655721 | ||
1649 | 534 | temp_dir = self.useFixture(TempDirectory()).path | ||
1650 | 535 | self.useFixture(ClusterConfigurationFixture(tftp_root=temp_dir)) | ||
1651 | 536 | mock_ensureService = self.patch( | ||
1652 | 537 | boot_resources.service_monitor, "ensureService") | ||
1653 | 538 | mock_call_and_check = self.patch(boot_resources, "call_and_check") | ||
1654 | 539 | mock_path_exists = self.patch(boot_resources.os.path, 'exists') | ||
1655 | 540 | mock_path_exists.return_value = False | ||
1656 | 541 | boot_resources.update_targets_conf(temp_dir) | ||
1657 | 542 | self.assertThat(mock_ensureService, MockCalledOnceWith("tgt")) | ||
1658 | 543 | self.assertThat( | ||
1659 | 544 | mock_path_exists, | ||
1660 | 545 | MockCalledOnceWith(os.path.join(temp_dir, 'maas.tgt'))) | ||
1661 | 546 | self.assertThat(mock_call_and_check, MockNotCalled()) | ||
1662 | 547 | |||
1663 | 548 | def test_update_targets_conf_sets_env_var_in_snap(self): | ||
1664 | 549 | # Regression test for LP:1718706 | ||
1665 | 550 | self.patch(boot_resources.service_monitor, "ensureService") | ||
1666 | 551 | self.patch(boot_resources.os.path, 'exists').return_value = True | ||
1667 | 552 | self.patch(boot_resources, 'call_and_check') | ||
1668 | 553 | self.patch(boot_resources, 'running_in_snap').return_value = True | ||
1669 | 554 | snap_data_path = factory.make_name('snap_data_path') | ||
1670 | 555 | self.patch(boot_resources, 'get_snap_data_path').return_value = ( | ||
1671 | 556 | snap_data_path) | ||
1672 | 557 | snapshot = factory.make_name("snapshot") | ||
1673 | 558 | boot_resources.update_targets_conf(snapshot) | ||
1674 | 559 | self.assertThat( | ||
1675 | 560 | boot_resources.call_and_check, | ||
1676 | 561 | MockCalledOnceWith([ | ||
1677 | 562 | 'sudo', '-n', '/usr/sbin/tgt-admin', | ||
1678 | 563 | '--conf', os.path.join(snapshot, 'maas.tgt'), | ||
1679 | 564 | '--update', 'ALL' | ||
1680 | 565 | ], env={ | ||
1681 | 566 | 'TGT_IPC_SOCKET': os.path.join( | ||
1682 | 567 | snap_data_path, 'tgtd-socket'), | ||
1683 | 568 | **os.environ, | ||
1684 | 569 | })) | ||
1685 | 570 | |||
1686 | 571 | >>>>>>> src/provisioningserver/import_images/tests/test_boot_resources.py | ||
1687 | 480 | 572 | ||
1688 | 481 | class TestMetaContains(MAASTestCase): | 573 | class TestMetaContains(MAASTestCase): |
1689 | 482 | """Tests for the `meta_contains` function.""" | 574 | """Tests for the `meta_contains` function.""" |
1690 | diff --git a/src/provisioningserver/import_images/tests/test_download_resources.py b/src/provisioningserver/import_images/tests/test_download_resources.py | |||
1691 | index 9f40e29..81bc3c1 100644 | |||
1692 | --- a/src/provisioningserver/import_images/tests/test_download_resources.py | |||
1693 | +++ b/src/provisioningserver/import_images/tests/test_download_resources.py | |||
1694 | @@ -359,6 +359,41 @@ class TestRepoWriter(MAASTestCase): | |||
1695 | 359 | label=product['label'], subarches={'ga-16.04', 'generic'}, | 359 | label=product['label'], subarches={'ga-16.04', 'generic'}, |
1696 | 360 | bootloader_type=None)) | 360 | bootloader_type=None)) |
1697 | 361 | 361 | ||
1698 | 362 | <<<<<<< src/provisioningserver/import_images/tests/test_download_resources.py | ||
1699 | 363 | def test_inserts_no_generic_link_for_generic_non_ga_kflavor(self): | ||
1700 | 364 | # Regression test for LP:1749246 | ||
1701 | 365 | ======= | ||
1702 | 366 | def test_inserts_generic_link_for_generic_ga_kflavor(self): | ||
1703 | 367 | >>>>>>> src/provisioningserver/import_images/tests/test_download_resources.py | ||
1704 | 368 | product_mapping = ProductMapping() | ||
1705 | 369 | product = self.make_product(subarch='hwe-16.04', kflavor='generic') | ||
1706 | 370 | product_mapping.add(product, 'hwe-16.04') | ||
1707 | 371 | repo_writer = download_resources.RepoWriter( | ||
1708 | 372 | None, None, product_mapping) | ||
1709 | 373 | self.patch( | ||
1710 | 374 | download_resources, 'products_exdata').return_value = product | ||
1711 | 375 | # Prevent MAAS from trying to actually write the file. | ||
1712 | 376 | mock_insert_file = self.patch(download_resources, 'insert_file') | ||
1713 | 377 | mock_link_resources = self.patch(download_resources, 'link_resources') | ||
1714 | 378 | # We only need to provide the product as the other fields are only used | ||
1715 | 379 | # when writing the actual files to disk. | ||
1716 | 380 | repo_writer.insert_item(product, None, None, None, None) | ||
1717 | 381 | # None is used for the store and the content source as we're not | ||
1718 | 382 | # writing anything to disk. | ||
1719 | 383 | self.assertThat( | ||
1720 | 384 | mock_insert_file, | ||
1721 | 385 | MockCalledOnceWith( | ||
1722 | 386 | None, os.path.basename(product['path']), product['sha256'], | ||
1723 | 387 | {'sha256': product['sha256']}, product['size'], None)) | ||
1724 | 388 | # links are mocked out by the mock_insert_file above. | ||
1725 | 389 | self.assertThat( | ||
1726 | 390 | mock_link_resources, | ||
1727 | 391 | MockCalledOnceWith( | ||
1728 | 392 | snapshot_path=None, links=mock.ANY, osystem=product['os'], | ||
1729 | 393 | arch=product['arch'], release=product['release'], | ||
1730 | 394 | label=product['label'], subarches={'hwe-16.04'}, | ||
1731 | 395 | bootloader_type=None)) | ||
1732 | 396 | |||
1733 | 362 | def test_inserts_no_generic_link_for_generic_non_ga_kflavor(self): | 397 | def test_inserts_no_generic_link_for_generic_non_ga_kflavor(self): |
1734 | 363 | # Regression test for LP:1749246 | 398 | # Regression test for LP:1749246 |
1735 | 364 | product_mapping = ProductMapping() | 399 | product_mapping = ProductMapping() |
1736 | diff --git a/src/provisioningserver/utils/tests/test_network.py b/src/provisioningserver/utils/tests/test_network.py | |||
1737 | index bda51e1..3b3c6b0 100644 | |||
1738 | --- a/src/provisioningserver/utils/tests/test_network.py | |||
1739 | +++ b/src/provisioningserver/utils/tests/test_network.py | |||
1740 | @@ -83,7 +83,10 @@ from provisioningserver.utils.network import ( | |||
1741 | 83 | resolves_to_loopback_address, | 83 | resolves_to_loopback_address, |
1742 | 84 | reverseResolve, | 84 | reverseResolve, |
1743 | 85 | ) | 85 | ) |
1744 | 86 | <<<<<<< src/provisioningserver/utils/tests/test_network.py | ||
1745 | 86 | from provisioningserver.utils.shell import get_env_with_locale | 87 | from provisioningserver.utils.shell import get_env_with_locale |
1746 | 88 | ======= | ||
1747 | 89 | >>>>>>> src/provisioningserver/utils/tests/test_network.py | ||
1748 | 87 | from testtools import ExpectedException | 90 | from testtools import ExpectedException |
1749 | 88 | from testtools.matchers import ( | 91 | from testtools.matchers import ( |
1750 | 89 | Contains, | 92 | Contains, |
1751 | diff --git a/utilities/release-build b/utilities/release-build | |||
1752 | index 3c0a5af..49f32cc 100755 | |||
1753 | --- a/utilities/release-build | |||
1754 | +++ b/utilities/release-build | |||
1755 | @@ -15,7 +15,7 @@ usage () { | |||
1756 | 15 | exit 1 | 15 | exit 1 |
1757 | 16 | } | 16 | } |
1758 | 17 | 17 | ||
1760 | 18 | DEFAULT_DISTROS="$(ubuntu-distro-info --supported | grep -v trusty)" | 18 | DEFAULT_DISTROS="$(ubuntu-distro-info --supported | grep -v trusty | grep -v bionic)" |
1761 | 19 | PACKAGE_DISTROS="" | 19 | PACKAGE_DISTROS="" |
1762 | 20 | KEEP_CHANGELOG=0 | 20 | KEEP_CHANGELOG=0 |
1763 | 21 | 21 | ||
1764 | @@ -61,7 +61,7 @@ dch -a "" --release-heuristic log --nomultimaint | |||
1765 | 61 | PKG=$(head -n1 debian/changelog | awk '{print $1}') | 61 | PKG=$(head -n1 debian/changelog | awk '{print $1}') |
1766 | 62 | MAJOR_VER=$(head -n 1 debian/changelog | sed 's/^.*(//' | sed 's/).*//' | sed 's/-.*//') | 62 | MAJOR_VER=$(head -n 1 debian/changelog | sed 's/^.*(//' | sed 's/).*//' | sed 's/-.*//') |
1767 | 63 | REV_COUNT=$(git rev-list --count $COMMIT) | 63 | REV_COUNT=$(git rev-list --count $COMMIT) |
1769 | 64 | REV_SHORT=$(git rev-parse --short $COMMIT) | 64 | REV_SHORT=$(git rev-parse --short=7 $COMMIT) |
1770 | 65 | FULL_VER="$MAJOR_VER-$REV_COUNT-g$REV_SHORT" | 65 | FULL_VER="$MAJOR_VER-$REV_COUNT-g$REV_SHORT" |
1771 | 66 | TARBALL="maas_$FULL_VER.orig.tar.gz" | 66 | TARBALL="maas_$FULL_VER.orig.tar.gz" |
1772 | 67 | 67 | ||
1773 | @@ -89,3 +89,12 @@ if echo "$PACKAGE_DISTROS" | grep -q "bionic"; then | |||
1774 | 89 | sed -i "s/) UNRELEASED;/~18.04.1) bionic;/i" debian/changelog | 89 | sed -i "s/) UNRELEASED;/~18.04.1) bionic;/i" debian/changelog |
1775 | 90 | debuild -S -sa | 90 | debuild -S -sa |
1776 | 91 | fi | 91 | fi |
1777 | 92 | <<<<<<< utilities/release-build | ||
1778 | 93 | ======= | ||
1779 | 94 | |||
1780 | 95 | if echo "$PACKAGE_DISTROS" | grep -q "artful"; then | ||
1781 | 96 | cp $ROOTDIR/debian/changelog debian/changelog | ||
1782 | 97 | sed -i "s/) UNRELEASED;/~17.10.1) artful;/" debian/changelog | ||
1783 | 98 | debuild -S | ||
1784 | 99 | fi | ||
1785 | 100 | >>>>>>> utilities/release-build |