Merge lp:~ricgard/maas/vlan-not-loading-on-rack-details--fix-bug-1621285 into lp:~maas-committers/maas/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
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.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

I've not tested it but codewise it looks good to me!

review: Approve

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>&nbsp;&nbsp;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>&nbsp;&nbsp;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>