device.html 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. {% extends '_base.html' %}
  2. {% load static from staticfiles %}
  3. {% load helpers %}
  4. {% block title %}{{ device }}{% endblock %}
  5. {% block content %}
  6. {% include 'dcim/inc/device_header.html' with active_tab='info' %}
  7. <div class="row">
  8. <div class="col-md-6">
  9. <div class="panel panel-default">
  10. <div class="panel-heading">
  11. <strong>Device</strong>
  12. </div>
  13. <table class="table table-hover panel-body attr-table">
  14. <tr>
  15. <td>Site</td>
  16. <td>
  17. {% if device.site.region %}
  18. <a href="{{ device.site.region.get_absolute_url }}">{{ device.site.region }}</a>
  19. <i class="fa fa-angle-right"></i>
  20. {% endif %}
  21. <a href="{% url 'dcim:site' slug=device.site.slug %}">{{ device.site }}</a>
  22. </td>
  23. </tr>
  24. <tr>
  25. <td>Rack</td>
  26. <td>
  27. {% if device.rack %}
  28. {% if device.rack.group %}
  29. <a href="{{ device.rack.group.get_absolute_url }}">{{ device.rack.group }}</a>
  30. <i class="fa fa-angle-right"></i>
  31. {% endif %}
  32. <a href="{% url 'dcim:rack' pk=device.rack.pk %}">{{ device.rack }}</a>
  33. {% else %}
  34. <span class="text-muted">None</span>
  35. {% endif %}
  36. </td>
  37. </tr>
  38. <tr>
  39. <td>Position</td>
  40. <td>
  41. {% if device.parent_bay %}
  42. {% with device.parent_bay.device as parent %}
  43. <a href="{{ parent.get_absolute_url }}">{{ parent }}</a> <i class="fa fa-angle-right"></i> {{ device.parent_bay }}
  44. {% if parent.position %}
  45. (U{{ parent.position }} / {{ parent.get_face_display }})
  46. {% endif %}
  47. {% endwith %}
  48. {% elif device.rack and device.position %}
  49. <span>U{{ device.position }} / {{ device.get_face_display }}</span>
  50. {% elif device.rack and device.device_type.u_height %}
  51. <span class="label label-warning">Not racked</span>
  52. {% else %}
  53. <span class="text-muted">N/A</span>
  54. {% endif %}
  55. </td>
  56. </tr>
  57. <tr>
  58. <td>Tenant</td>
  59. <td>
  60. {% if device.tenant %}
  61. {% if device.tenant.group %}
  62. <a href="{{ device.tenant.group.get_absolute_url }}">{{ device.tenant.group }}</a>
  63. <i class="fa fa-angle-right"></i>
  64. {% endif %}
  65. <a href="{{ device.tenant.get_absolute_url }}">{{ device.tenant }}</a>
  66. {% else %}
  67. <span class="text-muted">None</span>
  68. {% endif %}
  69. </td>
  70. </tr>
  71. <tr>
  72. <td>Device Type</td>
  73. <td>
  74. <span><a href="{% url 'dcim:devicetype' pk=device.device_type.pk %}">{{ device.device_type.full_name }}</a> ({{ device.device_type.u_height }}U)</span>
  75. </td>
  76. </tr>
  77. <tr>
  78. <td>Serial Number</td>
  79. <td>
  80. {% if device.serial %}
  81. <span>{{ device.serial }}</span>
  82. {% else %}
  83. <span class="text-muted">N/A</span>
  84. {% endif %}
  85. </td>
  86. </tr>
  87. <tr>
  88. <td>Asset Tag</td>
  89. <td>
  90. {% if device.asset_tag %}
  91. <span>{{ device.asset_tag }}</span>
  92. {% else %}
  93. <span class="text-muted">N/A</span>
  94. {% endif %}
  95. </td>
  96. </tr>
  97. </table>
  98. </div>
  99. {% if vc_members %}
  100. <div class="panel panel-default">
  101. <div class="panel-heading">
  102. <strong>Virtual Chassis</strong>
  103. </div>
  104. <table class="table table-hover panel-body attr-table">
  105. <tr>
  106. <th>Device</th>
  107. <th>Position</th>
  108. <th>Master</th>
  109. <th>Priority</th>
  110. </tr>
  111. {% for vc_member in vc_members %}
  112. <tr{% if vc_member == device %} class="info"{% endif %}>
  113. <td>
  114. <a href="{{ vc_member.get_absolute_url }}">{{ vc_member }}</a>
  115. </td>
  116. <td><span class="badge badge-default">{{ vc_member.vc_position }}</span></td>
  117. <td>{% if device.virtual_chassis.master == vc_member %}<i class="fa fa-check"></i>{% endif %}</td>
  118. <td>{{ vc_member.vc_priority|default:"" }}</td>
  119. </tr>
  120. {% endfor %}
  121. </table>
  122. <div class="panel-footer text-right">
  123. {% if perms.dcim.change_virtualchassis %}
  124. <a href="{% url 'dcim:virtualchassis_add_member' pk=device.virtual_chassis.pk %}?site={{ device.site.pk }}&rack={{ device.rack.pk }}&return_url={{ device.get_absolute_url }}" class="btn btn-primary btn-xs">
  125. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Member
  126. </a>
  127. <a href="{% url 'dcim:virtualchassis_edit' pk=device.virtual_chassis.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
  128. <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit Virtual Chassis
  129. </a>
  130. {% endif %}
  131. {% if perms.dcim.delete_virtualchassis %}
  132. <a href="{% url 'dcim:virtualchassis_delete' pk=device.virtual_chassis.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-xs">
  133. <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Virtual Chassis
  134. </a>
  135. {% endif %}
  136. </div>
  137. </div>
  138. {% endif %}
  139. <div class="panel panel-default">
  140. <div class="panel-heading">
  141. <strong>Management</strong>
  142. </div>
  143. <table class="table table-hover panel-body attr-table">
  144. <tr>
  145. <td>Role</td>
  146. <td>
  147. <a href="{{ device.device_role.get_absolute_url }}">{{ device.device_role }}</a>
  148. </td>
  149. </tr>
  150. <tr>
  151. <td>Platform</td>
  152. <td>
  153. {% if device.platform %}
  154. <span>{{ device.platform }}</span>
  155. {% else %}
  156. <span class="text-muted">None</span>
  157. {% endif %}
  158. </td>
  159. </tr>
  160. <tr>
  161. <td>Status</td>
  162. <td>
  163. <span class="label label-{{ device.get_status_class }}">{{ device.get_status_display }}</span>
  164. </td>
  165. </tr>
  166. <tr>
  167. <td>Primary IPv4</td>
  168. <td>
  169. {% if device.primary_ip4 %}
  170. <a href="{% url 'ipam:ipaddress' pk=device.primary_ip4.pk %}">{{ device.primary_ip4.address.ip }}</a>
  171. {% if device.primary_ip4.nat_inside %}
  172. <span>(NAT for {{ device.primary_ip4.nat_inside.address.ip }})</span>
  173. {% elif device.primary_ip4.nat_outside %}
  174. <span>(NAT: {{ device.primary_ip4.nat_outside.address.ip }})</span>
  175. {% endif %}
  176. {% else %}
  177. <span class="text-muted">N/A</span>
  178. {% endif %}
  179. </td>
  180. </tr>
  181. <tr>
  182. <td>Primary IPv6</td>
  183. <td>
  184. {% if device.primary_ip6 %}
  185. <a href="{% url 'ipam:ipaddress' pk=device.primary_ip6.pk %}">{{ device.primary_ip6.address.ip }}</a>
  186. {% if device.primary_ip6.nat_inside %}
  187. <span>(NAT for {{ device.primary_ip6.nat_inside.address.ip }})</span>
  188. {% elif device.primary_ip6.nat_outside %}
  189. <span>(NAT: {{ device.primary_ip6.nat_outside.address.ip }})</span>
  190. {% endif %}
  191. {% else %}
  192. <span class="text-muted">N/A</span>
  193. {% endif %}
  194. </td>
  195. </tr>
  196. {% if device.cluster %}
  197. <tr>
  198. <td>Cluster</td>
  199. <td>
  200. {% if device.cluster.group %}
  201. <a href="{{ device.cluster.group.get_absolute_url }}">{{ device.cluster.group }}</a>
  202. <i class="fa fa-angle-right"></i>
  203. {% endif %}
  204. <a href="{{ device.cluster.get_absolute_url }}">{{ device.cluster }}</a>
  205. </td>
  206. </tr>
  207. {% endif %}
  208. </table>
  209. </div>
  210. {% with device.get_custom_fields as custom_fields %}
  211. {% include 'inc/custom_fields_panel.html' %}
  212. {% endwith %}
  213. <div class="panel panel-default">
  214. <div class="panel-heading">
  215. <strong>Comments</strong>
  216. </div>
  217. <div class="panel-body">
  218. {% if device.comments %}
  219. {{ device.comments|gfm }}
  220. {% else %}
  221. <span class="text-muted">None</span>
  222. {% endif %}
  223. </div>
  224. </div>
  225. </div>
  226. <div class="col-md-6">
  227. <div class="panel panel-default">
  228. <div class="panel-heading">
  229. <strong>Console / Power</strong>
  230. </div>
  231. <table class="table table-hover panel-body component-list">
  232. {% for cp in console_ports %}
  233. {% include 'dcim/inc/consoleport.html' %}
  234. {% empty %}
  235. {% if device.device_type.console_port_templates.exists %}
  236. <tr>
  237. <td colspan="6" class="alert-warning">
  238. <i class="fa fa-fw fa-warning"></i> No console ports defined
  239. {% if perms.dcim.add_consoleport %}
  240. <a href="{% url 'dcim:consoleport_add' pk=device.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a>
  241. {% endif %}
  242. </td>
  243. </tr>
  244. {% endif %}
  245. {% endfor %}
  246. {% for pp in power_ports %}
  247. {% include 'dcim/inc/powerport.html' %}
  248. {% empty %}
  249. {% if device.device_type.power_port_templates.exists %}
  250. <tr>
  251. <td colspan="6" class="alert-warning">
  252. <i class="fa fa-fw fa-warning"></i> No power ports defined
  253. {% if perms.dcim.add_powerport %}
  254. <a href="{% url 'dcim:powerport_add' pk=device.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a>
  255. {% endif %}
  256. </td>
  257. </tr>
  258. {% endif %}
  259. {% endfor %}
  260. </table>
  261. {% if perms.dcim.add_interface or perms.dcim.add_consoleport or perms.dcim.add_powerport %}
  262. <div class="panel-footer text-right">
  263. {% if perms.dcim.add_consoleport %}
  264. <a href="{% url 'dcim:consoleport_add' pk=device.pk %}" class="btn btn-xs btn-primary">
  265. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add console port
  266. </a>
  267. {% endif %}
  268. {% if perms.dcim.add_powerport %}
  269. <a href="{% url 'dcim:powerport_add' pk=device.pk %}" class="btn btn-xs btn-primary">
  270. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add power port
  271. </a>
  272. {% endif %}
  273. </div>
  274. {% endif %}
  275. </div>
  276. {% if request.user.is_authenticated %}
  277. <div class="panel panel-default">
  278. <div class="panel-heading">
  279. <strong>Secrets</strong>
  280. </div>
  281. {% if secrets %}
  282. <table class="table table-hover panel-body">
  283. {% for secret in secrets %}
  284. {% include 'secrets/inc/secret_tr.html' %}
  285. {% endfor %}
  286. </table>
  287. {% else %}
  288. <div class="panel-body text-muted">
  289. None found
  290. </div>
  291. {% endif %}
  292. {% if perms.secrets.add_secret %}
  293. <form id="secret_form">
  294. {% csrf_token %}
  295. </form>
  296. <div class="panel-footer text-right">
  297. <a href="{% url 'dcim:device_addsecret' pk=device.pk %}" class="btn btn-xs btn-primary">
  298. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
  299. Add secret
  300. </a>
  301. </div>
  302. {% endif %}
  303. </div>
  304. {% endif %}
  305. <div class="panel panel-default">
  306. <div class="panel-heading">
  307. <strong>Services</strong>
  308. </div>
  309. {% if services %}
  310. <table class="table table-hover panel-body">
  311. {% for service in services %}
  312. {% include 'ipam/inc/service.html' %}
  313. {% endfor %}
  314. </table>
  315. {% else %}
  316. <div class="panel-body text-muted">
  317. None
  318. </div>
  319. {% endif %}
  320. {% if perms.ipam.add_service %}
  321. <div class="panel-footer text-right">
  322. <a href="{% url 'dcim:device_service_assign' device=device.pk %}" class="btn btn-xs btn-primary">
  323. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Assign service
  324. </a>
  325. </div>
  326. {% endif %}
  327. </div>
  328. <div class="panel panel-default">
  329. <div class="panel-heading">
  330. <strong>Images</strong>
  331. </div>
  332. {% include 'inc/image_attachments.html' with images=device.images.all %}
  333. {% if perms.extras.add_imageattachment %}
  334. <div class="panel-footer text-right">
  335. <a href="{% url 'dcim:device_add_image' object_id=device.pk %}" class="btn btn-primary btn-xs">
  336. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
  337. Attach an image
  338. </a>
  339. </div>
  340. {% endif %}
  341. </div>
  342. <div class="panel panel-default">
  343. <div class="panel-heading">
  344. <strong>Related Devices</strong>
  345. </div>
  346. {% if related_devices %}
  347. <table class="table table-hover panel-body">
  348. {% for rd in related_devices %}
  349. <tr>
  350. <td>
  351. <a href="{% url 'dcim:device' pk=rd.pk %}">{{ rd }}</a>
  352. </td>
  353. <td>
  354. {% if rd.rack %}
  355. <a href="{% url 'dcim:rack' pk=rd.rack.pk %}">Rack {{ rd.rack }}</a>
  356. {% else %}
  357. <span class="text-muted">&mdash;</span>
  358. {% endif %}
  359. </td>
  360. <td>{{ rd.device_type.full_name }}</td>
  361. </tr>
  362. {% endfor %}
  363. </table>
  364. {% else %}
  365. <div class="panel-body text-muted">None found</div>
  366. {% endif %}
  367. </div>
  368. </div>
  369. </div>
  370. <div class="row">
  371. <div class="col-md-12">
  372. {% if device_bays or device.device_type.is_parent_device %}
  373. {% if perms.dcim.delete_devicebay %}
  374. <form method="post" action="{% url 'dcim:devicebay_bulk_delete' pk=device.pk %}">
  375. {% csrf_token %}
  376. {% endif %}
  377. <div class="panel panel-default">
  378. <div class="panel-heading">
  379. <strong>Device Bays</strong>
  380. </div>
  381. <table class="table table-hover table-headings panel-body component-list">
  382. <thead>
  383. <tr>
  384. {% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %}
  385. <th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
  386. {% endif %}
  387. <th>Name</th>
  388. <th colspan="2">Installed Device</th>
  389. <th></th>
  390. </tr>
  391. </thead>
  392. <tbody>
  393. {% for devicebay in device_bays %}
  394. {% include 'dcim/inc/devicebay.html' %}
  395. {% empty %}
  396. <tr>
  397. <td colspan="5" class="text-center text-muted">&mdash; No device bays defined &mdash;</td>
  398. </tr>
  399. {% endfor %}
  400. </tbody>
  401. </table>
  402. <div class="panel-footer">
  403. {% if device_bays and perms.dcim.change_devicebay %}
  404. <button type="submit" name="_rename" formaction="{% url 'dcim:devicebay_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
  405. <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
  406. </button>
  407. {% endif %}
  408. {% if device_bays and perms.dcim.delete_devicebay %}
  409. <button type="submit" class="btn btn-danger btn-xs">
  410. <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete selected
  411. </button>
  412. {% endif %}
  413. {% if perms.dcim.add_devicebay %}
  414. <div class="pull-right">
  415. <a href="{% url 'dcim:devicebay_add' pk=device.pk %}" class="btn btn-primary btn-xs">
  416. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add device bays
  417. </a>
  418. </div>
  419. <div class="clearfix"></div>
  420. {% endif %}
  421. </div>
  422. </div>
  423. {% if perms.dcim.delete_devicebay %}
  424. </form>
  425. {% endif %}
  426. {% endif %}
  427. {% if interfaces or device.device_type.is_network_device %}
  428. {% if perms.dcim.change_interface or perms.dcim.delete_interface %}
  429. <form method="post">
  430. {% csrf_token %}
  431. <input type="hidden" name="device" value="{{ device.pk }}" />
  432. {% endif %}
  433. <div class="panel panel-default">
  434. <div class="panel-heading">
  435. <strong>Interfaces</strong>
  436. <div class="pull-right">
  437. <button class="btn btn-default btn-xs toggle-ips" selected="selected">
  438. <span class="glyphicon glyphicon-check" aria-hidden="true"></span> Show IPs
  439. </button>
  440. </div>
  441. </div>
  442. <table id="interfaces_table" class="table table-hover table-headings panel-body component-list">
  443. <thead>
  444. <tr>
  445. {% if perms.dcim.change_interface or perms.dcim.delete_interface %}
  446. <th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
  447. {% endif %}
  448. <th>Name</th>
  449. <th>LAG</th>
  450. <th>Description</th>
  451. <th>MTU</th>
  452. <th>MAC Address</th>
  453. <th colspan="2">Connection</th>
  454. <th></th>
  455. </tr>
  456. </thead>
  457. <tbody>
  458. {% for iface in interfaces %}
  459. {% include 'dcim/inc/interface.html' %}
  460. {% empty %}
  461. <tr>
  462. <td colspan="9" class="text-center text-muted">&mdash; No interfaces defined &mdash;</td>
  463. </tr>
  464. {% endfor %}
  465. </tbody>
  466. </table>
  467. <div class="panel-footer">
  468. {% if interfaces and perms.dcim.change_interface %}
  469. <button type="submit" name="_rename" formaction="{% url 'dcim:interface_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
  470. <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
  471. </button>
  472. <button type="submit" name="_edit" formaction="{% url 'dcim:interface_bulk_edit' pk=device.pk %}" class="btn btn-warning btn-xs">
  473. <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit
  474. </button>
  475. {% endif %}
  476. {% if interfaces and perms.dcim.delete_interfaceconnection %}
  477. <button type="submit" name="_disconnect" formaction="{% url 'dcim:interface_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
  478. <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
  479. </button>
  480. {% endif %}
  481. {% if interfaces and perms.dcim.delete_interface %}
  482. <button type="submit" name="_delete" formaction="{% url 'dcim:interface_bulk_delete' pk=device.pk %}" class="btn btn-danger btn-xs">
  483. <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
  484. </button>
  485. {% endif %}
  486. {% if perms.dcim.add_interface %}
  487. <div class="pull-right">
  488. <a href="{% url 'dcim:interface_add' pk=device.pk %}" class="btn btn-primary btn-xs">
  489. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add interfaces
  490. </a>
  491. </div>
  492. <div class="clearfix"></div>
  493. {% endif %}
  494. </div>
  495. </div>
  496. {% if perms.dcim.delete_interface %}
  497. </form>
  498. {% endif %}
  499. {% endif %}
  500. {% if cs_ports or device.device_type.is_console_server %}
  501. {% if perms.dcim.delete_consoleserverport %}
  502. <form method="post" action="{% url 'dcim:consoleserverport_bulk_delete' pk=device.pk %}">
  503. {% csrf_token %}
  504. {% endif %}
  505. <div class="panel panel-default">
  506. <div class="panel-heading">
  507. <strong>Console Server Ports</strong>
  508. </div>
  509. <table class="table table-hover table-headings panel-body component-list">
  510. <thead>
  511. <tr>
  512. {% if perms.dcim.change_consoleserverport or perms.dcim.delete_consoleserverport %}
  513. <th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
  514. {% endif %}
  515. <th>Name</th>
  516. <th colspan="2">Connection</th>
  517. <th></th>
  518. </tr>
  519. </thead>
  520. <tbody>
  521. {% for csp in cs_ports %}
  522. {% include 'dcim/inc/consoleserverport.html' %}
  523. {% empty %}
  524. <tr>
  525. <td colspan="5" class="text-center text-muted">&mdash; No console server ports defined &mdash;</td>
  526. </tr>
  527. {% endfor %}
  528. </tbody>
  529. </table>
  530. <div class="panel-footer">
  531. {% if cs_ports and perms.dcim.change_consoleport %}
  532. <button type="submit" name="_rename" formaction="{% url 'dcim:consoleserverport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
  533. <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
  534. </button>
  535. <button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
  536. <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
  537. </button>
  538. {% endif %}
  539. {% if cs_ports and perms.dcim.delete_consoleserverport %}
  540. <button type="submit" class="btn btn-danger btn-xs">
  541. <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
  542. </button>
  543. {% endif %}
  544. {% if perms.dcim.add_consoleserverport %}
  545. <div class="pull-right">
  546. <a href="{% url 'dcim:consoleserverport_add' pk=device.pk %}" class="btn btn-primary btn-xs">
  547. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add console server ports
  548. </a>
  549. </div>
  550. <div class="clearfix"></div>
  551. {% endif %}
  552. </div>
  553. </div>
  554. {% if perms.dcim.delete_consoleserverport %}
  555. </form>
  556. {% endif %}
  557. {% endif %}
  558. {% if power_outlets or device.device_type.is_pdu %}
  559. {% if perms.dcim.delete_poweroutlet %}
  560. <form method="post" action="{% url 'dcim:poweroutlet_bulk_delete' pk=device.pk %}">
  561. {% csrf_token %}
  562. {% endif %}
  563. <div class="panel panel-default">
  564. <div class="panel-heading">
  565. <strong>Power Outlets</strong>
  566. </div>
  567. <table class="table table-hover table-headings panel-body component-list">
  568. <thead>
  569. <tr>
  570. {% if perms.dcim.change_poweroutlet or perms.dcim.delete_poweroutlet %}
  571. <th class="pk"><input type="checkbox" class="toggle" title="Toggle all" /></th>
  572. {% endif %}
  573. <th>Name</th>
  574. <th colspan="2">Connection</th>
  575. <th></th>
  576. </tr>
  577. </thead>
  578. <tbody>
  579. {% for po in power_outlets %}
  580. {% include 'dcim/inc/poweroutlet.html' %}
  581. {% empty %}
  582. <tr>
  583. <td colspan="5" class="text-center text-muted">&mdash; No power outlets defined &mdash;</td>
  584. </tr>
  585. {% endfor %}
  586. </tbody>
  587. </table>
  588. <div class="panel-footer">
  589. {% if power_outlets and perms.dcim.change_powerport %}
  590. <button type="submit" name="_rename" formaction="{% url 'dcim:poweroutlet_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-xs">
  591. <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Rename
  592. </button>
  593. <button type="submit" name="_disconnect" formaction="{% url 'dcim:poweroutlet_bulk_disconnect' pk=device.pk %}" class="btn btn-danger btn-xs">
  594. <span class="glyphicon glyphicon-resize-full" aria-hidden="true"></span> Disconnect
  595. </button>
  596. {% endif %}
  597. {% if power_outlets and perms.dcim.delete_poweroutlet %}
  598. <button type="submit" class="btn btn-danger btn-xs">
  599. <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
  600. </button>
  601. {% endif %}
  602. {% if perms.dcim.add_poweroutlet %}
  603. <div class="pull-right">
  604. <a href="{% url 'dcim:poweroutlet_add' pk=device.pk %}" class="btn btn-primary btn-xs">
  605. <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add power outlets
  606. </a>
  607. </div>
  608. <div class="clearfix"></div>
  609. {% endif %}
  610. </div>
  611. </div>
  612. {% if perms.dcim.delete_poweroutlet %}
  613. </form>
  614. {% endif %}
  615. {% endif %}
  616. </div>
  617. </div>
  618. {% include 'inc/graphs_modal.html' %}
  619. {% include 'secrets/inc/private_key_modal.html' %}
  620. {% endblock %}
  621. {% block javascript %}
  622. <script type="text/javascript">
  623. function toggleConnection(elem, api_url) {
  624. var url = netbox_api_path + api_url + elem.attr('data') + "/";
  625. if (elem.hasClass('connected')) {
  626. $.ajax({
  627. url: url,
  628. method: 'PATCH',
  629. dataType: 'json',
  630. beforeSend: function(xhr, settings) {
  631. xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
  632. },
  633. data: {
  634. 'connection_status': 'False'
  635. },
  636. context: this,
  637. success: function() {
  638. elem.parents('tr').removeClass('success').addClass('info');
  639. elem.removeClass('connected btn-warning').addClass('btn-success');
  640. elem.attr('title', 'Mark installed');
  641. elem.children('i').removeClass('glyphicon glyphicon-ban-circle').addClass('fa fa-plug')
  642. }
  643. });
  644. } else {
  645. $.ajax({
  646. url: url,
  647. method: 'PATCH',
  648. dataType: 'json',
  649. beforeSend: function(xhr, settings) {
  650. xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
  651. },
  652. data: {
  653. 'connection_status': 'True'
  654. },
  655. context: this,
  656. success: function() {
  657. elem.parents('tr').removeClass('info').addClass('success');
  658. elem.removeClass('btn-success').addClass('connected btn-warning');
  659. elem.attr('title', 'Mark planned');
  660. elem.children('i').removeClass('fa fa-plug').addClass('glyphicon glyphicon-ban-circle')
  661. }
  662. });
  663. }
  664. return false;
  665. }
  666. $(".consoleport-toggle").click(function() {
  667. return toggleConnection($(this), "dcim/console-ports/");
  668. });
  669. $(".powerport-toggle").click(function() {
  670. return toggleConnection($(this), "dcim/power-ports/");
  671. });
  672. $(".interface-toggle").click(function() {
  673. return toggleConnection($(this), "dcim/interface-connections/");
  674. });
  675. // Toggle the display of IP addresses under interfaces
  676. $('button.toggle-ips').click(function() {
  677. var selected = $(this).attr('selected');
  678. if (selected) {
  679. $('#interfaces_table tr.ipaddress').hide();
  680. } else {
  681. $('#interfaces_table tr.ipaddress').show();
  682. }
  683. $(this).attr('selected', !selected);
  684. $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked');
  685. return false;
  686. });
  687. </script>
  688. <script src="{% static 'js/graphs.js' %}?v{{ settings.VERSION }}"></script>
  689. <script src="{% static 'js/secrets.js' %}?v{{ settings.VERSION }}"></script>
  690. {% endblock %}