Merge lp:~ricgard/maas/vlan-not-loading-on-rack-details--fix-bug-1621285 into lp:~maas-committers/maas/trunk
- vlan-not-loading-on-rack-details--fix-bug-1621285
- Merge into trunk
Proposed by
Richard McCartney
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Andres Rodriguez | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 5335 | ||||
Proposed branch: | lp:~ricgard/maas/vlan-not-loading-on-rack-details--fix-bug-1621285 | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Diff against target: |
1245 lines (+612/-610) 1 file modified
src/maasserver/static/partials/node-details.html (+612/-610) |
||||
To merge this branch: | bzr merge lp:~ricgard/maas/vlan-not-loading-on-rack-details--fix-bug-1621285 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Approve | ||
Review via email: mp+305199@code.launchpad.net |
Commit message
Resolves issue on the rack details page to show Served VLAN's content.
Description of the change
Resolves issue on the rack details page to show Served VLAN's content. Amended the node-details.html markup to load the controller correctly.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/maasserver/static/partials/node-details.html' |
2 | --- src/maasserver/static/partials/node-details.html 2016-09-07 15:19:31 +0000 |
3 | +++ src/maasserver/static/partials/node-details.html 2016-09-08 11:12:45 +0000 |
4 | @@ -466,629 +466,631 @@ |
5 | </div> |
6 | </div> |
7 | </div> |
8 | - <div class="row" ng-controller="NodeNetworkingController" data-ng-show="isController"> |
9 | - <div class="wrapper--inner"> |
10 | - <div class="twelve-col" data-ng-hide="loaded"> |
11 | - <h2>Served VLANs</h2> |
12 | - <p class="u-text--loading"><i class="icon icon--loading u-animation--spin"></i> Loading...</p> |
13 | - </div> |
14 | - <div class="twelve-col" data-ng-show="loaded"> |
15 | - <h2>Served VLANs</h2> |
16 | - </div> |
17 | - <div class="twelve-col"> |
18 | + <div ng-controller="NodeNetworkingController"> |
19 | + <div class="row u-border--top" data-ng-show="isController"> |
20 | + <div class="wrapper--inner"> |
21 | + <div class="twelve-col" data-ng-hide="loaded"> |
22 | + <h2>Served VLANs</h2> |
23 | + <p class="u-text--loading"><i class="icon icon--loading u-animation--spin"></i> Loading...</p> |
24 | + </div> |
25 | + <div class="twelve-col" data-ng-show="loaded"> |
26 | + <h2>Served VLANs</h2> |
27 | + </div> |
28 | + <div class="twelve-col"> |
29 | + <form class="ng-hide" data-ng-show="loaded"> |
30 | + <div class="table"> |
31 | + <header class="table__head"> |
32 | + <div class="table__row"> |
33 | + <div class="table__header table-col--15">Fabric</div> |
34 | + <div class="table__header table-col--15">VLAN</div> |
35 | + <div class="table__header table-col--30">Subnets</div> |
36 | + <div class="table__header table-col--20">Primary rack</div> |
37 | + <div class="table__header table-col--20">Secondary rack</div> |
38 | + </div> |
39 | + </header> |
40 | + <main class="table__body"> |
41 | + <div class="table__row" data-ng-repeat="vlanRow in vlanTable"> |
42 | + <div class="table__data table-col--15"> |
43 | + <a href="#/fabric/{$ vlanRow['fabric'].id $}">{$ vlanRow['fabric'].name $}</a> |
44 | + </div> |
45 | + <div class="table__data table-col--15"> |
46 | + <a href="#/vlan/{$ vlanRow['vlan'].id $}">{$ getVLANText(vlanRow['vlan']) $}</a> |
47 | + </div> |
48 | + <div class="table__data table-col--30"> |
49 | + <span data-ng-repeat="subnet in vlanRow['subnets']"> |
50 | + <div class="u-margin--bottom-small"> |
51 | + <a href="#/subnet/{$ subnet.id $}">{$ getSubnetText(subnet) $}</a> |
52 | + </div> |
53 | + </span> |
54 | + </div> |
55 | + <div class="table__data table-col--20"> |
56 | + <a href="#/node/controller/{$ vlanRow['primary_rack'].system_id $}">{$ vlanRow['primary_rack'].fqdn $}</a> |
57 | + </div> |
58 | + <div class="table__data table-col--20"> |
59 | + <a href="#/node/controller/{$ vlanRow['secondary_rack'].system_id $}">{$ vlanRow['secondary_rack'].fqdn $}</a> |
60 | + </div> |
61 | + </div> |
62 | + </main> |
63 | + </div> |
64 | + </form> |
65 | + </div> |
66 | + </div> |
67 | + </div> |
68 | + <div class="row"> |
69 | + <div class="wrapper--inner"> |
70 | + <div class="twelve-col" data-ng-hide="loaded"> |
71 | + <h2>Interfaces</h2> |
72 | + <p><i class="icon icon--loading u-animation--spin"></i>Loading...</p> |
73 | + </div> |
74 | <form class="ng-hide" data-ng-show="loaded"> |
75 | - <div class="table"> |
76 | + <div class="twelve-col"> |
77 | + <h2 class="title">Interfaces</h2> |
78 | + </div> |
79 | + <div class="twelve-col"> |
80 | + <ul class="flash-messages" data-ng-if=" |
81 | + (!isController && isAllNetworkingDisabled() && isSuperUser()) || |
82 | + !node.on_network || (!isController && !isUbuntuOS())"> |
83 | + <li class="flash-messages__item flash-messages__item--error" data-ng-if="!node.on_network"> |
84 | + Node must be connected to a network. |
85 | + </li> |
86 | + <li class="flash-messages__item flash-messages__item--info" data-ng-if="!isController && isAllNetworkingDisabled() && isSuperUser()"> |
87 | + Interface configuration cannot be modified unless the node is Ready or Broken. |
88 | + </li> |
89 | + <li class="flash-messages__item flash-messages__item--info" data-ng-if="!isController && !isUbuntuOS()"> |
90 | + Custom network configuration only supported on Ubuntu. Using OS default configuration. |
91 | + </li> |
92 | + </ul> |
93 | + </div> |
94 | + <div class="table table--hover u-margin--bottom"> |
95 | <header class="table__head"> |
96 | <div class="table__row"> |
97 | - <div class="table__header table-col--15">Fabric</div> |
98 | - <div class="table__header table-col--15">VLAN</div> |
99 | - <div class="table__header table-col--30">Subnets</div> |
100 | - <div class="table__header table-col--20">Primary rack</div> |
101 | - <div class="table__header table-col--20">Secondary rack</div> |
102 | + <div class="table__header table-col--3"></div> |
103 | + <div class="table__header table-col--12"> |
104 | + <a class="table__header-link is-active" |
105 | + data-ng-class="{ 'is-active': column == 'name' }" |
106 | + data-ng-click="column = 'name'"> |
107 | + Name |
108 | + </a> |
109 | + <span class="divide"></span> |
110 | + <a class="table__header-link" data-ng-class="{ 'is-active': column == 'mac' }" |
111 | + data-ng-click="column = 'mac'"> |
112 | + MAC |
113 | + </a> |
114 | + </div> |
115 | + <div class="table__header table-col--3"><span data-ng-if="!isController">PXE</span></div> |
116 | + <div class="table__header table-col--9">Type</div> |
117 | + <div class="table__header table-col--14">Fabric</div> |
118 | + <div class="table__header table-col--14">VLAN</div> |
119 | + <div class="table__header table-col--18">Subnet</div> |
120 | + <div class="table__header table-col--27">IP Address</div> |
121 | </div> |
122 | </header> |
123 | - <main class="table__body"> |
124 | - <div class="table__row" data-ng-repeat="vlanRow in vlanTable"> |
125 | - <div class="table__data table-col--15"> |
126 | - <a href="#/fabric/{$ vlanRow['fabric'].id $}">{$ vlanRow['fabric'].name $}</a> |
127 | - </div> |
128 | - <div class="table__data table-col--15"> |
129 | - <a href="#/vlan/{$ vlanRow['vlan'].id $}">{$ getVLANText(vlanRow['vlan']) $}</a> |
130 | - </div> |
131 | - <div class="table__data table-col--30"> |
132 | - <span data-ng-repeat="subnet in vlanRow['subnets']"> |
133 | - <div class="u-margin--bottom-small"> |
134 | - <a href="#/subnet/{$ subnet.id $}">{$ getSubnetText(subnet) $}</a> |
135 | - </div> |
136 | - </span> |
137 | - </div> |
138 | - <div class="table__data table-col--20"> |
139 | - <a href="#/node/controller/{$ vlanRow['primary_rack'].system_id $}">{$ vlanRow['primary_rack'].fqdn $}</a> |
140 | - </div> |
141 | - <div class="table__data table-col--20"> |
142 | - <a href="#/node/controller/{$ vlanRow['secondary_rack'].system_id $}">{$ vlanRow['secondary_rack'].fqdn $}</a> |
143 | + <main class="table__body" data-selected-rows> |
144 | + <div class="table__row" |
145 | + data-ng-class="{ disabled: isDisabled(), 'is-active': isInterfaceSelected(interface) && isNodeEditingAllowed(), noEdit: cannotEditInterface(interface) }" |
146 | + data-ng-repeat="interface in interfaces | removeInterfaceParents:newBondInterface:!isNodeEditingAllowed() | removeInterfaceParents:newBridgeInterface:!isNodeEditingAllowed()"> |
147 | + <div class="table__data table-col--3"> |
148 | + <input type="checkbox" class="checkbox" id="{$ getUniqueKey(interface) $}" |
149 | + data-ng-hide="isAllNetworkingDisabled()" |
150 | + data-ng-checked="isInterfaceSelected(interface)" |
151 | + data-ng-click="toggleInterfaceSelect(interface)" |
152 | + data-ng-disabled="isDisabled()" |
153 | + data-ng-if="!isController && isNodeEditingAllowed()"> |
154 | + <label for="{$ getUniqueKey(interface) $}"></label> |
155 | + </div> |
156 | + <div class="table__data table-col--12" data-ng-show="column == 'name'"> |
157 | + <span data-ng-if="!isEditing(interface)">{$ interface.name $}</span> |
158 | + <input type="text" class="table__input" |
159 | + data-ng-if="isEditing(interface)" |
160 | + data-ng-model="editInterface.name" |
161 | + data-ng-class="{ 'has-error': isInterfaceNameInvalid(editInterface) }"> |
162 | + </div> |
163 | + <div class="table__data table-col--12 ng-hide" data-ng-show="column == 'mac'"> |
164 | + {$ interface.mac_address $} |
165 | + </div> |
166 | + <div class="table__data table-col--3 u-align--center"> |
167 | + <input type="radio" name="bootInterface" id="{$ interface.name $}" checked |
168 | + data-ng-if="!isController && isBootInterface(interface)"> |
169 | + <label for="{$ interface.name $}"></label> |
170 | + </div> |
171 | + <div class="table__data table-col--9"> |
172 | + <span data-ng-if="!isEditing(interface)">{$ getInterfaceTypeText(interface) $}</span> |
173 | + </div> |
174 | + <div class="table__data table-col--14"> |
175 | + <span data-ng-if="!isEditing(interface)">{$ interface.fabric.name $}</span> |
176 | + </div> |
177 | + <div class="table__data table-col--14"> |
178 | + <span data-ng-if="!isEditing(interface)">{$ getVLANText(interface.vlan) $}</span> |
179 | + </div> |
180 | + <div class="table__data table-col--18"> |
181 | + <span data-ng-if="!isEditing(interface)">{$ getSubnetText(interface.subnet) $}</span> |
182 | + <span data-ng-if="isAllNetworkingDisabled() && interface.discovered[0].subnet_id"> |
183 | + {$ getSubnetText(getSubnet(interface.discovered[0].subnet_id)) $} |
184 | + </span> |
185 | + </div> |
186 | + <div class="table__data table-col--19"> |
187 | + <span data-ng-if="!isEditing(interface) && !interface.discovered[0].ip_address"> |
188 | + {$ interface.ip_address $} ({$ getLinkModeText(interface) $}) |
189 | + </span> |
190 | + <span data-ng-if="!isEditing(interface) && interface.discovered[0].ip_address"> |
191 | + {$ interface.discovered[0].ip_address $} (DHCP) |
192 | + </span> |
193 | + </div> |
194 | + <div class="table__data table-col--8"> |
195 | + <div class="table__controls u-align--right" data-ng-if="isNodeEditingAllowed()"> |
196 | + <a class="icon icon--add tooltip" |
197 | + aria-label="Add Alias or VLAN" |
198 | + data-ng-if="!isController && (canAddAlias(interface) || canAddVLAN(interface))" |
199 | + data-ng-click="quickAdd(interface)"></a> |
200 | + <a class="icon icon--edit tooltip" |
201 | + data-ng-if="!cannotEditInterface(interface)" |
202 | + aria-label="Edit" |
203 | + data-ng-click="edit(interface)"></a> |
204 | + <a class="icon icon--delete tooltip u-margin--left" |
205 | + data-ng-if="!isController" |
206 | + aria-label="Remove" |
207 | + data-ng-click="quickRemove(interface)"></a> |
208 | + </div> |
209 | + </div> |
210 | + <div class="table__dropdown table__dropdown--info"> |
211 | + <div class="table__row" data-ng-class="{ 'is-active': isShowingMembers(interface) }" data-ng-repeat="member in interface.members"> |
212 | + <div data-ng-show="isShowingMembers(interface)"> |
213 | + <div class="table__data u-padding--top-none table-col--3"></div> |
214 | + <div class="table__data u-padding--top-none table-col--15" |
215 | + data-ng-show="column == 'name'">{$ member.name $}</div> |
216 | + <div class="table__data u-padding--top-none table-col--15 ng-hide" |
217 | + data-ng-show="column == 'mac'">{$ member.mac_address $}</div> |
218 | + <div class="table__data u-padding--top-none table-col--15">{$ getInterfaceTypeText(member) $}</div> |
219 | + <div class="table__data u-padding--top-none table-col--67"> |
220 | + </div> |
221 | + </div> |
222 | + </div> |
223 | + </div> |
224 | + <div data-ng-show="isNodeEditingAllowed()"> |
225 | + <div class="table__dropdown"> |
226 | + <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing" data-ng-class="{ 'is-active': isEditing(interface) || isShowingAdd() }"> |
227 | + <div data-ng-if="isShowingAdd()" class="table__row--indent"> |
228 | + <div class="form__fieldset six-col"> |
229 | + <dl> |
230 | + <dt class="two-col">Name</dt> |
231 | + <dd class="four-col last-col">{$ getAddName() $}</dd> |
232 | + </dl> |
233 | + <div class="form__group"> |
234 | + <label for="type" class="two-col">Type</label> |
235 | + <select name="type" class="three-col" |
236 | + data-ng-model="newInterface.type" |
237 | + data-ng-change="addTypeChanged()"> |
238 | + <option value="alias" data-ng-show="canAddAlias(newInterface.parent)">Alias</option> |
239 | + <option value="vlan" data-ng-show="canAddVLAN(newInterface.parent)">VLAN</option> |
240 | + </select> |
241 | + </div> |
242 | + <div class="form__group" data-ng-if="newInterface.type === 'vlan'"> |
243 | + <label class="two-col">Tags</label> |
244 | + <div class="form__group-input three-col last-col"> |
245 | + <tags-input ng-model="newInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
246 | + </div> |
247 | + </div> |
248 | + </div> |
249 | + <div class="form__fieldset six-col last-col"> |
250 | + <div class="form__group"> |
251 | + <label for="fabric" class="two-col">Fabric</label> |
252 | + <select name="fabric" class="three-col" |
253 | + data-ng-model="newInterface.parent.fabric" |
254 | + data-ng-options="fabric as fabric.name for fabric in fabrics" |
255 | + disabled="disabled"> |
256 | + </select> |
257 | + </div> |
258 | + <div class="form__group" data-ng-if="newInterface.type === 'alias'"> |
259 | + <label for="vlan" class="two-col">VLAN</label> |
260 | + <select name="vlan" class="three-col" |
261 | + data-ng-model="newInterface.vlan" |
262 | + data-ng-options="vlan as getVLANText(vlan) for vlan in vlans" |
263 | + disabled="disabled"> |
264 | + </select> |
265 | + </div> |
266 | + <div class="form__group" data-ng-if="newInterface.type === 'vlan'"> |
267 | + <label for="vlan" class="two-col">VLAN</label> |
268 | + <select name="vlan" class="three-col" |
269 | + data-ng-model="newInterface.vlan" |
270 | + data-ng-change="vlanChanged(newInterface)" |
271 | + data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | removeDefaultVLAN | filterByFabric:newInterface.parent.fabric | filterByUnusedForInterface:newInterface.parent:originalInterfaces"> |
272 | + </select> |
273 | + </div> |
274 | + <div class="form__group"> |
275 | + <label for="subnet" class="two-col">Subnet</label> |
276 | + <select name="subnet" class="three-col" |
277 | + ng-model="newInterface.subnet" |
278 | + data-ng-change="subnetChanged(newInterface)" |
279 | + data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:newInterface.vlan"> |
280 | + <option value="" data-ng-hide="newInterface.type === 'alias'">Unconfigured</option> |
281 | + </select> |
282 | + </div> |
283 | + <div class="form__group" data-ng-if="!isLinkModeDisabled(newInterface)"> |
284 | + <label for="link-mode" class="two-col">IP mode</label> |
285 | + <select name="link-mode" class="three-col" |
286 | + data-ng-model="newInterface.mode" |
287 | + data-ng-change="modeChanged(newInterface)" |
288 | + data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:newInterface"> |
289 | + </select> |
290 | + </div> |
291 | + <div class="form__group" data-ng-if="newInterface.mode == 'static'"> |
292 | + <label for="ip-address" class="two-col">IP address</label> |
293 | + <input name="ip-address" type="text" class="three-col" |
294 | + placeholder="IP address (optional)" |
295 | + ng-model="newInterface.ip_address" |
296 | + data-ng-class="{ 'has-error': isIPAddressInvalid(newInterface) }"> |
297 | + </div> |
298 | + </div> |
299 | + </div> |
300 | + <div data-ng-if="isEditing(interface)" class="table__row--indent"> |
301 | + <div class="form__fieldset six-col"> |
302 | + <dl> |
303 | + <dt class="two-col">Type</dt> |
304 | + <dd class="four-col last-col">{$ getInterfaceTypeText(interface) $}</dd> |
305 | + </dl> |
306 | + <div class="form__group" data-ng-if="interface.type != 'alias' && interface.type != 'vlan'"> |
307 | + <label for="mac" class="two-col">MAC address</label> |
308 | + <input name="mac" type="text" class="three-col" |
309 | + placeholder="00:00:00:00:00:00" |
310 | + data-ng-model="editInterface.mac_address" |
311 | + data-ng-class="{ 'has-error': isMACAddressInvalid(editInterface.mac_address, true) }"> |
312 | + </div> |
313 | + <div class="form__group"> |
314 | + <label class="two-col" data-ng-if="interface.type != 'alias'">Tags</label> |
315 | + <div class="form__group-input three-col last-col" data-ng-if="interface.type != 'alias'"> |
316 | + <tags-input ng-model="editInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
317 | + </div> |
318 | + </div> |
319 | + </div> |
320 | + <div class="form__fieldset six-col last-col"> |
321 | + <div class="form__group"> |
322 | + <label for="fabric" class="two-col">Fabric</label> |
323 | + <select name="fabric" class="three-col" |
324 | + data-ng-model="editInterface.fabric" |
325 | + data-ng-change="fabricChanged(editInterface)" |
326 | + data-ng-disabled="interface.type === 'vlan'" |
327 | + data-ng-options="fabric as fabric.name for fabric in fabrics"> |
328 | + <option value="">Disconnected</option> |
329 | + </select> |
330 | + </div> |
331 | + <div class="form__group" data-ng-if="editInterface.fabric"> |
332 | + <label for="vlan" class="two-col">VLAN</label> |
333 | + <select name="vlan" class="three-col" |
334 | + ng-model="editInterface.vlan" |
335 | + data-ng-disabled="interface.type === 'physical' || interface.type === 'bond'" |
336 | + data-ng-change="vlanChanged(editInterface)" |
337 | + data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | removeDefaultVLANIfVLAN:interface.type | filterByFabric:editInterface.fabric"> |
338 | + </select> |
339 | + </div> |
340 | + <div class="form__group" data-ng-if="editInterface.fabric"> |
341 | + <label for="subnet" class="two-col">Subnet</label> |
342 | + <select name="subnet" class="three-col" |
343 | + ng-model="editInterface.subnet" |
344 | + data-ng-change="subnetChanged(newInterface)" |
345 | + data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:editInterface.vlan"> |
346 | + <option value="" data-ng-hide="interface.links.length > 1">Unconfigured</option> |
347 | + </select> |
348 | + </div> |
349 | + <div class="form__group" data-ng-if="editInterface.fabric && !isLinkModeDisabled(editInterface)"> |
350 | + <label for="link-mode" class="two-col">IP mode</label> |
351 | + <select name="link-mode" class="three-col" |
352 | + ng-model="editInterface.mode" |
353 | + data-ng-change="modeChanged(editInterface)" |
354 | + data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:editInterface"> |
355 | + </select> |
356 | + </div> |
357 | + <div class="form__group" data-ng-if="editInterface.fabric && editInterface.mode == 'static'"> |
358 | + <label for="ip-address" class="two-col">IP address</label> |
359 | + <div class="form__group-input three-col last-col"> |
360 | + <input name="ip-address" type="text" |
361 | + placeholder="IP address (optional)" |
362 | + ng-model="editInterface.ip_address" |
363 | + data-ng-class="{ 'has-error': isIPAddressInvalid(editInterface) }"> |
364 | + <ul class="errors u-margin--bottom-none form__group--errors" data-ng-if="getInterfaceError(editInterface)"> |
365 | + <li>{$ getInterfaceError(editInterface) $}</li> |
366 | + </ul> |
367 | + </div> |
368 | + </div> |
369 | + </div> |
370 | + </div> |
371 | + </div> |
372 | + <div class="table__row u-padding--right-small u-padding--left-small box-sizing is-active" data-ng-if="isShowingDeleteConfirm()"> |
373 | + <div class="table__data u-float--left"> |
374 | + <p><span class="icon icon--warning u-margin--right-small"></span> Are you sure you want to remove this {$ getRemoveTypeText(interface) $}?</p> |
375 | + </div> |
376 | + <div class="table__data u-float--right"> |
377 | + <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
378 | + <button class="button--primary button--inline" data-ng-click="confirmRemove(interface)">Remove</button> |
379 | + </div> |
380 | + </div> |
381 | + <div class="table__row is-active" data-ng-if="isEditing(interface)"> |
382 | + <div class="table__data u-float--right"> |
383 | + <a class="button--base button--inline" data-ng-click="editCancel()">Cancel</a> |
384 | + <button class="button--primary button--inline" data-ng-disabled="isInterfaceNameInvalid(editInterface) || isIPAddressInvalid(editInterface) || isMACAddressInvalid(editInterface.mac_address, true)" data-ng-click="editSave()">Save</button> |
385 | + </div> |
386 | + </div> |
387 | + <div class="table__row is-active" data-ng-if="isShowingAdd() && !newInterface.saving"> |
388 | + <div class="table__data u-float--left"> |
389 | + <button class="button--secondary button--inline" |
390 | + data-ng-click="addInterface('alias')" |
391 | + data-ng-show="canAddAlias(interface)">Add <span data-ng-show="newInterface.type === 'alias'">another </span>alias</button> |
392 | + <button class="button--secondary button--inline" |
393 | + data-ng-click="addInterface('vlan')" |
394 | + data-ng-show="canAddAnotherVLAN(interface)">Add <span data-ng-show="newInterface.type === 'vlan'">another </span>VLAN</button> |
395 | + </div> |
396 | + <div class="table__data u-float--right"> |
397 | + <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
398 | + <button class="button--primary button--inline" data-ng-click="addInterface()">Add</button> |
399 | + </div> |
400 | + </div> |
401 | + </div> |
402 | + </div> |
403 | + </div> |
404 | + <div class="table__row is-active" data-ng-if="isShowingCreateBond() && isNodeEditingAllowed()"> |
405 | + <div class="table__data table-col--3"> |
406 | + <input type="checkbox" class="checkbox" name="bond-create" disabled="disabled" checked /> |
407 | + <label for="bond-create"></label> |
408 | + </div> |
409 | + <div class="table__data table-col--12"> |
410 | + <input type="text" name="name" class="table__input editible" |
411 | + data-ng-class="{ 'has-error': isInterfaceNameInvalid(newBondInterface) }" |
412 | + data-ng-model="newBondInterface.name"> |
413 | + </div> |
414 | + <div class="table__data table-col--3 u-align--center"> |
415 | + <input type="radio" name="bondBootInterface" checked id="{$ newBondInterface $}" |
416 | + data-ng-if="hasBootInterface(newBondInterface)"> |
417 | + <label for="{$ newBondInterface $}"></label> |
418 | + </div> |
419 | + <div class="table__data table-col--82"></div> |
420 | + <div class="table__dropdown"> |
421 | + <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing is-active"> |
422 | + <div class="table__row--indent"> |
423 | + <div class="form__fieldset six-col"> |
424 | + <div class="form__group"> |
425 | + <label for="bond-mode" class="two-col">Bond mode</label> |
426 | + <select name="bond-mode" class="three-col" |
427 | + data-ng-model="newBondInterface.mode" |
428 | + data-ng-options="mode[0] as mode[1] for mode in bondOptions.modes"> |
429 | + </select> |
430 | + </div> |
431 | + <div class="form__group"> |
432 | + <label for="mac" class="two-col">MAC address</label> |
433 | + <input type="text" name="mac" class="three-col" |
434 | + data-ng-model="newBondInterface.macAddress" |
435 | + data-ng-class="{ 'has-error': isMACAddressInvalid(newBondInterface.macAddress) }" |
436 | + data-ng-placeholder="getInterfacePlaceholderMACAddress(newBondInterface)"> |
437 | + </div> |
438 | + <div class="form__group"> |
439 | + <label class="two-col">Tags</label> |
440 | + <div class="form__Group-input three-col last-col"> |
441 | + <tags-input ng-model="newBondInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
442 | + </div> |
443 | + </div> |
444 | + </div> |
445 | + <div class="form__fieldset six-col last-col"> |
446 | + <div class="form__group" data-ng-if="showLACPRate()"> |
447 | + <label for="lacp-rate" class="two-col">LACP rate</label> |
448 | + <select name="lacp-rate" class="three-col" |
449 | + data-ng-model="newBondInterface.lacpRate" |
450 | + data-ng-options="rate[0] as rate[1] for rate in bondOptions.lacp_rates"> |
451 | + </select> |
452 | + </div> |
453 | + <div class="form__group" data-ng-if="showXMITHashPolicy()"> |
454 | + <label for="xmit-hash-policy" class="two-col">XMIT hash policy</label> |
455 | + <select name="xmit-hash-policy" class="three-col" |
456 | + data-ng-model="newBondInterface.xmitHashPolicy" |
457 | + data-ng-options="xmit[0] as xmit[1] for xmit in bondOptions.xmit_hash_policies"> |
458 | + </select> |
459 | + </div> |
460 | + </div> |
461 | + </div> |
462 | + </div> |
463 | + <div class="table__row--indent"> |
464 | + <div class="table__row table__row--head is-active"> |
465 | + <div class="table__header table-col--3"></div> |
466 | + <div class="table__header table-col--15">Name</div> |
467 | + <div class="table__header table-col--15">Type</div> |
468 | + <div class="table__header table-col--67">Primary</div> |
469 | + </div> |
470 | + <div class="table__row u-border--none is-active" |
471 | + data-ng-repeat="parent in newBondInterface.parents | orderBy:'name'"> |
472 | + <div class="table__data u-padding--top-none table-col--3"></div> |
473 | + <div class="table__data u-padding--top-none table-col--15">{$ parent.name $}</div> |
474 | + <div class="table__data u-padding--top-none table-col--15">{$ getInterfaceTypeText(parent) $}</div> |
475 | + <div class="table__data u-padding--top-none table-col--67"> |
476 | + <input type="radio" name="bondPrimary" id="{$ parent.name $}" data-ng-model="newBondInterface.primary" data-ng-value="parent"> |
477 | + <label for="{$ parent.name $}"></label> |
478 | + </div> |
479 | + </div> |
480 | + </div> |
481 | + <div class="table__row is-active"> |
482 | + <div class="table__data u-float--right"> |
483 | + <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
484 | + <button class="button--primary button--inline" |
485 | + data-ng-click="addBond()" |
486 | + data-ng-disabled="cannotAddBond()">Save</button> |
487 | + </div> |
488 | + </div> |
489 | + </div> |
490 | + </div> |
491 | + <div class="table__row is-active" data-ng-if="isShowingCreateBridge() && isNodeEditingAllowed()"> |
492 | + <div class="table__data table-col--3"> |
493 | + <input type="checkbox" class="checkbox" id="bond-create" disabled="disabled" checked /> |
494 | + <label for="bridge-create"></label> |
495 | + </div> |
496 | + <div class="table__data table-col--12"> |
497 | + <input type="text" class="table__input editible" |
498 | + data-ng-class="{ 'has-error': isInterfaceNameInvalid(newBridgeInterface) }" |
499 | + data-ng-model="newBridgeInterface.name"> |
500 | + </div> |
501 | + <div class="table__data table-col--3"> |
502 | + <input class="align-center" type="radio" id="{$ newBridgeInterface $}" name="bridgeBootInterface" checked |
503 | + data-ng-if="hasBootInterface(newBridgeInterface)"> |
504 | + <label for="{$ newBridgeInterface $}"></label> |
505 | + </div> |
506 | + <div class="table__data table-col--82"></div> |
507 | + <div class="table__dropdown"> |
508 | + <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing is-active"> |
509 | + <div class="table__row--indent"> |
510 | + <div class="form__fieldset six-col"> |
511 | + <dl> |
512 | + <dt class="two-col">Primary</dt> |
513 | + <dd class="four-col last-col">{$ newBridgeInterface.primary.name $}</dd> |
514 | + </dl> |
515 | + <div class="form__group"> |
516 | + <label for="mac" class="two-col">MAC address</label> |
517 | + <input type="text" name="mac" class="three-col" |
518 | + data-ng-model="newBridgeInterface.macAddress" |
519 | + data-ng-class="{ 'has-error': isMACAddressInvalid(newBridgeInterface.macAddress) }" |
520 | + data-ng-placeholder="getInterfacePlaceholderMACAddress(newBridgeInterface)"> |
521 | + </div> |
522 | + <div class="form__group"> |
523 | + <label class="two-col">Tags</label> |
524 | + <div class="form__group-input three-col last-col"> |
525 | + <tags-input ng-model="newBridgeInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
526 | + </div> |
527 | + </div> |
528 | + </div> |
529 | + <div class="form__fieldset six-col last-col"> |
530 | + <div class="form__group"> |
531 | + <label for="stp" class="two-col form__group-label">STP</label> |
532 | + <div class="form__group-input three-col"> |
533 | + <div class="onoffswitch"> |
534 | + <input input id="bridge_stp" type="checkbox" name="bridge_stp" class="onoffswitch-checkbox" |
535 | + data-ng-model="newBridgeInterface.bridge_stp"> |
536 | + <label class="onoffswitch-label" for="bridge_stp"> |
537 | + <span class="onoffswitch-inner"></span> |
538 | + <span class="onoffswitch-switch"></span> |
539 | + </label> |
540 | + </div> |
541 | + </div> |
542 | + </div> |
543 | + <div class="form__group" data-ng-if="newBridgeInterface.bridge_stp"> |
544 | + <label for="fd" class="two-col">Forward delay</label> |
545 | + <input type="text" name="mac" class="three-col" |
546 | + data-ng-model="newBridgeInterface.bridge_fd"> |
547 | + </div> |
548 | + </div> |
549 | + </div> |
550 | + </div> |
551 | + <div class="table__row is-active"> |
552 | + <div class="table__data u-float--right"> |
553 | + <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
554 | + <button class="button--primary button--inline" |
555 | + data-ng-click="addBridge()" |
556 | + data-ng-disabled="cannotAddBridge()">Save</button> |
557 | + </div> |
558 | + </div> |
559 | + </div> |
560 | + </div> |
561 | + <div class="table__row is-active" data-ng-show="isShowingCreatePhysical()"> |
562 | + <div class="table__data table-col--3"> |
563 | + <input type="checkbox" class="checkbox" id="interface-create" disabled="disabled" checked /> |
564 | + <label for="interface-create"></label> |
565 | + </div> |
566 | + <div class="table__data table-col--12"> |
567 | + <input type="text" class="table__input" |
568 | + data-ng-class="{ 'has-error': isInterfaceNameInvalid(newInterface) }" |
569 | + data-ng-model="newInterface.name"> |
570 | + </div> |
571 | + <div class="table__data table-col--85"></div> |
572 | + <div class="table__dropdown"> |
573 | + <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing is-active"> |
574 | + <div class="table__row--indent"> |
575 | + <div class="form__fieldset six-col"> |
576 | + <dl> |
577 | + <dt class="two-col">Type</dt> |
578 | + <dd class="four-col last-col">Physical</dd> |
579 | + </dl> |
580 | + <div class="form__group"> |
581 | + <label for="mac" class="two-col">MAC address</label> |
582 | + <input type="text" name="mac" class="three-col" |
583 | + data-ng-model="newInterface.macAddress" |
584 | + data-ng-class="{ 'has-error': isMACAddressInvalid(newInterface.macAddress, false) || newInterface.macError }"> |
585 | + </div> |
586 | + <div class="form__group"> |
587 | + <label class="two-col">Tags</label> |
588 | + <div class="form__group-input three-col last-col"> |
589 | + <tags-input ng-model="newInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
590 | + </div> |
591 | + </div> |
592 | + </div> |
593 | + <div class="form__fieldset six-col last-col"> |
594 | + <div class="form__group"> |
595 | + <label for="fabric" class="two-col">Fabric</label> |
596 | + <select name="fabric" class="three-col" |
597 | + data-ng-model="newInterface.fabric" |
598 | + data-ng-change="fabricChanged(newInterface)" |
599 | + data-ng-options="fabric as fabric.name for fabric in fabrics"> |
600 | + </select> |
601 | + </div> |
602 | + <div class="form__group"> |
603 | + <label for="vlan" class="two-col">VLAN</label> |
604 | + <select name="vlan" class="three-col" |
605 | + data-ng-model="newInterface.vlan" |
606 | + data-ng-options="vlan as getVLANText(vlan) for vlan in vlans" |
607 | + disabled="disabled"> |
608 | + </select> |
609 | + </div> |
610 | + <div class="form__group"> |
611 | + <label for="subnet" class="two-col">Subnet</label> |
612 | + <select name="subnet" class="three-col" |
613 | + ng-model="newInterface.subnet" |
614 | + data-ng-change="subnetChanged(newInterface)" |
615 | + data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:newInterface.vlan"> |
616 | + <option value="" data-ng-hide="newInterface.type === 'alias'">Unconfigured</option> |
617 | + </select> |
618 | + </div> |
619 | + <div class="form__group" data-ng-if="!isLinkModeDisabled(newInterface)"> |
620 | + <label for="link-mode" class="two-col">IP mode</label> |
621 | + <select name="link-mode" class="three-col" |
622 | + data-ng-model="newInterface.mode" |
623 | + data-ng-change="modeChanged(newInterface)" |
624 | + data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:newInterface"> |
625 | + </select> |
626 | + </div> |
627 | + <div class="form__group" data-ng-if="newInterface.mode == 'static'"> |
628 | + <label for="ip-address" class="two-col">IP address</label> |
629 | + <input name="ip-address" type="text" class="three-col" |
630 | + placeholder="IP address (optional)" |
631 | + ng-model="newInterface.ip_address" |
632 | + data-ng-class="{ 'has-error': isIPAddressInvalid(newInterface) }"> |
633 | + </div> |
634 | + </div> |
635 | + </div> |
636 | + </div> |
637 | + </div> |
638 | + <div class="table__dropdown"> |
639 | + <div class="table__row is-active"> |
640 | + <div class="table__data u-float--left" data-ng-show="newInterface.errorMsg"> |
641 | + <span class="icon icon--error u-margin--right-small"></span>{$ newInterface.errorMsg $} |
642 | + </div> |
643 | + <div class="table__data u-float--right"> |
644 | + <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
645 | + <button class="button--primary button--inline" |
646 | + data-ng-click="addPhysicalInterface()" |
647 | + data-ng-disabled="cannotAddPhysicalInterface()">Save</button> |
648 | + </div> |
649 | + </div> |
650 | </div> |
651 | </div> |
652 | </main> |
653 | </div> |
654 | + <div data-ng-if="!isController" data-ng-hide="isAllNetworkingDisabled() || isShowingCreateBond() || isShowingCreatePhysical()"> |
655 | + <a class="button--secondary button--inline" |
656 | + data-ng-disabled="selectedMode !== null" |
657 | + data-ng-click="showCreatePhysical()">Add interface</a> |
658 | + <a class="button--secondary button--inline" |
659 | + data-ng-disabled="!canCreateBond()" |
660 | + data-ng-click="showCreateBond()">Create bond</a> |
661 | + <a class="button--secondary button--inline" |
662 | + data-ng-disabled="!canCreateBridge()" |
663 | + data-ng-click="showCreateBridge()">Create bridge</a> |
664 | + </div> |
665 | </form> |
666 | </div> |
667 | </div> |
668 | </div> |
669 | - <div class="row" ng-controller="NodeNetworkingController"> |
670 | - <div class="wrapper--inner"> |
671 | - <div class="twelve-col" data-ng-hide="loaded"> |
672 | - <h2>Interfaces</h2> |
673 | - <p><i class="icon icon--loading u-animation--spin"></i>Loading...</p> |
674 | - </div> |
675 | - <form class="ng-hide" data-ng-show="loaded"> |
676 | - <div class="twelve-col"> |
677 | - <h2 class="title">Interfaces</h2> |
678 | - </div> |
679 | - <div class="twelve-col"> |
680 | - <ul class="flash-messages" data-ng-if=" |
681 | - (!isController && isAllNetworkingDisabled() && isSuperUser()) || |
682 | - !node.on_network || (!isController && !isUbuntuOS())"> |
683 | - <li class="flash-messages__item flash-messages__item--error" data-ng-if="!node.on_network"> |
684 | - Node must be connected to a network. |
685 | - </li> |
686 | - <li class="flash-messages__item flash-messages__item--info" data-ng-if="!isController && isAllNetworkingDisabled() && isSuperUser()"> |
687 | - Interface configuration cannot be modified unless the node is Ready or Broken. |
688 | - </li> |
689 | - <li class="flash-messages__item flash-messages__item--info" data-ng-if="!isController && !isUbuntuOS()"> |
690 | - Custom network configuration only supported on Ubuntu. Using OS default configuration. |
691 | - </li> |
692 | - </ul> |
693 | - </div> |
694 | - <div class="table table--hover u-margin--bottom"> |
695 | - <header class="table__head"> |
696 | - <div class="table__row"> |
697 | - <div class="table__header table-col--3"></div> |
698 | - <div class="table__header table-col--12"> |
699 | - <a class="table__header-link is-active" |
700 | - data-ng-class="{ 'is-active': column == 'name' }" |
701 | - data-ng-click="column = 'name'"> |
702 | - Name |
703 | - </a> |
704 | - <span class="divide"></span> |
705 | - <a class="table__header-link" data-ng-class="{ 'is-active': column == 'mac' }" |
706 | - data-ng-click="column = 'mac'"> |
707 | - MAC |
708 | - </a> |
709 | - </div> |
710 | - <div class="table__header table-col--3"><span data-ng-if="!isController">PXE</span></div> |
711 | - <div class="table__header table-col--9">Type</div> |
712 | - <div class="table__header table-col--14">Fabric</div> |
713 | - <div class="table__header table-col--14">VLAN</div> |
714 | - <div class="table__header table-col--18">Subnet</div> |
715 | - <div class="table__header table-col--27">IP Address</div> |
716 | - </div> |
717 | - </header> |
718 | - <main class="table__body" data-selected-rows> |
719 | - <div class="table__row" |
720 | - data-ng-class="{ disabled: isDisabled(), 'is-active': isInterfaceSelected(interface) && isNodeEditingAllowed(), noEdit: cannotEditInterface(interface) }" |
721 | - data-ng-repeat="interface in interfaces | removeInterfaceParents:newBondInterface:!isNodeEditingAllowed() | removeInterfaceParents:newBridgeInterface:!isNodeEditingAllowed()"> |
722 | - <div class="table__data table-col--3"> |
723 | - <input type="checkbox" class="checkbox" id="{$ getUniqueKey(interface) $}" |
724 | - data-ng-hide="isAllNetworkingDisabled()" |
725 | - data-ng-checked="isInterfaceSelected(interface)" |
726 | - data-ng-click="toggleInterfaceSelect(interface)" |
727 | - data-ng-disabled="isDisabled()" |
728 | - data-ng-if="!isController && isNodeEditingAllowed()"> |
729 | - <label for="{$ getUniqueKey(interface) $}"></label> |
730 | - </div> |
731 | - <div class="table__data table-col--12" data-ng-show="column == 'name'"> |
732 | - <span data-ng-if="!isEditing(interface)">{$ interface.name $}</span> |
733 | - <input type="text" class="table__input" |
734 | - data-ng-if="isEditing(interface)" |
735 | - data-ng-model="editInterface.name" |
736 | - data-ng-class="{ 'has-error': isInterfaceNameInvalid(editInterface) }"> |
737 | - </div> |
738 | - <div class="table__data table-col--12 ng-hide" data-ng-show="column == 'mac'"> |
739 | - {$ interface.mac_address $} |
740 | - </div> |
741 | - <div class="table__data table-col--3 u-align--center"> |
742 | - <input type="radio" name="bootInterface" id="{$ interface.name $}" checked |
743 | - data-ng-if="!isController && isBootInterface(interface)"> |
744 | - <label for="{$ interface.name $}"></label> |
745 | - </div> |
746 | - <div class="table__data table-col--9"> |
747 | - <span data-ng-if="!isEditing(interface)">{$ getInterfaceTypeText(interface) $}</span> |
748 | - </div> |
749 | - <div class="table__data table-col--14"> |
750 | - <span data-ng-if="!isEditing(interface)">{$ interface.fabric.name $}</span> |
751 | - </div> |
752 | - <div class="table__data table-col--14"> |
753 | - <span data-ng-if="!isEditing(interface)">{$ getVLANText(interface.vlan) $}</span> |
754 | - </div> |
755 | - <div class="table__data table-col--18"> |
756 | - <span data-ng-if="!isEditing(interface)">{$ getSubnetText(interface.subnet) $}</span> |
757 | - <span data-ng-if="isAllNetworkingDisabled() && interface.discovered[0].subnet_id"> |
758 | - {$ getSubnetText(getSubnet(interface.discovered[0].subnet_id)) $} |
759 | - </span> |
760 | - </div> |
761 | - <div class="table__data table-col--19"> |
762 | - <span data-ng-if="!isEditing(interface) && !interface.discovered[0].ip_address"> |
763 | - {$ interface.ip_address $} ({$ getLinkModeText(interface) $}) |
764 | - </span> |
765 | - <span data-ng-if="!isEditing(interface) && interface.discovered[0].ip_address"> |
766 | - {$ interface.discovered[0].ip_address $} (DHCP) |
767 | - </span> |
768 | - </div> |
769 | - <div class="table__data table-col--8"> |
770 | - <div class="table__controls u-align--right" data-ng-if="isNodeEditingAllowed()"> |
771 | - <a class="icon icon--add tooltip" |
772 | - aria-label="Add Alias or VLAN" |
773 | - data-ng-if="!isController && (canAddAlias(interface) || canAddVLAN(interface))" |
774 | - data-ng-click="quickAdd(interface)"></a> |
775 | - <a class="icon icon--edit tooltip" |
776 | - data-ng-if="!cannotEditInterface(interface)" |
777 | - aria-label="Edit" |
778 | - data-ng-click="edit(interface)"></a> |
779 | - <a class="icon icon--delete tooltip u-margin--left" |
780 | - data-ng-if="!isController" |
781 | - aria-label="Remove" |
782 | - data-ng-click="quickRemove(interface)"></a> |
783 | - </div> |
784 | - </div> |
785 | - <div class="table__dropdown table__dropdown--info"> |
786 | - <div class="table__row" data-ng-class="{ 'is-active': isShowingMembers(interface) }" data-ng-repeat="member in interface.members"> |
787 | - <div data-ng-show="isShowingMembers(interface)"> |
788 | - <div class="table__data u-padding--top-none table-col--3"></div> |
789 | - <div class="table__data u-padding--top-none table-col--15" |
790 | - data-ng-show="column == 'name'">{$ member.name $}</div> |
791 | - <div class="table__data u-padding--top-none table-col--15 ng-hide" |
792 | - data-ng-show="column == 'mac'">{$ member.mac_address $}</div> |
793 | - <div class="table__data u-padding--top-none table-col--15">{$ getInterfaceTypeText(member) $}</div> |
794 | - <div class="table__data u-padding--top-none table-col--67"> |
795 | - </div> |
796 | - </div> |
797 | - </div> |
798 | - </div> |
799 | - <div data-ng-show="isNodeEditingAllowed()"> |
800 | - <div class="table__dropdown"> |
801 | - <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing" data-ng-class="{ 'is-active': isEditing(interface) || isShowingAdd() }"> |
802 | - <div data-ng-if="isShowingAdd()" class="table__row--indent"> |
803 | - <div class="form__fieldset six-col"> |
804 | - <dl> |
805 | - <dt class="two-col">Name</dt> |
806 | - <dd class="four-col last-col">{$ getAddName() $}</dd> |
807 | - </dl> |
808 | - <div class="form__group"> |
809 | - <label for="type" class="two-col">Type</label> |
810 | - <select name="type" class="three-col" |
811 | - data-ng-model="newInterface.type" |
812 | - data-ng-change="addTypeChanged()"> |
813 | - <option value="alias" data-ng-show="canAddAlias(newInterface.parent)">Alias</option> |
814 | - <option value="vlan" data-ng-show="canAddVLAN(newInterface.parent)">VLAN</option> |
815 | - </select> |
816 | - </div> |
817 | - <div class="form__group" data-ng-if="newInterface.type === 'vlan'"> |
818 | - <label class="two-col">Tags</label> |
819 | - <div class="form__group-input three-col last-col"> |
820 | - <tags-input ng-model="newInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
821 | - </div> |
822 | - </div> |
823 | - </div> |
824 | - <div class="form__fieldset six-col last-col"> |
825 | - <div class="form__group"> |
826 | - <label for="fabric" class="two-col">Fabric</label> |
827 | - <select name="fabric" class="three-col" |
828 | - data-ng-model="newInterface.parent.fabric" |
829 | - data-ng-options="fabric as fabric.name for fabric in fabrics" |
830 | - disabled="disabled"> |
831 | - </select> |
832 | - </div> |
833 | - <div class="form__group" data-ng-if="newInterface.type === 'alias'"> |
834 | - <label for="vlan" class="two-col">VLAN</label> |
835 | - <select name="vlan" class="three-col" |
836 | - data-ng-model="newInterface.vlan" |
837 | - data-ng-options="vlan as getVLANText(vlan) for vlan in vlans" |
838 | - disabled="disabled"> |
839 | - </select> |
840 | - </div> |
841 | - <div class="form__group" data-ng-if="newInterface.type === 'vlan'"> |
842 | - <label for="vlan" class="two-col">VLAN</label> |
843 | - <select name="vlan" class="three-col" |
844 | - data-ng-model="newInterface.vlan" |
845 | - data-ng-change="vlanChanged(newInterface)" |
846 | - data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | removeDefaultVLAN | filterByFabric:newInterface.parent.fabric | filterByUnusedForInterface:newInterface.parent:originalInterfaces"> |
847 | - </select> |
848 | - </div> |
849 | - <div class="form__group"> |
850 | - <label for="subnet" class="two-col">Subnet</label> |
851 | - <select name="subnet" class="three-col" |
852 | - ng-model="newInterface.subnet" |
853 | - data-ng-change="subnetChanged(newInterface)" |
854 | - data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:newInterface.vlan"> |
855 | - <option value="" data-ng-hide="newInterface.type === 'alias'">Unconfigured</option> |
856 | - </select> |
857 | - </div> |
858 | - <div class="form__group" data-ng-if="!isLinkModeDisabled(newInterface)"> |
859 | - <label for="link-mode" class="two-col">IP mode</label> |
860 | - <select name="link-mode" class="three-col" |
861 | - data-ng-model="newInterface.mode" |
862 | - data-ng-change="modeChanged(newInterface)" |
863 | - data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:newInterface"> |
864 | - </select> |
865 | - </div> |
866 | - <div class="form__group" data-ng-if="newInterface.mode == 'static'"> |
867 | - <label for="ip-address" class="two-col">IP address</label> |
868 | - <input name="ip-address" type="text" class="three-col" |
869 | - placeholder="IP address (optional)" |
870 | - ng-model="newInterface.ip_address" |
871 | - data-ng-class="{ 'has-error': isIPAddressInvalid(newInterface) }"> |
872 | - </div> |
873 | - </div> |
874 | - </div> |
875 | - <div data-ng-if="isEditing(interface)" class="table__row--indent"> |
876 | - <div class="form__fieldset six-col"> |
877 | - <dl> |
878 | - <dt class="two-col">Type</dt> |
879 | - <dd class="four-col last-col">{$ getInterfaceTypeText(interface) $}</dd> |
880 | - </dl> |
881 | - <div class="form__group" data-ng-if="interface.type != 'alias' && interface.type != 'vlan'"> |
882 | - <label for="mac" class="two-col">MAC address</label> |
883 | - <input name="mac" type="text" class="three-col" |
884 | - placeholder="00:00:00:00:00:00" |
885 | - data-ng-model="editInterface.mac_address" |
886 | - data-ng-class="{ 'has-error': isMACAddressInvalid(editInterface.mac_address, true) }"> |
887 | - </div> |
888 | - <div class="form__group"> |
889 | - <label class="two-col" data-ng-if="interface.type != 'alias'">Tags</label> |
890 | - <div class="form__group-input three-col last-col" data-ng-if="interface.type != 'alias'"> |
891 | - <tags-input ng-model="editInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
892 | - </div> |
893 | - </div> |
894 | - </div> |
895 | - <div class="form__fieldset six-col last-col"> |
896 | - <div class="form__group"> |
897 | - <label for="fabric" class="two-col">Fabric</label> |
898 | - <select name="fabric" class="three-col" |
899 | - data-ng-model="editInterface.fabric" |
900 | - data-ng-change="fabricChanged(editInterface)" |
901 | - data-ng-disabled="interface.type === 'vlan'" |
902 | - data-ng-options="fabric as fabric.name for fabric in fabrics"> |
903 | - <option value="">Disconnected</option> |
904 | - </select> |
905 | - </div> |
906 | - <div class="form__group" data-ng-if="editInterface.fabric"> |
907 | - <label for="vlan" class="two-col">VLAN</label> |
908 | - <select name="vlan" class="three-col" |
909 | - ng-model="editInterface.vlan" |
910 | - data-ng-disabled="interface.type === 'physical' || interface.type === 'bond'" |
911 | - data-ng-change="vlanChanged(editInterface)" |
912 | - data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | removeDefaultVLANIfVLAN:interface.type | filterByFabric:editInterface.fabric"> |
913 | - </select> |
914 | - </div> |
915 | - <div class="form__group" data-ng-if="editInterface.fabric"> |
916 | - <label for="subnet" class="two-col">Subnet</label> |
917 | - <select name="subnet" class="three-col" |
918 | - ng-model="editInterface.subnet" |
919 | - data-ng-change="subnetChanged(newInterface)" |
920 | - data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:editInterface.vlan"> |
921 | - <option value="" data-ng-hide="interface.links.length > 1">Unconfigured</option> |
922 | - </select> |
923 | - </div> |
924 | - <div class="form__group" data-ng-if="editInterface.fabric && !isLinkModeDisabled(editInterface)"> |
925 | - <label for="link-mode" class="two-col">IP mode</label> |
926 | - <select name="link-mode" class="three-col" |
927 | - ng-model="editInterface.mode" |
928 | - data-ng-change="modeChanged(editInterface)" |
929 | - data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:editInterface"> |
930 | - </select> |
931 | - </div> |
932 | - <div class="form__group" data-ng-if="editInterface.fabric && editInterface.mode == 'static'"> |
933 | - <label for="ip-address" class="two-col">IP address</label> |
934 | - <div class="form__group-input three-col last-col"> |
935 | - <input name="ip-address" type="text" |
936 | - placeholder="IP address (optional)" |
937 | - ng-model="editInterface.ip_address" |
938 | - data-ng-class="{ 'has-error': isIPAddressInvalid(editInterface) }"> |
939 | - <ul class="errors u-margin--bottom-none form__group--errors" data-ng-if="getInterfaceError(editInterface)"> |
940 | - <li>{$ getInterfaceError(editInterface) $}</li> |
941 | - </ul> |
942 | - </div> |
943 | - </div> |
944 | - </div> |
945 | - </div> |
946 | - </div> |
947 | - <div class="table__row u-padding--right-small u-padding--left-small box-sizing is-active" data-ng-if="isShowingDeleteConfirm()"> |
948 | - <div class="table__data u-float--left"> |
949 | - <p><span class="icon icon--warning u-margin--right-small"></span> Are you sure you want to remove this {$ getRemoveTypeText(interface) $}?</p> |
950 | - </div> |
951 | - <div class="table__data u-float--right"> |
952 | - <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
953 | - <button class="button--primary button--inline" data-ng-click="confirmRemove(interface)">Remove</button> |
954 | - </div> |
955 | - </div> |
956 | - <div class="table__row is-active" data-ng-if="isEditing(interface)"> |
957 | - <div class="table__data u-float--right"> |
958 | - <a class="button--base button--inline" data-ng-click="editCancel()">Cancel</a> |
959 | - <button class="button--primary button--inline" data-ng-disabled="isInterfaceNameInvalid(editInterface) || isIPAddressInvalid(editInterface) || isMACAddressInvalid(editInterface.mac_address, true)" data-ng-click="editSave()">Save</button> |
960 | - </div> |
961 | - </div> |
962 | - <div class="table__row is-active" data-ng-if="isShowingAdd() && !newInterface.saving"> |
963 | - <div class="table__data u-float--left"> |
964 | - <button class="button--secondary button--inline" |
965 | - data-ng-click="addInterface('alias')" |
966 | - data-ng-show="canAddAlias(interface)">Add <span data-ng-show="newInterface.type === 'alias'">another </span>alias</button> |
967 | - <button class="button--secondary button--inline" |
968 | - data-ng-click="addInterface('vlan')" |
969 | - data-ng-show="canAddAnotherVLAN(interface)">Add <span data-ng-show="newInterface.type === 'vlan'">another </span>VLAN</button> |
970 | - </div> |
971 | - <div class="table__data u-float--right"> |
972 | - <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
973 | - <button class="button--primary button--inline" data-ng-click="addInterface()">Add</button> |
974 | - </div> |
975 | - </div> |
976 | - </div> |
977 | - </div> |
978 | - </div> |
979 | - <div class="table__row is-active" data-ng-if="isShowingCreateBond() && isNodeEditingAllowed()"> |
980 | - <div class="table__data table-col--3"> |
981 | - <input type="checkbox" class="checkbox" name="bond-create" disabled="disabled" checked /> |
982 | - <label for="bond-create"></label> |
983 | - </div> |
984 | - <div class="table__data table-col--12"> |
985 | - <input type="text" name="name" class="table__input editible" |
986 | - data-ng-class="{ 'has-error': isInterfaceNameInvalid(newBondInterface) }" |
987 | - data-ng-model="newBondInterface.name"> |
988 | - </div> |
989 | - <div class="table__data table-col--3 u-align--center"> |
990 | - <input type="radio" name="bondBootInterface" checked id="{$ newBondInterface $}" |
991 | - data-ng-if="hasBootInterface(newBondInterface)"> |
992 | - <label for="{$ newBondInterface $}"></label> |
993 | - </div> |
994 | - <div class="table__data table-col--82"></div> |
995 | - <div class="table__dropdown"> |
996 | - <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing is-active"> |
997 | - <div class="table__row--indent"> |
998 | - <div class="form__fieldset six-col"> |
999 | - <div class="form__group"> |
1000 | - <label for="bond-mode" class="two-col">Bond mode</label> |
1001 | - <select name="bond-mode" class="three-col" |
1002 | - data-ng-model="newBondInterface.mode" |
1003 | - data-ng-options="mode[0] as mode[1] for mode in bondOptions.modes"> |
1004 | - </select> |
1005 | - </div> |
1006 | - <div class="form__group"> |
1007 | - <label for="mac" class="two-col">MAC address</label> |
1008 | - <input type="text" name="mac" class="three-col" |
1009 | - data-ng-model="newBondInterface.macAddress" |
1010 | - data-ng-class="{ 'has-error': isMACAddressInvalid(newBondInterface.macAddress) }" |
1011 | - data-ng-placeholder="getInterfacePlaceholderMACAddress(newBondInterface)"> |
1012 | - </div> |
1013 | - <div class="form__group"> |
1014 | - <label class="two-col">Tags</label> |
1015 | - <div class="form__Group-input three-col last-col"> |
1016 | - <tags-input ng-model="newBondInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
1017 | - </div> |
1018 | - </div> |
1019 | - </div> |
1020 | - <div class="form__fieldset six-col last-col"> |
1021 | - <div class="form__group" data-ng-if="showLACPRate()"> |
1022 | - <label for="lacp-rate" class="two-col">LACP rate</label> |
1023 | - <select name="lacp-rate" class="three-col" |
1024 | - data-ng-model="newBondInterface.lacpRate" |
1025 | - data-ng-options="rate[0] as rate[1] for rate in bondOptions.lacp_rates"> |
1026 | - </select> |
1027 | - </div> |
1028 | - <div class="form__group" data-ng-if="showXMITHashPolicy()"> |
1029 | - <label for="xmit-hash-policy" class="two-col">XMIT hash policy</label> |
1030 | - <select name="xmit-hash-policy" class="three-col" |
1031 | - data-ng-model="newBondInterface.xmitHashPolicy" |
1032 | - data-ng-options="xmit[0] as xmit[1] for xmit in bondOptions.xmit_hash_policies"> |
1033 | - </select> |
1034 | - </div> |
1035 | - </div> |
1036 | - </div> |
1037 | - </div> |
1038 | - <div class="table__row--indent"> |
1039 | - <div class="table__row table__row--head is-active"> |
1040 | - <div class="table__header table-col--3"></div> |
1041 | - <div class="table__header table-col--15">Name</div> |
1042 | - <div class="table__header table-col--15">Type</div> |
1043 | - <div class="table__header table-col--67">Primary</div> |
1044 | - </div> |
1045 | - <div class="table__row u-border--none is-active" |
1046 | - data-ng-repeat="parent in newBondInterface.parents | orderBy:'name'"> |
1047 | - <div class="table__data u-padding--top-none table-col--3"></div> |
1048 | - <div class="table__data u-padding--top-none table-col--15">{$ parent.name $}</div> |
1049 | - <div class="table__data u-padding--top-none table-col--15">{$ getInterfaceTypeText(parent) $}</div> |
1050 | - <div class="table__data u-padding--top-none table-col--67"> |
1051 | - <input type="radio" name="bondPrimary" id="{$ parent.name $}" data-ng-model="newBondInterface.primary" data-ng-value="parent"> |
1052 | - <label for="{$ parent.name $}"></label> |
1053 | - </div> |
1054 | - </div> |
1055 | - </div> |
1056 | - <div class="table__row is-active"> |
1057 | - <div class="table__data u-float--right"> |
1058 | - <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
1059 | - <button class="button--primary button--inline" |
1060 | - data-ng-click="addBond()" |
1061 | - data-ng-disabled="cannotAddBond()">Save</button> |
1062 | - </div> |
1063 | - </div> |
1064 | - </div> |
1065 | - </div> |
1066 | - <div class="table__row is-active" data-ng-if="isShowingCreateBridge() && isNodeEditingAllowed()"> |
1067 | - <div class="table__data table-col--3"> |
1068 | - <input type="checkbox" class="checkbox" id="bond-create" disabled="disabled" checked /> |
1069 | - <label for="bridge-create"></label> |
1070 | - </div> |
1071 | - <div class="table__data table-col--12"> |
1072 | - <input type="text" class="table__input editible" |
1073 | - data-ng-class="{ 'has-error': isInterfaceNameInvalid(newBridgeInterface) }" |
1074 | - data-ng-model="newBridgeInterface.name"> |
1075 | - </div> |
1076 | - <div class="table__data table-col--3"> |
1077 | - <input class="align-center" type="radio" id="{$ newBridgeInterface $}" name="bridgeBootInterface" checked |
1078 | - data-ng-if="hasBootInterface(newBridgeInterface)"> |
1079 | - <label for="{$ newBridgeInterface $}"></label> |
1080 | - </div> |
1081 | - <div class="table__data table-col--82"></div> |
1082 | - <div class="table__dropdown"> |
1083 | - <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing is-active"> |
1084 | - <div class="table__row--indent"> |
1085 | - <div class="form__fieldset six-col"> |
1086 | - <dl> |
1087 | - <dt class="two-col">Primary</dt> |
1088 | - <dd class="four-col last-col">{$ newBridgeInterface.primary.name $}</dd> |
1089 | - </dl> |
1090 | - <div class="form__group"> |
1091 | - <label for="mac" class="two-col">MAC address</label> |
1092 | - <input type="text" name="mac" class="three-col" |
1093 | - data-ng-model="newBridgeInterface.macAddress" |
1094 | - data-ng-class="{ 'has-error': isMACAddressInvalid(newBridgeInterface.macAddress) }" |
1095 | - data-ng-placeholder="getInterfacePlaceholderMACAddress(newBridgeInterface)"> |
1096 | - </div> |
1097 | - <div class="form__group"> |
1098 | - <label class="two-col">Tags</label> |
1099 | - <div class="form__group-input three-col last-col"> |
1100 | - <tags-input ng-model="newBridgeInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
1101 | - </div> |
1102 | - </div> |
1103 | - </div> |
1104 | - <div class="form__fieldset six-col last-col"> |
1105 | - <div class="form__group"> |
1106 | - <label for="stp" class="two-col form__group-label">STP</label> |
1107 | - <div class="form__group-input three-col"> |
1108 | - <div class="onoffswitch"> |
1109 | - <input input id="bridge_stp" type="checkbox" name="bridge_stp" class="onoffswitch-checkbox" |
1110 | - data-ng-model="newBridgeInterface.bridge_stp"> |
1111 | - <label class="onoffswitch-label" for="bridge_stp"> |
1112 | - <span class="onoffswitch-inner"></span> |
1113 | - <span class="onoffswitch-switch"></span> |
1114 | - </label> |
1115 | - </div> |
1116 | - </div> |
1117 | - </div> |
1118 | - <div class="form__group" data-ng-if="newBridgeInterface.bridge_stp"> |
1119 | - <label for="fd" class="two-col">Forward delay</label> |
1120 | - <input type="text" name="mac" class="three-col" |
1121 | - data-ng-model="newBridgeInterface.bridge_fd"> |
1122 | - </div> |
1123 | - </div> |
1124 | - </div> |
1125 | - </div> |
1126 | - <div class="table__row is-active"> |
1127 | - <div class="table__data u-float--right"> |
1128 | - <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
1129 | - <button class="button--primary button--inline" |
1130 | - data-ng-click="addBridge()" |
1131 | - data-ng-disabled="cannotAddBridge()">Save</button> |
1132 | - </div> |
1133 | - </div> |
1134 | - </div> |
1135 | - </div> |
1136 | - <div class="table__row is-active" data-ng-show="isShowingCreatePhysical()"> |
1137 | - <div class="table__data table-col--3"> |
1138 | - <input type="checkbox" class="checkbox" id="interface-create" disabled="disabled" checked /> |
1139 | - <label for="interface-create"></label> |
1140 | - </div> |
1141 | - <div class="table__data table-col--12"> |
1142 | - <input type="text" class="table__input" |
1143 | - data-ng-class="{ 'has-error': isInterfaceNameInvalid(newInterface) }" |
1144 | - data-ng-model="newInterface.name"> |
1145 | - </div> |
1146 | - <div class="table__data table-col--85"></div> |
1147 | - <div class="table__dropdown"> |
1148 | - <div class="table__row form form--stack u-padding--top u-padding--right u-padding--left box-sizing is-active"> |
1149 | - <div class="table__row--indent"> |
1150 | - <div class="form__fieldset six-col"> |
1151 | - <dl> |
1152 | - <dt class="two-col">Type</dt> |
1153 | - <dd class="four-col last-col">Physical</dd> |
1154 | - </dl> |
1155 | - <div class="form__group"> |
1156 | - <label for="mac" class="two-col">MAC address</label> |
1157 | - <input type="text" name="mac" class="three-col" |
1158 | - data-ng-model="newInterface.macAddress" |
1159 | - data-ng-class="{ 'has-error': isMACAddressInvalid(newInterface.macAddress, false) || newInterface.macError }"> |
1160 | - </div> |
1161 | - <div class="form__group"> |
1162 | - <label class="two-col">Tags</label> |
1163 | - <div class="form__group-input three-col last-col"> |
1164 | - <tags-input ng-model="newInterface.tags" allow-tags-pattern="[\w-]+"></tags-input> |
1165 | - </div> |
1166 | - </div> |
1167 | - </div> |
1168 | - <div class="form__fieldset six-col last-col"> |
1169 | - <div class="form__group"> |
1170 | - <label for="fabric" class="two-col">Fabric</label> |
1171 | - <select name="fabric" class="three-col" |
1172 | - data-ng-model="newInterface.fabric" |
1173 | - data-ng-change="fabricChanged(newInterface)" |
1174 | - data-ng-options="fabric as fabric.name for fabric in fabrics"> |
1175 | - </select> |
1176 | - </div> |
1177 | - <div class="form__group"> |
1178 | - <label for="vlan" class="two-col">VLAN</label> |
1179 | - <select name="vlan" class="three-col" |
1180 | - data-ng-model="newInterface.vlan" |
1181 | - data-ng-options="vlan as getVLANText(vlan) for vlan in vlans" |
1182 | - disabled="disabled"> |
1183 | - </select> |
1184 | - </div> |
1185 | - <div class="form__group"> |
1186 | - <label for="subnet" class="two-col">Subnet</label> |
1187 | - <select name="subnet" class="three-col" |
1188 | - ng-model="newInterface.subnet" |
1189 | - data-ng-change="subnetChanged(newInterface)" |
1190 | - data-ng-options="subnet as getSubnetText(subnet) for subnet in subnets | filterByVLAN:newInterface.vlan"> |
1191 | - <option value="" data-ng-hide="newInterface.type === 'alias'">Unconfigured</option> |
1192 | - </select> |
1193 | - </div> |
1194 | - <div class="form__group" data-ng-if="!isLinkModeDisabled(newInterface)"> |
1195 | - <label for="link-mode" class="two-col">IP mode</label> |
1196 | - <select name="link-mode" class="three-col" |
1197 | - data-ng-model="newInterface.mode" |
1198 | - data-ng-change="modeChanged(newInterface)" |
1199 | - data-ng-options="mode.mode as mode.text for mode in modes | filterLinkModes:newInterface"> |
1200 | - </select> |
1201 | - </div> |
1202 | - <div class="form__group" data-ng-if="newInterface.mode == 'static'"> |
1203 | - <label for="ip-address" class="two-col">IP address</label> |
1204 | - <input name="ip-address" type="text" class="three-col" |
1205 | - placeholder="IP address (optional)" |
1206 | - ng-model="newInterface.ip_address" |
1207 | - data-ng-class="{ 'has-error': isIPAddressInvalid(newInterface) }"> |
1208 | - </div> |
1209 | - </div> |
1210 | - </div> |
1211 | - </div> |
1212 | - </div> |
1213 | - <div class="table__dropdown"> |
1214 | - <div class="table__row is-active"> |
1215 | - <div class="table__data u-float--left" data-ng-show="newInterface.errorMsg"> |
1216 | - <span class="icon icon--error u-margin--right-small"></span>{$ newInterface.errorMsg $} |
1217 | - </div> |
1218 | - <div class="table__data u-float--right"> |
1219 | - <a class="button--base button--inline" data-ng-click="cancel()">Cancel</a> |
1220 | - <button class="button--primary button--inline" |
1221 | - data-ng-click="addPhysicalInterface()" |
1222 | - data-ng-disabled="cannotAddPhysicalInterface()">Save</button> |
1223 | - </div> |
1224 | - </div> |
1225 | - </div> |
1226 | - </div> |
1227 | - </main> |
1228 | - </div> |
1229 | - <div data-ng-if="!isController" data-ng-hide="isAllNetworkingDisabled() || isShowingCreateBond() || isShowingCreatePhysical()"> |
1230 | - <a class="button--secondary button--inline" |
1231 | - data-ng-disabled="selectedMode !== null" |
1232 | - data-ng-click="showCreatePhysical()">Add interface</a> |
1233 | - <a class="button--secondary button--inline" |
1234 | - data-ng-disabled="!canCreateBond()" |
1235 | - data-ng-click="showCreateBond()">Create bond</a> |
1236 | - <a class="button--secondary button--inline" |
1237 | - data-ng-disabled="!canCreateBridge()" |
1238 | - data-ng-click="showCreateBridge()">Create bridge</a> |
1239 | - </div> |
1240 | - </form> |
1241 | - </div> |
1242 | - </div> |
1243 | <div class="row" id="storage" data-ng-hide="isController"> |
1244 | <div class="wrapper--inner" ng-controller="NodeStorageController"> |
1245 | <form> |
I've not tested it but codewise it looks good to me!