index.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. <?php
  2. //-
  3. // Copyright (c) 2011-2017 Joe Clarke <jclarke@cisco.com>
  4. // All rights reserved.
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions
  7. // are met:
  8. // 1. Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // 2. Redistributions in binary form must reproduce the above copyright
  11. // notice, this list of conditions and the following disclaimer in the
  12. // documentation and/or other materials provided with the distribution.
  13. // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23. // SUCH DAMAGE.
  24. include_once 'db.inc.php';
  25. include_once 'swreg/swreg.inc.php';
  26. require_once 'Log.php';
  27. require_once 'functions.php';
  28. $dsn = "$db_driver:host=$db_host;dbname=$db_name";
  29. $options = [
  30. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  31. PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  32. PDO::ATTR_EMULATE_PREPARES => false,
  33. ];
  34. try {
  35. $dbh = new PDO($dsn, $db_user, $db_pass, $options);
  36. } catch (PDOException $e) {
  37. die($e->getMessage());
  38. }
  39. $logger = Log::singleton('file', LOGFILE, TOOL_NAME.' : Physical Switches');
  40. if ($logger === false) {
  41. die("Failed to open logfile.\n");
  42. }
  43. $mask = Log::UPTO(LOG_LEVEL);
  44. $logger->setMask($mask);
  45. $base = get_base($_SERVER['SCRIPT_NAME']);
  46. $ruser = '<AUTHENTICATION NOT ENABLED>';
  47. if (isset($_SERVER['REMOTE_USER'])) {
  48. $ruser = $_SERVER['REMOTE_USER'];
  49. }
  50. $errors = array();
  51. if (isset($_REQUEST['prev_checked'])) {
  52. $pc = $_REQUEST['prev_checked'];
  53. $pas = $_REQUEST['prev_assigned_switch'];
  54. $c = (isset($_REQUEST['checked'])) ? $_REQUEST['checked'] : array();
  55. $as = $_REQUEST['assigned_switch'];
  56. $d = (isset($_REQUEST['delete'])) ? $_REQUEST['delete'] : array();
  57. $rz = (isset($_REQUEST['reztp'])) ? $_REQUEST['reztp'] : array();
  58. foreach ($pc as $swsn => $value) {
  59. $curr_del = (isset($d[$swsn])) ? $d[$swsn] : 0;
  60. $curr_rz = (isset($rz[$swsn])) ? $rz[$swsn] : 0;
  61. if ($curr_del == 1) {
  62. $sql = "DELETE FROM DEVICE_MAP WHERE serial_number=:sn";
  63. try {
  64. $sth = $dbh->prepare($sql);
  65. $sth->execute(['sn' => $swsn]);
  66. $sth->closeCursor();
  67. $logger->info("User {$ruser} deleted physical switch {$swsn}");
  68. } catch (PDOException $e) {
  69. array_push($errors, "Failed to delete switch {$swsn}: {$e->getMessage()}");
  70. }
  71. continue;
  72. }
  73. if ($curr_rz == 1) {
  74. $sql = "UPDATE DEVICE_MAP SET should_re_ztp=:rz WHERE serial_number=:sn";
  75. try {
  76. $sth = $dbh->prepare($sql);
  77. $sth->execute(['sn' => $swsn, 'rz' => 2]);
  78. $sth->closeCursor();
  79. $logger->info("User {$ruser} set physical switch {$swsn} to re-ZTP");
  80. } catch (PDOException $e) {
  81. array_push($errors, "Failed to set switch {$swsn} to re-ZTP: {$e->getMessage()}");
  82. }
  83. }
  84. $curr_checked = (isset($c[$swsn])) ? $c[$swsn] : 0;
  85. if ($value != $curr_checked || $pas[$swsn] != $as[$swsn]) {
  86. $nc = $curr_checked;
  87. $additional = '';
  88. if ($nc == 1 && $as == '__BOGUS__') {
  89. array_push($errors, "You must select a logical switch assignment for $swsn");
  90. } else {
  91. if ($nc == 0 || $as == '__BOGUS__') {
  92. $nas = 'NULL';
  93. $additional = ", provisioned_status = '".PROVISION_UNKNOWN."', device_status = '".REACHABILITY_NEVER_REACHABLE."'";
  94. } else {
  95. $nas = "'{$as[$swsn]}'";
  96. }
  97. $sql = "UPDATE DEVICE_MAP SET checked_out='{$nc}', assigned_switch = {$nas} {$additional} WHERE serial_number='{$swsn}'";
  98. try {
  99. $dbh->query($sql);
  100. $logger->info("User {$ruser} updated physical switches, checked_out={$nc}, assigned_switch={$nas} for serial_number={$swsn}");
  101. } catch (PDOException $e) {
  102. array_push($errors, "Failed to update $swsn: '{$e->getMessage()}'");
  103. }
  104. }
  105. }
  106. }
  107. }
  108. $wc = '';
  109. if (isset($_REQUEST['filter'])) {
  110. switch ($_REQUEST['filter']) {
  111. case 'a':
  112. $wc = '';
  113. break;
  114. case 'p':
  115. $wc = 'WHERE assigned_switch IS NOT NULL';
  116. break;
  117. case 'up':
  118. $wc = 'WHERE assigned_switch IS NULL';
  119. break;
  120. case 'vu':
  121. $wc = 'WHERE provisioned_status=\''.PROVISION_UNKNOWN.'\'';
  122. break;
  123. case 'vi':
  124. $wc = 'WHERE provisioned_status=\''.PROVISION_IN_PROGRESS.'\'';
  125. break;
  126. case 'vf':
  127. $wc = 'WHERE provisioned_status=\''.PROVISION_FAIL.'\'';
  128. break;
  129. case 'vs':
  130. $wc = 'WHERE provisioned_status=\''.PROVISION_SUCCESS.'\'';
  131. break;
  132. case 'r':
  133. $wc = 'WHERE device_status=\''.REACHABILITY_REACHABLE.'\'';
  134. break;
  135. case 'ur':
  136. $wc = 'WHERE provisioned_status=\''.PROVISION_SUCCESS.'\' AND (device_status=\''.REACHABILITY_NEVER_REACHABLE.'\' OR device_status=\''.REACHABILITY_NOW_UNREACHABLE.'\')';
  137. break;
  138. default:
  139. if (preg_match("/^pid:([\w\d-]+)/", $_REQUEST['filter'], $match)) {
  140. $wc = "WHERE pid = '{$match[1]}'";
  141. } else {
  142. $wc = '';
  143. }
  144. break;
  145. }
  146. }
  147. $res = null;
  148. if (isset($_REQUEST['switch_name'])) {
  149. $sql = "SELECT * FROM DEVICE_MAP WHERE serial_number LIKE :swname1 OR assigned_switch LIKE :swname2 ORDER BY LPAD(lower(serial_number), 10, 0)";
  150. try {
  151. $res = $dbh->prepare($sql);
  152. $res->execute(['swname1' => "%{$_REQUEST['switch_name']}%", 'swname2' => "%{$_REQUEST['switch_name']}%"]);
  153. } catch (PDOException $e) {
  154. echo "<p><font color=\"red\">Error querying for physical switches: {$e->getMessage()}</font></p>\r\n";
  155. exit(1);
  156. }
  157. } else {
  158. $sql = 'SELECT * FROM DEVICE_MAP '.$wc.' ORDER BY LPAD(lower(serial_number), 10, 0)';
  159. try {
  160. $res = $dbh->query($sql);
  161. } catch (PDOException $e) {
  162. echo "<p><font color=\"red\">Error querying for physical switches: {$e->getMessage()}</font></p>\r\n";
  163. exit(1);
  164. }
  165. }
  166. $sql = 'SELECT name, pid FROM SWITCHES WHERE ip_address IS NOT NULL ORDER BY name';
  167. $ls_res = null;
  168. try {
  169. $ls_res = $dbh->query($sql);
  170. } catch (PDOException $e) {
  171. echo "<p><font color=\"red\">Error querying for logical switches: {$e->getMessage()}</font></p>\r\n";
  172. exit(1);
  173. }
  174. $lswitches = array();
  175. while ($row = $ls_res->fetch()) {
  176. if (!isset($lswitches[$row['pid']])) {
  177. $lswitches[$row['pid']] = array('__BOGUS__', $row['name']);
  178. } else {
  179. array_push($lswitches[$row['pid']], $row['name']);
  180. }
  181. }
  182. $switches = array();
  183. while ($row = $res->fetch()) {
  184. array_push($switches, $row);
  185. }
  186. $sql = 'SELECT DISTINCT(pid) AS pid FROM DEVICE_MAP';
  187. try {
  188. $res = $dbh->query($sql);
  189. } catch (PDOException $e) {
  190. echo "<p><font color=\"red\">Error querying for PIDs: {$e->getMessage()}</font></p>\r\n";
  191. exit(1);
  192. }
  193. $pids = array();
  194. while ($row = $res->fetch()) {
  195. $pids[$row['pid']] = true;
  196. }
  197. $sql = 'SELECT assigned_switch FROM DEVICE_MAP WHERE assigned_switch IS NOT NULL';
  198. try {
  199. $res = $dbh->query($sql);
  200. } catch (PDOException $e) {
  201. echo "<p><font color=\"red\">Error querying for assigned switches: {$e->getMessage()}</font></p>\r\n";
  202. exit(1);
  203. }
  204. $used = array();
  205. while ($row = $res->fetch()) {
  206. $used[$row['assigned_switch']] = true;
  207. }
  208. $filt = null;
  209. if (!isset($_REQUEST['filter'])) {
  210. $filt = '';
  211. } else {
  212. $filt = $_REQUEST['filter'];
  213. }
  214. print_header(TOOL_NAME.': Physical Switches');
  215. ?>
  216. <body class="flex">
  217. <script language="javascript">
  218. var deletes = 0;
  219. var PROVISION_UNKNOWN = <?=PROVISION_UNKNOWN?>;
  220. var PROVISION_IN_PROGRESS = <?=PROVISION_IN_PROGRESS?>;
  221. var PROVISION_FAIL = <?=PROVISION_FAIL?>;
  222. var PROVISION_SUCCESS = <?=PROVISION_SUCCESS?>;
  223. var REACHABILITY_NEVER_REACHABLE = <?=REACHABILITY_NEVER_REACHABLE?>;
  224. var REACHABILITY_NOW_UNREACHABLE = <?=REACHABILITY_NOW_UNREACHABLE?>;
  225. var REACHABILITY_REACHABLE = <?=REACHABILITY_REACHABLE?>;
  226. var row_intervals = {};
  227. function refresh() {
  228. $.ajax({
  229. url: '<?=$base?>/get_dev_stats.php',
  230. dataType: 'json',
  231. success: function(data) {
  232. $.each(data.response, function(k, v) {
  233. var rtext = '&nbsp;';
  234. var color = '#FFFFFF';
  235. var rtitle = 'Not yet assigned';
  236. var prs = v.provisioned_status;
  237. var ds = v.device_status;
  238. if (prs == PROVISION_SUCCESS) {
  239. color = '#00FF00';
  240. rtitle = 'Bootstrap validated successfully';
  241. rtext += '&nbsp;&nbsp;&nbsp;';
  242. } else if (prs == PROVISION_UNKNOWN || prs == PROVISION_IN_PROGRESS) {
  243. color = '#919191';
  244. rtitle = 'Not yet bootstrapped';
  245. if (prs == PROVISION_IN_PROGRESS) {
  246. rtitle = 'Bootstrapping in progress';
  247. rtext += '&nbsp;';
  248. }
  249. } else {
  250. color = '#FF0000';
  251. rtitle = 'Bootstrap validation failed';
  252. rtext += '&nbsp;&nbsp;';
  253. }
  254. rtext += '<input type="hidden" id="pros' + k + '" value="' + prs + '">';
  255. if (prs != PROVISION_IN_PROGRESS) {
  256. if ('undefined' !== typeof row_intervals[k]) {
  257. $('#psr_' + k).stop(true, true);
  258. clearInterval(row_intervals[k]);
  259. $('#psr_' + k).stop(true, true);
  260. }
  261. }
  262. $('#psr_' + k).css('background', color);
  263. $('#psr_' + k).html('<span style="display: none">' + prs + '</span>' + rtext);
  264. $('#psr_' + k).attr('title', rtitle);
  265. if (prs == PROVISION_IN_PROGRESS) {
  266. if ('undefined' !== typeof row_intervals[k]) {
  267. clearInterval(row_intervals[k]);
  268. $('#psr_' + k).stop(true, true);
  269. }
  270. var pulseint = setInterval(function() {
  271. $('#psr_' + k).animate({
  272. backgroundColor: '#919191',
  273. }, 1000).animate({
  274. backgroundColor: '#f5f5f5',
  275. }, 1000);
  276. }, 1500);
  277. row_intervals[k] = pulseint;
  278. }
  279. color = '#FFFFFF';
  280. rtext = '&nbsp;';
  281. rtitle = 'Not yet assigned';
  282. if (ds == REACHABILITY_NEVER_REACHABLE && prs == PROVISION_SUCCESS) {
  283. color = '#FF0000';
  284. rtitle = 'Device was never reachable';
  285. } else if (ds == REACHABILITY_NEVER_REACHABLE) {
  286. color = '#919191';
  287. rtitle = 'Not yet bootstrapped';
  288. rtext += '&nbsp;';
  289. } else if (ds == REACHABILITY_NOW_UNREACHABLE) {
  290. color = '#FFFF00';
  291. rtitle = 'Device has been reachable, but is not reachable now';
  292. rtext += '&nbsp;&nbsp;';
  293. } else {
  294. color = '#00FF00';
  295. rtitle = 'Device is reachable';
  296. rtext += '&nbsp;&nbsp;&nbsp;';
  297. }
  298. $('#dsr_' + k).css('background', color);
  299. $('#dsr_' + k).html('<span style="display: none">' + ds + '</span>' + rtext);
  300. $('#dsr_' + k).attr('title', rtitle);
  301. });
  302. },
  303. complete: function(xhr, message) {
  304. setTimeout(refresh, 30000);
  305. }
  306. });
  307. }
  308. function reztp_all() {
  309. if ($('#reztp_all_box').is(':checked')) {
  310. $('.reztp').each(function() {
  311. $(this).prop('checked', true);
  312. });
  313. } else {
  314. $('.reztp').each(function() {
  315. $(this).prop('checked', false);
  316. });
  317. }
  318. return true;
  319. }
  320. function toggle_reztp_all(elem) {
  321. if (!$(elem).is(':checked')) {
  322. $('#reztp_all_box').prop('checked', false);
  323. }
  324. }
  325. function check_confirm() {
  326. var delete_conf = true;
  327. var reztp_conf = true;
  328. if (deletes > 0) {
  329. delete_conf = confirm("Are you sure you want to delete these " + deletes + " physical switch(es)?");
  330. }
  331. $('.reztp').each(function() {
  332. if ($(this).is(':checked')) {
  333. one_checked = true;
  334. return;
  335. }
  336. });
  337. if (one_checked) {
  338. reztp_conf = confirm("Are you sure you want to re-ZTP these switches?");
  339. }
  340. return reztp_conf && delete_conf;
  341. }
  342. if ( window.history.replaceState ) {
  343. window.history.replaceState( null, null, window.location.href );
  344. }
  345. $(document).ready(function() {
  346. $('#devtable').DataTable({
  347. "scrollY": "400px",
  348. "scrollCollapse": true,
  349. "paging": false
  350. });
  351. refresh();
  352. });
  353. </script>
  354. <div id="headswreg">
  355. <div class="apage">
  356. <div id="header">
  357. <h1><?=TOOL_NAME?>: Physical Switches</h1>
  358. </div>
  359. <br/>
  360. </div>
  361. </div>
  362. <div class="apage">
  363. <form method="POST" name="search_form" action="<?=$_SERVER['PHP_SELF']?>">
  364. <table class="noborder" summary="Filter Table">
  365. <tr>
  366. <td class="left_act">Show Only:
  367. <select name="filter" onChange="MM_jumpMenu('parent', this, 0)">
  368. <option value="<?=$_SERVER['PHP_SELF']?>?filter=a" <?=($filt == 'a') ? 'selected' : ''?>>All</option>
  369. <option value="<?=$_SERVER['PHP_SELF']?>?filter=p" <?=($filt == 'p') ? 'selected' : ''?>>Assigned</option>
  370. <option value="<?=$_SERVER['PHP_SELF']?>?filter=up" <?=($filt == 'up') ? 'selected' : ''?>>Unassigned</option>
  371. <option value="<?=$_SERVER['PHP_SELF']?>?filter=vu" <?=($filt == 'vu') ? 'selected' : ''?>>Not Yet Bootstrapped</option>
  372. <option value="<?=$_SERVER['PHP_SELF']?>?filter=vi" <?=($filt == 'vi') ? 'selected' : ''?>>Bootstrapping In Progress</option>
  373. <option value="<?=$_SERVER['PHP_SELF']?>?filter=vf" <?=($filt == 'vf') ? 'selected' : ''?>>Verification Failed</option>
  374. <option value="<?=$_SERVER['PHP_SELF']?>?filter=vs" <?=($filt == 'vs') ? 'selected' : ''?>>Verification Succeeded</option>
  375. <option value="<?=$_SERVER['PHP_SELF']?>?filter=r" <?=($filt == 'r') ? 'selected' : ''?>>Reachable</option>
  376. <option value="<?=$_SERVER['PHP_SELF']?>?filter=ur" <?=($filt == 'ur') ? 'selected' : ''?>>Unreachable</option>
  377. <?php
  378. foreach ($pids as $lsp => $value) {
  379. $selected = ($filt == "pid:$lsp") ? 'selected' : ''; ?>
  380. <option value="<?=$_SERVER['PHP_SELF']?>?filter=pid:<?=$lsp?>" <?=$selected?>><?=$lsp?></option>
  381. <?php
  382. }
  383. ?>
  384. </select></td>
  385. <td class="right">Switch Search:
  386. <input type="text" size="16" name="switch_name" value="<?=(isset($_REQUEST['switch_name'])) ? $_REQUEST['switch_name'] : ''?>">
  387. <input type="image" value="Submit" name="search" src="/images/submit_button.png">
  388. </td>
  389. </tr>
  390. </table>
  391. </form>
  392. <br/>
  393. <table class="noborder" summary="Control Table">
  394. <tr>
  395. <td class="left"><a href="<?=$base?>/add_phys.php">Add Physical Switch</a> |
  396. <?php
  397. if (EXPORT_PRIME === true) {
  398. ?>
  399. <a href="#" onClick="window.open('<?=$base?>/export.php')">Export to Prime / DNS</a> |
  400. <?php
  401. }
  402. if (EXPORT_DEADMAN === true) {
  403. ?>
  404. <a href="#" onClick="window.open('<?=$base?>/export_deadman.php')">Export To Ansible</a> |
  405. <?php
  406. } ?>
  407. <a href="<?=$base?>/logicsw.php">Logical Switches</a></td>
  408. </tr>
  409. </table>
  410. <form name="mod_phys_switch_form" method="POST" action="<?=$_SERVER['PHP_SELF']?>" onSubmit='return check_confirm();'>
  411. <?php
  412. foreach (array_merge($_GET, $_POST) as $name => $value) {
  413. if (!is_array($value)) {
  414. ?>
  415. <input type="hidden" name="<?=$name?>" value="<?=$value?>">
  416. <?php
  417. }
  418. }
  419. ?>
  420. <div class="btable">
  421. <table summary="Button Table" width="100%" cellspacing="0">
  422. <tr>
  423. <td><input type="reset" value="Reset" name="reset">
  424. <input type="submit" value="Submit" name="submit"></td>
  425. </tr>
  426. </table>
  427. </div>
  428. <br/>
  429. <div align="center">
  430. <?php
  431. foreach ($errors as $error) {
  432. ?>
  433. <p class="error"><?=$error?></p>
  434. <?php
  435. }
  436. ?>
  437. </div>
  438. <div class="maintable">
  439. <table id="devtable" class="cell-border compact" width="100%" cellspacing="0" summary="Physical Switch Table">
  440. <thead>
  441. <tr>
  442. <th class="headlink">Row No.</th>
  443. <th class="headlink">Delete?</th>
  444. <th class="headlink">Assigned?</th>
  445. <th class="headlink">Re-ZTP? <input type="checkbox" id="reztp_all_box" onchange="return reztp_all();"></th>
  446. <th class="headlink">Serial Number</th>
  447. <th class="headlink">Product ID</th>
  448. <th class="headlink">Max Ports</th>
  449. <th class="headlink">Assigned Logical<br/>Switch</th>
  450. <th class="headlink">Provision<br/>Status</th>
  451. <th class="headlink">Reachability</th>
  452. </tr>
  453. </thead>
  454. <tbody>
  455. <?php
  456. $i = 0;
  457. foreach ($switches as $row) {
  458. $sn = $row['serial_number'];
  459. $checked = false;
  460. $will_rz = false;
  461. if ($row['checked_out'] == 1) {
  462. $checked = true;
  463. }
  464. if ($row['should_re_ztp'] > 0) {
  465. $will_rz = true;
  466. } ?>
  467. <tr>
  468. <td><?=$i + 1?>.</td>
  469. <td><input type="checkbox" name="delete[<?=$sn?>]" value="1" onClick="if (this.checked == true) { deletes++; } else { deletes--; }"></td>
  470. <td><input type="hidden" name="prev_checked[<?=$sn?>]" value="<?=$row['checked_out']?>">
  471. <input id="checked_<?=$i?>" type="checkbox" name="checked[<?=$sn?>]" value="1" <?=($checked) ? 'checked' : ''?>></td>
  472. <td><input id="reztp_<?=$i?>" class="reztp" type="checkbox" name="reztp[<?=$sn?>]" value="1" onchange="toggle_reztp_all(this);" <?=($will_rz) ? 'disabled' : ''?>></td>
  473. <td><?=$row['serial_number']?></td>
  474. <td><?=$row['pid']?></td>
  475. <td><?=$row['max_ports']?></td>
  476. <td><input type="hidden" name="prev_assigned_switch[<?=$sn?>]" value="<?=$row['assigned_switch']?>">
  477. <select id="asw<?=$i?>" name="assigned_switch[<?=$sn?>]" onChange='var elem = document.getElementById("checked_<?=$i?>"); if (this.value == "__BOGUS__") { elem.checked = false; } else { elem.checked = true; }'>
  478. <?php
  479. $has_avail = false;
  480. foreach ($lswitches[$row['pid']] as $lsw) {
  481. $selected = ($row['assigned_switch'] == $lsw) ? 'selected' : '';
  482. if ($selected == '' && isset($used[$lsw]) && $used[$lsw] === true) {
  483. continue;
  484. }
  485. if ($lsw == '__BOGUS__') {
  486. ?>
  487. <option value="__BOGUS__" <?=$selected?>>--Please Select--</option>
  488. <?php
  489. } else {
  490. $has_avail = true; ?>
  491. <option value="<?=$lsw?>" <?=$selected?>><?=$lsw?></option>
  492. <?php
  493. }
  494. }
  495. if (!$has_avail) {
  496. ?>
  497. <option value="__BOGUS__" <?=$selected?>>--Please Select--</option>
  498. <?php
  499. } ?>
  500. </select>
  501. &nbsp;<a href="#" onClick='var lsw = document.getElementById("asw<?=$i?>"); if (lsw.value == "__BOGUS__") { alert("There is no logical switch associated to this device."); return false; } else { window.open("<?=$base?>/logicsw.php?switch_name=" + lsw.value, "Logical switch " + lsw.value, "height=480,width=1048"); return false; }'><img src="/images/switch.gif" border="0" title="View logical switch"></a>&nbsp;<a href="#" onClick='var pros = document.getElementById("pros<?=$row['serial_number']?>"); var lsw = document.getElementById("asw<?=$i?>"); if (pros.value < PROVISION_FAIL) { alert("This switch config has not yet been generated."); return false; } else { window.open("<?=$base?>/show_config.php?cfg=" + lsw.value + "-config.txt&dname=" + lsw.value, "Config for switch " + lsw.value, "height=650,width=980"); return false; }'><img src="/images/mag.gif" border="0" title="View switch config"></a>
  502. </td>
  503. <?php
  504. $color = '#FFFFFF';
  505. $rtext = 'N/A';
  506. $rtitle = 'Not yet assigned'; ?>
  507. <td id="psr_<?=$row['serial_number']?>" style="background: <?=$color?>;" title="<?=$rtitle?>"><input type="hidden" id="pros<?=$row['serial_number']?>" value="<?=$row['provisioned_status']?>"><span style="display: none"><?=$row['provisioned_status']?></span><?=$rtext?></td>
  508. <?php
  509. $color = '#FFFFFF';
  510. $rtext = 'N/A';
  511. $rtitle = 'Not yet assigned'; ?>
  512. <td id="dsr_<?=$row['serial_number']?>" style="background: <?=$color?>;" title="<?=$rtitle?>"><span style="display: none"><?=$row['device_status']?></span><?=$rtext?></td>
  513. </tr>
  514. <?php
  515. ++$i;
  516. }
  517. ?>
  518. </tbody>
  519. </table>
  520. </div>
  521. <br/>
  522. <div class="btable">
  523. <table summary="Button Table" width="100%" cellspacing="0">
  524. <tr>
  525. <td><input type="reset" value="Reset" name="reset">
  526. <input type="submit" value="Submit" name="submit"></td>
  527. </tr>
  528. </table>
  529. </div>
  530. </form>
  531. </div>
  532. </body>
  533. </html>
  534. <?php
  535. cleanup();
  536. ?>